blob: 60a5bce542fe425031117cd1517af90b5990b1d9 [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:
359 * @ctxt: a schema validation context (optional)
360 *
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:
405 * @ctxt: a schema validation context (optional)
406 * @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 ************************************************************************/
904/**
905 * numberedString:
906 * @prefix: the string prefix
907 * @number: the number
908 *
909 * Build a new numbered string
910 *
911 * Returns the new string
912 */
913
914/**
915 * xmlSchemaGetProp:
916 * @ctxt: the parser context
917 * @node: the node
918 * @name: the property name
919 *
920 * Read a attribute value and internalize the string
921 *
922 * Returns the string or NULL if not present.
923 */
924static const xmlChar *
925xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
926 const char *name)
927{
928 xmlChar *val;
929 const xmlChar *ret;
930
931 val = xmlGetProp(node, BAD_CAST name);
932 if (val == NULL)
933 return(NULL);
934 ret = xmlDictLookup(ctxt->dict, val, -1);
935 xmlFree(val);
936 return(ret);
937}
938
939/**
940 * xmlSchemaGetNamespace:
941 * @ctxt: the parser context
942 * @schema: the schemas containing the declaration
943 * @node: the node
944 * @qname: the QName to analyze
945 *
946 * Find the namespace name for the given declaration.
947 *
948 * Returns the local name for that declaration, as well as the namespace name
949 */
950static const xmlChar *
951xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
952 xmlNodePtr node, const xmlChar *qname,
953 const xmlChar **namespace) {
954 int len;
955 const xmlChar *name, *prefix, *def = NULL;
956 xmlNsPtr ns;
957
958 *namespace = NULL;
959
960 if (xmlStrEqual(node->name, BAD_CAST "element") ||
961 xmlStrEqual(node->name, BAD_CAST "attribute") ||
962 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
963 xmlStrEqual(node->name, BAD_CAST "complexType")) {
964 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
965 }
966
967 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
968 name = xmlSplitQName3(qname, &len);
969 if (name == NULL) {
970 if (def == NULL) {
971 if (xmlStrEqual(node->name, BAD_CAST "element")) {
972 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
973 *namespace = schema->targetNamespace;
974 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
975 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
976 *namespace = schema->targetNamespace;
977 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
978 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
979 *namespace = schema->targetNamespace;
980 }
981 } else {
982 *namespace = def;
983 }
984 return(qname);
985 }
986 name = xmlDictLookup(ctxt->dict, name, -1);
987 prefix = xmlDictLookup(ctxt->dict, qname, len);
988 if (def != NULL) {
989 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
990 "%s: presence of both prefix %s and targetNamespace\n",
991 node->name, prefix);
992 }
993 ns = xmlSearchNs(node->doc, node, prefix);
994 if (ns == NULL) {
995 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
996 "%s: the QName prefix %s is undefined\n",
997 node->name, prefix);
998 return(name);
999 }
1000 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1001 return(name);
1002}
1003
1004/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001005 * *
1006 * Parsing functions *
1007 * *
1008 ************************************************************************/
1009
1010/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001011 * xmlSchemaGetElem:
1012 * @schema: the schemas context
1013 * @name: the element name
1014 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001015 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001016 *
1017 * Lookup a an element in the schemas or the accessible schemas
1018 *
1019 * Returns the element definition or NULL if not found.
1020 */
1021static xmlSchemaElementPtr
1022xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001023 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001024{
1025 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001026 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001027
1028 if ((name == NULL) || (schema == NULL))
1029 return (NULL);
1030
1031 if (namespace == NULL) {
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 if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1038 if (xmlStrEqual(namespace, schema->targetNamespace))
1039 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1040 else
1041 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001042 if ((ret != NULL) &&
1043 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001044 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001045 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001046 } else {
1047 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001048 if ((ret != NULL) &&
1049 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001050 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001051 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001052 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001053 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001054 import = xmlHashLookup(schema->schemasImports, namespace);
1055 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001056 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001057#ifdef DEBUG
1058 if (ret == NULL) {
1059 if (namespace == NULL)
1060 fprintf(stderr, "Unable to lookup type %s", name);
1061 else
1062 fprintf(stderr, "Unable to lookup type %s:%s", name,
1063 namespace);
1064 }
1065#endif
1066 return (ret);
1067}
1068
1069/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001070 * xmlSchemaGetType:
1071 * @schema: the schemas context
1072 * @name: the type name
1073 * @ns: the type namespace
1074 *
1075 * Lookup a type in the schemas or the predefined types
1076 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001077 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001078 */
1079static xmlSchemaTypePtr
1080xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001081 const xmlChar * namespace)
1082{
Daniel Veillard4255d502002-04-16 15:50:10 +00001083 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001084 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001085
1086 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001087 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001088 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001089 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1090 if (ret != NULL)
1091 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001092 }
1093 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001094 if (ret != NULL)
1095 return (ret);
1096 import = xmlHashLookup(schema->schemasImports, namespace);
1097 if (import != NULL)
1098 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001099#ifdef DEBUG
1100 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001101 if (namespace == NULL)
1102 fprintf(stderr, "Unable to lookup type %s", name);
1103 else
1104 fprintf(stderr, "Unable to lookup type %s:%s", name,
1105 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001106 }
1107#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001108 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001109}
1110
1111/************************************************************************
1112 * *
1113 * Parsing functions *
1114 * *
1115 ************************************************************************/
1116
1117#define IS_BLANK_NODE(n) \
1118 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1119
1120/**
1121 * xmlSchemaIsBlank:
1122 * @str: a string
1123 *
1124 * Check if a string is ignorable
1125 *
1126 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1127 */
1128static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001129xmlSchemaIsBlank(xmlChar * str)
1130{
Daniel Veillard4255d502002-04-16 15:50:10 +00001131 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001132 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001133 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001134 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001135 return (0);
1136 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001137 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001138 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001139}
1140
1141/**
1142 * xmlSchemaAddNotation:
1143 * @ctxt: a schema validation context
1144 * @schema: the schema being built
1145 * @name: the item name
1146 *
1147 * Add an XML schema Attrribute declaration
1148 * *WARNING* this interface is highly subject to change
1149 *
1150 * Returns the new struture or NULL in case of error
1151 */
1152static xmlSchemaNotationPtr
1153xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001154 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001155{
1156 xmlSchemaNotationPtr ret = NULL;
1157 int val;
1158
1159 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1160 return (NULL);
1161
1162 if (schema->notaDecl == NULL)
1163 schema->notaDecl = xmlHashCreate(10);
1164 if (schema->notaDecl == NULL)
1165 return (NULL);
1166
1167 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1168 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001169 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001170 return (NULL);
1171 }
1172 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001173 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001174 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1175 ret);
1176 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001177 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1178 XML_SCHEMAP_REDEFINED_NOTATION,
1179 "Notation %s already defined\n",
1180 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001181 xmlFree(ret);
1182 return (NULL);
1183 }
1184 return (ret);
1185}
1186
1187
1188/**
1189 * xmlSchemaAddAttribute:
1190 * @ctxt: a schema validation context
1191 * @schema: the schema being built
1192 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001193 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001194 *
1195 * Add an XML schema Attrribute declaration
1196 * *WARNING* this interface is highly subject to change
1197 *
1198 * Returns the new struture or NULL in case of error
1199 */
1200static xmlSchemaAttributePtr
1201xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001202 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001203{
1204 xmlSchemaAttributePtr ret = NULL;
1205 int val;
1206
1207 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1208 return (NULL);
1209
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001210#ifdef DEBUG
1211 fprintf(stderr, "Adding attribute %s\n", name);
1212 if (namespace != NULL)
1213 fprintf(stderr, " target namespace %s\n", namespace);
1214#endif
1215
Daniel Veillard4255d502002-04-16 15:50:10 +00001216 if (schema->attrDecl == NULL)
1217 schema->attrDecl = xmlHashCreate(10);
1218 if (schema->attrDecl == NULL)
1219 return (NULL);
1220
1221 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1222 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001223 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001224 return (NULL);
1225 }
1226 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001227 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1228 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001229 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001230 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001231 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001232 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1233 XML_SCHEMAP_REDEFINED_ATTR,
1234 "Attribute %s already defined\n",
1235 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001236 xmlFree(ret);
1237 return (NULL);
1238 }
1239 return (ret);
1240}
1241
1242/**
1243 * xmlSchemaAddAttributeGroup:
1244 * @ctxt: a schema validation context
1245 * @schema: the schema being built
1246 * @name: the item name
1247 *
1248 * Add an XML schema Attrribute Group declaration
1249 *
1250 * Returns the new struture or NULL in case of error
1251 */
1252static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001253xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1254 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001255{
1256 xmlSchemaAttributeGroupPtr ret = NULL;
1257 int val;
1258
1259 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1260 return (NULL);
1261
1262 if (schema->attrgrpDecl == NULL)
1263 schema->attrgrpDecl = xmlHashCreate(10);
1264 if (schema->attrgrpDecl == NULL)
1265 return (NULL);
1266
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001267 ret =
1268 (xmlSchemaAttributeGroupPtr)
1269 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001270 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001271 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001272 return (NULL);
1273 }
1274 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001275 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001276 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001277 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001278 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001279 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1280 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1281 "Attribute group %s already defined\n",
1282 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001283 xmlFree(ret);
1284 return (NULL);
1285 }
1286 return (ret);
1287}
1288
1289/**
1290 * xmlSchemaAddElement:
1291 * @ctxt: a schema validation context
1292 * @schema: the schema being built
1293 * @name: the type name
1294 * @namespace: the type namespace
1295 *
1296 * Add an XML schema Element declaration
1297 * *WARNING* this interface is highly subject to change
1298 *
1299 * Returns the new struture or NULL in case of error
1300 */
1301static xmlSchemaElementPtr
1302xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1303 const xmlChar * name, const xmlChar * namespace)
1304{
1305 xmlSchemaElementPtr ret = NULL;
1306 int val;
1307
1308 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1309 return (NULL);
1310
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001311#ifdef DEBUG
1312 fprintf(stderr, "Adding element %s\n", name);
1313 if (namespace != NULL)
1314 fprintf(stderr, " target namespace %s\n", namespace);
1315#endif
1316
Daniel Veillard4255d502002-04-16 15:50:10 +00001317 if (schema->elemDecl == NULL)
1318 schema->elemDecl = xmlHashCreate(10);
1319 if (schema->elemDecl == NULL)
1320 return (NULL);
1321
1322 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1323 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001324 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001325 return (NULL);
1326 }
1327 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001328 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1329 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001330 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001331 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001332 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001333 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001334
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001335 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001336 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1337 namespace, ret);
1338 if (val != 0) {
1339 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1340 XML_SCHEMAP_REDEFINED_ELEMENT,
1341 "Element %s already defined\n",
1342 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001343 xmlFree(ret);
1344 return (NULL);
1345 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001346 }
1347 return (ret);
1348}
1349
1350/**
1351 * xmlSchemaAddType:
1352 * @ctxt: a schema validation context
1353 * @schema: the schema being built
1354 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001355 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001356 *
1357 * Add an XML schema Simple Type definition
1358 * *WARNING* this interface is highly subject to change
1359 *
1360 * Returns the new struture or NULL in case of error
1361 */
1362static xmlSchemaTypePtr
1363xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001364 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001365{
1366 xmlSchemaTypePtr ret = NULL;
1367 int val;
1368
1369 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1370 return (NULL);
1371
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001372#ifdef DEBUG
1373 fprintf(stderr, "Adding type %s\n", name);
1374 if (namespace != NULL)
1375 fprintf(stderr, " target namespace %s\n", namespace);
1376#endif
1377
Daniel Veillard4255d502002-04-16 15:50:10 +00001378 if (schema->typeDecl == NULL)
1379 schema->typeDecl = xmlHashCreate(10);
1380 if (schema->typeDecl == NULL)
1381 return (NULL);
1382
1383 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1384 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001385 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001386 return (NULL);
1387 }
1388 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001389 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001390 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001391 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001392 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001393 if (ctxt->includes == 0) {
1394 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1395 XML_SCHEMAP_REDEFINED_TYPE,
1396 "Type %s already defined\n",
1397 name, NULL);
1398 xmlFree(ret);
1399 return (NULL);
1400 } else {
1401 xmlSchemaTypePtr prev;
1402
1403 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1404 if (prev == NULL) {
1405 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1406 XML_ERR_INTERNAL_ERROR,
1407 "Internal error on type %s definition\n",
1408 name, NULL);
1409 xmlFree(ret);
1410 return (NULL);
1411 }
1412 ret->redef = prev->redef;
1413 prev->redef = ret;
1414 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001415 }
1416 ret->minOccurs = 1;
1417 ret->maxOccurs = 1;
1418
1419 return (ret);
1420}
1421
1422/**
1423 * xmlSchemaAddGroup:
1424 * @ctxt: a schema validation context
1425 * @schema: the schema being built
1426 * @name: the group name
1427 *
1428 * Add an XML schema Group definition
1429 *
1430 * Returns the new struture or NULL in case of error
1431 */
1432static xmlSchemaTypePtr
1433xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001434 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001435{
1436 xmlSchemaTypePtr ret = NULL;
1437 int val;
1438
1439 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1440 return (NULL);
1441
1442 if (schema->groupDecl == NULL)
1443 schema->groupDecl = xmlHashCreate(10);
1444 if (schema->groupDecl == NULL)
1445 return (NULL);
1446
1447 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1448 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001449 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001450 return (NULL);
1451 }
1452 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001453 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 val =
1455 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1456 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001457 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001458 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1459 XML_SCHEMAP_REDEFINED_GROUP,
1460 "Group %s already defined\n",
1461 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001462 xmlFree(ret);
1463 return (NULL);
1464 }
1465 ret->minOccurs = 1;
1466 ret->maxOccurs = 1;
1467
1468 return (ret);
1469}
1470
1471/************************************************************************
1472 * *
1473 * Utilities for parsing *
1474 * *
1475 ************************************************************************/
1476
1477/**
1478 * xmlGetQNameProp:
1479 * @ctxt: a schema validation context
1480 * @node: a subtree containing XML Schema informations
1481 * @name: the attribute name
1482 * @namespace: the result namespace if any
1483 *
1484 * Extract a QName Attribute value
1485 *
1486 * Returns the NCName or NULL if not found, and also update @namespace
1487 * with the namespace URI
1488 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001489static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001490xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001491 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001492{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001493 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001494 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001495 const xmlChar *ret, *prefix;
1496 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001497
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001498 *namespace = NULL;
1499 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001500 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001501 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001502
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001503 ret = xmlSplitQName3(val, &len);
1504 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001505 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001506 }
1507 ret = xmlDictLookup(ctxt->dict, ret, -1);
1508 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001509
1510 ns = xmlSearchNs(node->doc, node, prefix);
1511 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001512 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1513 "Attribute %s: the QName prefix %s is undefined\n",
1514 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001515 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001516 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001517 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001518 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001519}
1520
1521/**
1522 * xmlGetMaxOccurs:
1523 * @ctxt: a schema validation context
1524 * @node: a subtree containing XML Schema informations
1525 *
1526 * Get the maxOccurs property
1527 *
1528 * Returns the default if not found, or the value
1529 */
1530static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1532{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001533 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001534 int ret = 0;
1535
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001536 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001537 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001538 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001539
1540 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001541 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001542 }
1543
1544 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001545 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001546 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001547 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001548 ret = ret * 10 + (*cur - '0');
1549 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001550 }
William M. Brack76e95df2003-10-18 16:20:14 +00001551 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001553 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001554 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1555 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001556 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001557 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001558 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001559}
1560
1561/**
1562 * xmlGetMinOccurs:
1563 * @ctxt: a schema validation context
1564 * @node: a subtree containing XML Schema informations
1565 *
1566 * Get the minOccurs property
1567 *
1568 * Returns the default if not found, or the value
1569 */
1570static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001571xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1572{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001573 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001574 int ret = 0;
1575
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001576 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001577 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001579
1580 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001581 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001582 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001583 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 ret = ret * 10 + (*cur - '0');
1585 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001586 }
William M. Brack76e95df2003-10-18 16:20:14 +00001587 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001588 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001589 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001590 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1591 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001592 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001593 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001594 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001595}
1596
1597/**
1598 * xmlGetBooleanProp:
1599 * @ctxt: a schema validation context
1600 * @node: a subtree containing XML Schema informations
1601 * @name: the attribute name
1602 * @def: the default value
1603 *
1604 * Get is a bolean property is set
1605 *
1606 * Returns the default if not found, 0 if found to be false,
1607 * 1 if found to be true
1608 */
1609static int
1610xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001611 const char *name, int def)
1612{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001613 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001614
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001615 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001616 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001617 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001618
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001619 if (xmlStrEqual(val, BAD_CAST "true"))
1620 def = 1;
1621 else if (xmlStrEqual(val, BAD_CAST "false"))
1622 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001623 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001624 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1625 "Attribute %s: the value %s is not boolean\n",
1626 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001627 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001628 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001629}
1630
1631/************************************************************************
1632 * *
1633 * Shema extraction from an Infoset *
1634 * *
1635 ************************************************************************/
1636static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1637 ctxt, xmlSchemaPtr schema,
1638 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001639static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1640 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001641 xmlSchemaPtr schema,
1642 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001643static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1644 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001645 xmlSchemaPtr schema,
1646 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001647 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001648static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1649 xmlSchemaPtr schema,
1650 xmlNodePtr node);
1651static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1652 xmlSchemaPtr schema,
1653 xmlNodePtr node);
1654static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1655 ctxt,
1656 xmlSchemaPtr schema,
1657 xmlNodePtr node);
1658static xmlSchemaAttributeGroupPtr
1659xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1660 xmlSchemaPtr schema, xmlNodePtr node);
1661static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1662 xmlSchemaPtr schema,
1663 xmlNodePtr node);
1664static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1665 xmlSchemaPtr schema,
1666 xmlNodePtr node);
1667static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001668xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1669 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001670
1671/**
1672 * xmlSchemaParseAttrDecls:
1673 * @ctxt: a schema validation context
1674 * @schema: the schema being built
1675 * @node: a subtree containing XML Schema informations
1676 * @type: the hosting type
1677 *
1678 * parse a XML schema attrDecls declaration corresponding to
1679 * <!ENTITY % attrDecls
1680 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1681 */
1682static xmlNodePtr
1683xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1684 xmlNodePtr child, xmlSchemaTypePtr type)
1685{
1686 xmlSchemaAttributePtr lastattr, attr;
1687
1688 lastattr = NULL;
1689 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001690 (IS_SCHEMA(child, "attributeGroup"))) {
1691 attr = NULL;
1692 if (IS_SCHEMA(child, "attribute")) {
1693 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1694 } else if (IS_SCHEMA(child, "attributeGroup")) {
1695 attr = (xmlSchemaAttributePtr)
1696 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1697 }
1698 if (attr != NULL) {
1699 if (lastattr == NULL) {
1700 type->attributes = attr;
1701 lastattr = attr;
1702 } else {
1703 lastattr->next = attr;
1704 lastattr = attr;
1705 }
1706 }
1707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001708 }
1709 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001710 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1711 if (attr != NULL) {
1712 if (lastattr == NULL) {
1713 type->attributes = attr;
1714 lastattr = attr;
1715 } else {
1716 lastattr->next = attr;
1717 lastattr = attr;
1718 }
1719 }
1720 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001721 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001722 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001723}
1724
1725/**
1726 * xmlSchemaParseAnnotation:
1727 * @ctxt: a schema validation context
1728 * @schema: the schema being built
1729 * @node: a subtree containing XML Schema informations
1730 *
1731 * parse a XML schema Attrribute declaration
1732 * *WARNING* this interface is highly subject to change
1733 *
1734 * Returns -1 in case of error, 0 if the declaration is inproper and
1735 * 1 in case of success.
1736 */
1737static xmlSchemaAnnotPtr
1738xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1739 xmlNodePtr node)
1740{
1741 xmlSchemaAnnotPtr ret;
1742
1743 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1744 return (NULL);
1745 ret = xmlSchemaNewAnnot(ctxt, node);
1746
1747 return (ret);
1748}
1749
1750/**
1751 * xmlSchemaParseFacet:
1752 * @ctxt: a schema validation context
1753 * @schema: the schema being built
1754 * @node: a subtree containing XML Schema informations
1755 *
1756 * parse a XML schema Facet declaration
1757 * *WARNING* this interface is highly subject to change
1758 *
1759 * Returns the new type structure or NULL in case of error
1760 */
1761static xmlSchemaFacetPtr
1762xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001763 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001764{
1765 xmlSchemaFacetPtr facet;
1766 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001767 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001768
1769 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1770 return (NULL);
1771
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001772 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001773 if (facet == NULL) {
1774 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1775 return (NULL);
1776 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001777 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001778 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001779 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001780 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1781 "Facet %s has no value\n", node->name, NULL);
1782 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001783 return (NULL);
1784 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001785 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001786 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001787 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001788 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001789 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001790 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001791 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001792 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001793 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001794 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001795 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001796 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001797 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001798 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001799 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001800 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001801 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001802 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001803 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001804 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001805 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1807 } else if (IS_SCHEMA(node, "minLength")) {
1808 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1809 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001810 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1811 "Unknown facet type %s\n", node->name, NULL);
1812 xmlSchemaFreeFacet(facet);
1813 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001814 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001815 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001816 facet->value = value;
1817 child = node->children;
1818
1819 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001820 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1821 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001822 }
1823 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001824 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1825 "Facet %s has unexpected child content\n",
1826 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001827 }
1828 return (facet);
1829}
1830
1831/**
1832 * xmlSchemaParseAny:
1833 * @ctxt: a schema validation context
1834 * @schema: the schema being built
1835 * @node: a subtree containing XML Schema informations
1836 *
1837 * parse a XML schema Any declaration
1838 * *WARNING* this interface is highly subject to change
1839 *
1840 * Returns the new type structure or NULL in case of error
1841 */
1842static xmlSchemaTypePtr
1843xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1844 xmlNodePtr node)
1845{
1846 xmlSchemaTypePtr type;
1847 xmlNodePtr child = NULL;
1848 xmlChar name[30];
1849
1850 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1851 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001852 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001853 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001854 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001855 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001856 type->node = node;
1857 type->type = XML_SCHEMA_TYPE_ANY;
1858 child = node->children;
1859 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1860 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1861
1862 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001863 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1864 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001865 }
1866 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001867 xmlSchemaPErr2(ctxt, node, child,
1868 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1869 "Sequence %s has unexpected content\n", type->name,
1870 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001871 }
1872
1873 return (type);
1874}
1875
1876/**
1877 * xmlSchemaParseNotation:
1878 * @ctxt: a schema validation context
1879 * @schema: the schema being built
1880 * @node: a subtree containing XML Schema informations
1881 *
1882 * parse a XML schema Notation declaration
1883 *
1884 * Returns the new structure or NULL in case of error
1885 */
1886static xmlSchemaNotationPtr
1887xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001888 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001889{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001890 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001891 xmlSchemaNotationPtr ret;
1892 xmlNodePtr child = NULL;
1893
1894 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1895 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001896 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001897 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001898 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1899 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001900 return (NULL);
1901 }
1902 ret = xmlSchemaAddNotation(ctxt, schema, name);
1903 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001904 return (NULL);
1905 }
1906 child = node->children;
1907 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001908 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1909 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001910 }
1911 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001912 xmlSchemaPErr2(ctxt, node, child,
1913 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1914 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001915 }
1916
1917 return (ret);
1918}
1919
1920/**
1921 * xmlSchemaParseAnyAttribute:
1922 * @ctxt: a schema validation context
1923 * @schema: the schema being built
1924 * @node: a subtree containing XML Schema informations
1925 *
1926 * parse a XML schema AnyAttrribute declaration
1927 * *WARNING* this interface is highly subject to change
1928 *
1929 * Returns an attribute def structure or NULL
1930 */
1931static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001932xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1933 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001934{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001935 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001936 xmlSchemaAttributePtr ret;
1937 xmlNodePtr child = NULL;
1938 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001939 const xmlChar *local, *ns;
1940
Daniel Veillard4255d502002-04-16 15:50:10 +00001941
1942 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1943 return (NULL);
1944
1945 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001946 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1947 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001948 if (ret == NULL) {
1949 return (NULL);
1950 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001951 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1952 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001953 if ((processContents == NULL)
1954 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1955 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1956 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1957 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1958 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1959 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001960 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001961 xmlSchemaPErr2(ctxt, node, child,
1962 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1963 "anyAttribute has unexpected content for processContents: %s\n",
1964 processContents, NULL);
1965 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001966 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001967
1968 child = node->children;
1969 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001970 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1971 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001972 }
1973 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001974 xmlSchemaPErr2(ctxt, node, child,
1975 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1976 "anyAttribute %s has unexpected content\n",
1977 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001978 }
1979
1980 return (ret);
1981}
1982
1983
1984/**
1985 * xmlSchemaParseAttribute:
1986 * @ctxt: a schema validation context
1987 * @schema: the schema being built
1988 * @node: a subtree containing XML Schema informations
1989 *
1990 * parse a XML schema Attrribute declaration
1991 * *WARNING* this interface is highly subject to change
1992 *
1993 * Returns -1 in case of error, 0 if the declaration is inproper and
1994 * 1 in case of success.
1995 */
1996static xmlSchemaAttributePtr
1997xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1998 xmlNodePtr node)
1999{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002000 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002001 xmlSchemaAttributePtr ret;
2002 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002003 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002004
2005 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2006 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002007 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002008 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002009
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002010 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2011 if (ref == NULL) {
2012 xmlSchemaPErr2(ctxt, node, child,
2013 XML_SCHEMAP_ATTR_NONAME_NOREF,
2014 "Attribute has no name nor ref\n", NULL, NULL);
2015 return (NULL);
2016 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002017 if (refNs == NULL)
2018 refNs = schema->targetNamespace;
2019 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2020 name = (const xmlChar *) buf;
2021 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2022 } else {
2023 const xmlChar *local, *ns;
2024
2025 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2026 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002027 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002028 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 return (NULL);
2030 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002031 ret->ref = ref;
2032 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002033 if ((ret->targetNamespace != NULL) &&
2034 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2035 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2036 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002037 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002038 if ((ret->typeName != NULL) && (ret->typeNs == NULL))
2039 ret->typeNs = schema->targetNamespace;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002040 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002041 child = node->children;
2042 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002043 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2044 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002045 }
2046 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002047 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2048 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002049 }
2050 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002051 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2052 "attribute %s has unexpected content\n", name,
2053 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002054 }
2055
2056 return (ret);
2057}
2058
2059/**
2060 * xmlSchemaParseAttributeGroup:
2061 * @ctxt: a schema validation context
2062 * @schema: the schema being built
2063 * @node: a subtree containing XML Schema informations
2064 *
2065 * parse a XML schema Attribute Group declaration
2066 * *WARNING* this interface is highly subject to change
2067 *
2068 * Returns the attribute group or NULL in case of error.
2069 */
2070static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002071xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2072 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002073{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002074 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002075 xmlSchemaAttributeGroupPtr ret;
2076 xmlSchemaAttributePtr last = NULL, attr;
2077 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002078 const xmlChar *oldcontainer;
2079 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002080
2081 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2082 return (NULL);
2083 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002084 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002085 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002086
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002087 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2088 if (ref == NULL) {
2089 xmlSchemaPErr2(ctxt, node, child,
2090 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2091 "AttributeGroup has no name nor ref\n", NULL,
2092 NULL);
2093 return (NULL);
2094 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002095 if (refNs == NULL)
2096 refNs = schema->targetNamespace;
2097 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2098 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002099 if (name == NULL) {
2100 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2101 return (NULL);
2102 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002103 }
2104 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2105 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002106 return (NULL);
2107 }
2108 ret->ref = ref;
2109 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002110 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002111 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002112 child = node->children;
2113 ctxt->container = name;
2114 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002115 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2116 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002117 }
2118 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002119 (IS_SCHEMA(child, "attributeGroup"))) {
2120 attr = NULL;
2121 if (IS_SCHEMA(child, "attribute")) {
2122 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2123 } else if (IS_SCHEMA(child, "attributeGroup")) {
2124 attr = (xmlSchemaAttributePtr)
2125 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2126 }
2127 if (attr != NULL) {
2128 if (last == NULL) {
2129 ret->attributes = attr;
2130 last = attr;
2131 } else {
2132 last->next = attr;
2133 last = attr;
2134 }
2135 }
2136 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002137 }
2138 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002139 TODO
2140 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002141 }
2142 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002143 xmlSchemaPErr2(ctxt, node, child,
2144 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2145 "attribute group %s has unexpected content\n", name,
2146 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002147 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002148 ctxt->container = oldcontainer;
2149 return (ret);
2150}
2151
2152/**
2153 * xmlSchemaParseElement:
2154 * @ctxt: a schema validation context
2155 * @schema: the schema being built
2156 * @node: a subtree containing XML Schema informations
2157 *
2158 * parse a XML schema Element declaration
2159 * *WARNING* this interface is highly subject to change
2160 *
2161 * Returns -1 in case of error, 0 if the declaration is inproper and
2162 * 1 in case of success.
2163 */
2164static xmlSchemaElementPtr
2165xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2166 xmlNodePtr node, int toplevel)
2167{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002168 const xmlChar *name, *fixed;
2169 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002170 xmlSchemaElementPtr ret;
2171 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002172 const xmlChar *oldcontainer;
2173 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002174
2175 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2176 return (NULL);
2177 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002178 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002179 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002180
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002181 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2182 if (ref == NULL) {
2183 xmlSchemaPErr2(ctxt, node, child,
2184 XML_SCHEMAP_ELEM_NONAME_NOREF,
2185 "Element has no name nor ref\n", NULL, NULL);
2186 return (NULL);
2187 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002188 if (refNs == NULL)
2189 refNs = schema->targetNamespace;
2190 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2191 name = (const xmlChar *) buf;
2192 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2193 } else {
2194 const xmlChar *local, *ns;
2195
2196 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2197 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002198 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002199 if (ret != NULL)
2200 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002201 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002202 return (NULL);
2203 }
2204 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2205 ret->ref = ref;
2206 ret->refNs = refNs;
2207 if (ref != NULL)
2208 ret->flags |= XML_SCHEMAS_ELEM_REF;
2209 if (toplevel)
2210 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2211 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2212 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2213 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2214 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2215 ctxt->container = name;
2216
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002217 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002218 ret->namedType =
2219 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002220 if ((ret->namedType != NULL) && (ret->namedTypeNs == NULL))
2221 ret->namedTypeNs = schema->targetNamespace;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002222 ret->substGroup =
2223 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2224 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002225 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2227 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002229 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002230 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2232 "Element %s has both default and fixed\n",
2233 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002234 } else if (fixed != NULL) {
2235 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002236 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002237 }
2238
2239 child = node->children;
2240 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2242 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002243 }
2244 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002245 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 child = child->next;
2247 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 child = child->next;
2250 }
2251 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002252 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2253 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002254 }
2255 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002256 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2257 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002258 }
2259
2260 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002261 return (ret);
2262}
2263
2264/**
2265 * xmlSchemaParseUnion:
2266 * @ctxt: a schema validation context
2267 * @schema: the schema being built
2268 * @node: a subtree containing XML Schema informations
2269 *
2270 * parse a XML schema Union definition
2271 * *WARNING* this interface is highly subject to change
2272 *
2273 * Returns -1 in case of error, 0 if the declaration is inproper and
2274 * 1 in case of success.
2275 */
2276static xmlSchemaTypePtr
2277xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002278 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002279{
2280 xmlSchemaTypePtr type, subtype, last = NULL;
2281 xmlNodePtr child = NULL;
2282 xmlChar name[30];
2283
2284 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2285 return (NULL);
2286
2287
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002288 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002289 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002290 if (type == NULL)
2291 return (NULL);
2292 type->node = node;
2293 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002294 type->id = xmlSchemaGetProp(ctxt, node, "id");
2295 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002296
2297 child = node->children;
2298 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002299 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002301 }
2302 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002303 subtype = (xmlSchemaTypePtr)
2304 xmlSchemaParseSimpleType(ctxt, schema, child);
2305 if (subtype != NULL) {
2306 if (last == NULL) {
2307 type->subtypes = subtype;
2308 last = subtype;
2309 } else {
2310 last->next = subtype;
2311 last = subtype;
2312 }
2313 last->next = NULL;
2314 }
2315 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002316 }
2317 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002318 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2319 "Union %s has unexpected content\n", type->name,
2320 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002321 }
2322 return (type);
2323}
2324
2325/**
2326 * xmlSchemaParseList:
2327 * @ctxt: a schema validation context
2328 * @schema: the schema being built
2329 * @node: a subtree containing XML Schema informations
2330 *
2331 * parse a XML schema List definition
2332 * *WARNING* this interface is highly subject to change
2333 *
2334 * Returns -1 in case of error, 0 if the declaration is inproper and
2335 * 1 in case of success.
2336 */
2337static xmlSchemaTypePtr
2338xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002339 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002340{
2341 xmlSchemaTypePtr type, subtype;
2342 xmlNodePtr child = NULL;
2343 xmlChar name[30];
2344
2345 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2346 return (NULL);
2347
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002349 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002350 if (type == NULL)
2351 return (NULL);
2352 type->node = node;
2353 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002354 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002355 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002356 if ((type->ref != NULL) && (type->refNs == NULL))
2357 type->refNs = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00002358
2359 child = node->children;
2360 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002361 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2362 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002363 }
2364 subtype = NULL;
2365 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002366 subtype = (xmlSchemaTypePtr)
2367 xmlSchemaParseSimpleType(ctxt, schema, child);
2368 child = child->next;
2369 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002370 }
2371 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002372 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2373 "List %s has unexpected content\n", type->name,
2374 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002375 }
2376 return (type);
2377}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002378
Daniel Veillard4255d502002-04-16 15:50:10 +00002379/**
2380 * xmlSchemaParseSimpleType:
2381 * @ctxt: a schema validation context
2382 * @schema: the schema being built
2383 * @node: a subtree containing XML Schema informations
2384 *
2385 * parse a XML schema Simple Type definition
2386 * *WARNING* this interface is highly subject to change
2387 *
2388 * Returns -1 in case of error, 0 if the declaration is inproper and
2389 * 1 in case of success.
2390 */
2391static xmlSchemaTypePtr
2392xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2393 xmlNodePtr node)
2394{
2395 xmlSchemaTypePtr type, subtype;
2396 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002397 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002398
2399 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2400 return (NULL);
2401
2402
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002403 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002404 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002405 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002406
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002407 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2408 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2409 } else {
2410 const xmlChar *local, *ns;
2411
2412 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2413 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002414 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002415 if (type == NULL)
2416 return (NULL);
2417 type->node = node;
2418 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002419 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002420
2421 child = node->children;
2422 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002423 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2424 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002425 }
2426 subtype = NULL;
2427 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 subtype = (xmlSchemaTypePtr)
2429 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2430 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002432 subtype = (xmlSchemaTypePtr)
2433 xmlSchemaParseList(ctxt, schema, child);
2434 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002435 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002436 subtype = (xmlSchemaTypePtr)
2437 xmlSchemaParseUnion(ctxt, schema, child);
2438 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002439 }
2440 type->subtypes = subtype;
2441 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002442 xmlSchemaPErr2(ctxt, node, child,
2443 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2444 "SimpleType %s has unexpected content\n",
2445 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002446 }
2447
2448 return (type);
2449}
2450
2451
2452/**
2453 * xmlSchemaParseGroup:
2454 * @ctxt: a schema validation context
2455 * @schema: the schema being built
2456 * @node: a subtree containing XML Schema informations
2457 *
2458 * parse a XML schema Group definition
2459 * *WARNING* this interface is highly subject to change
2460 *
2461 * Returns -1 in case of error, 0 if the declaration is inproper and
2462 * 1 in case of success.
2463 */
2464static xmlSchemaTypePtr
2465xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002466 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002467{
2468 xmlSchemaTypePtr type, subtype;
2469 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002470 const xmlChar *name;
2471 const xmlChar *ref = NULL, *refNs = NULL;
2472 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002473
2474 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2475 return (NULL);
2476
2477
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002478 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002479 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002480
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002481 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2482 if (ref == NULL) {
2483 xmlSchemaPErr2(ctxt, node, child,
2484 XML_SCHEMAP_GROUP_NONAME_NOREF,
2485 "Group has no name nor ref\n", NULL, NULL);
2486 return (NULL);
2487 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002488 if (refNs == NULL)
2489 refNs = schema->targetNamespace;
2490 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2491 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002492 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002493 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002494 if (type == NULL)
2495 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002496
Daniel Veillard4255d502002-04-16 15:50:10 +00002497 type->node = node;
2498 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002499 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002500 type->ref = ref;
2501 type->refNs = refNs;
2502 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2503 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2504
2505 child = node->children;
2506 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002507 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2508 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002509 }
2510 subtype = NULL;
2511 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002512 subtype = (xmlSchemaTypePtr)
2513 xmlSchemaParseAll(ctxt, schema, child);
2514 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002515 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002516 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2517 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002518 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002519 subtype = (xmlSchemaTypePtr)
2520 xmlSchemaParseSequence(ctxt, schema, child);
2521 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002522 }
2523 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002524 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002525 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002526 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2527 "Group %s has unexpected content\n", type->name,
2528 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002529 }
2530
2531 return (type);
2532}
2533
2534/**
2535 * xmlSchemaParseAll:
2536 * @ctxt: a schema validation context
2537 * @schema: the schema being built
2538 * @node: a subtree containing XML Schema informations
2539 *
2540 * parse a XML schema All definition
2541 * *WARNING* this interface is highly subject to change
2542 *
2543 * Returns -1 in case of error, 0 if the declaration is inproper and
2544 * 1 in case of success.
2545 */
2546static xmlSchemaTypePtr
2547xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002548 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002549{
2550 xmlSchemaTypePtr type, subtype, last = NULL;
2551 xmlNodePtr child = NULL;
2552 xmlChar name[30];
2553
2554 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2555 return (NULL);
2556
2557
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002558 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002559 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002560 if (type == NULL)
2561 return (NULL);
2562 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002563 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002564 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002565 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002566 if (type->minOccurs > 1)
2567 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2568 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002569 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002570 if (type->maxOccurs > 1)
2571 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2572 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002573
2574 child = node->children;
2575 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002576 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2577 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002578 }
2579 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002580 subtype = (xmlSchemaTypePtr)
2581 xmlSchemaParseElement(ctxt, schema, child, 0);
2582 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002583 if (subtype->minOccurs > 1)
2584 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2585 "invalid value for minOccurs (must be 0 or 1)\n",
2586 NULL, NULL);
2587 if (subtype->maxOccurs > 1)
2588 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2589 "invalid value for maxOccurs (must be 0 or 1)\n",
2590 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002591 if (last == NULL) {
2592 type->subtypes = subtype;
2593 last = subtype;
2594 } else {
2595 last->next = subtype;
2596 last = subtype;
2597 }
2598 last->next = NULL;
2599 }
2600 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002601 }
2602 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002603 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2604 "All %s has unexpected content\n", type->name,
2605 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002606 }
2607
2608 return (type);
2609}
2610
2611/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002612 * xmlSchemaImportSchema
2613 *
2614 * @ctxt: a schema validation context
2615 * @schemaLocation: an URI defining where to find the imported schema
2616 *
2617 * import a XML schema
2618 * *WARNING* this interface is highly subject to change
2619 *
2620 * Returns -1 in case of error and 1 in case of success.
2621 */
2622static xmlSchemaImportPtr
2623xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2624 const xmlChar *schemaLocation)
2625{
2626 xmlSchemaImportPtr import;
2627 xmlSchemaParserCtxtPtr newctxt;
2628
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002629 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002630 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002631 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002632 NULL);
2633 return (NULL);
2634 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002635 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2636 /* Keep the same dictionnary for parsing, really */
2637 xmlDictReference(ctxt->dict);
2638 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002639 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002640 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2641
Daniel Veillard1d913862003-11-21 00:28:39 +00002642 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2643 ctxt->userData);
2644
2645 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2646 if (import == NULL) {
2647 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2648 NULL);
2649 xmlSchemaFreeParserCtxt(newctxt);
2650 return (NULL);
2651 }
2652
2653 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002654 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002655 import->schema = xmlSchemaParse(newctxt);
2656
2657 if (import->schema == NULL) {
2658 /* FIXME use another error enum here ? */
2659 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2660 "failed to import schema at location %s\n",
2661 schemaLocation, NULL);
2662
2663 xmlSchemaFreeParserCtxt(newctxt);
2664 if (import->schemaLocation != NULL)
2665 xmlFree((xmlChar *)import->schemaLocation);
2666 xmlFree(import);
2667 return NULL;
2668 }
2669
2670 xmlSchemaFreeParserCtxt(newctxt);
2671 return import;
2672}
2673
2674
2675/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002676 * xmlSchemaParseImport:
2677 * @ctxt: a schema validation context
2678 * @schema: the schema being built
2679 * @node: a subtree containing XML Schema informations
2680 *
2681 * parse a XML schema Import definition
2682 * *WARNING* this interface is highly subject to change
2683 *
2684 * Returns -1 in case of error, 0 if the declaration is inproper and
2685 * 1 in case of success.
2686 */
2687static int
2688xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002689 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002690{
2691 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002692 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002693 const xmlChar *namespace;
2694 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002695 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002696 xmlURIPtr check;
2697
Daniel Veillard1d913862003-11-21 00:28:39 +00002698
Daniel Veillard5a872412002-05-22 06:40:27 +00002699 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2700 return (-1);
2701
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002702 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002703 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002704 check = xmlParseURI((const char *) namespace);
2705 if (check == NULL) {
2706 xmlSchemaPErr2(ctxt, node, child,
2707 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2708 "Import namespace attribute is not an URI: %s\n",
2709 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002710 return (-1);
2711 } else {
2712 xmlFreeURI(check);
2713 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002714 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002715 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002716 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002717 xmlChar *base = NULL;
2718 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002719 check = xmlParseURI((const char *) schemaLocation);
2720 if (check == NULL) {
2721 xmlSchemaPErr2(ctxt, node, child,
2722 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2723 "Import schemaLocation attribute is not an URI: %s\n",
2724 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002725 return (-1);
2726 } else {
2727 xmlFreeURI(check);
2728 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002729 base = xmlNodeGetBase(node->doc, node);
2730 if (base == NULL) {
2731 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2732 } else {
2733 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002734 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002735 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002736 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002737 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2738 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002739 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002740 }
2741 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002742 schema->schemasImports = xmlHashCreate(10);
2743 if (schema->schemasImports == NULL) {
2744 xmlSchemaPErr2(ctxt, node, child,
2745 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2746 "Internal: failed to build import table\n",
2747 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002748 return (-1);
2749 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002750 }
2751 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002752 import = xmlHashLookup(schema->schemasImports,
2753 XML_SCHEMAS_DEFAULT_NAMESPACE);
2754 if (import != NULL)
2755 previous = import->schemaLocation;
2756 else
2757 previous = NULL;
2758
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 if (schemaLocation != NULL) {
2760 if (previous != NULL) {
2761 if (!xmlStrEqual(schemaLocation, previous)) {
2762 xmlSchemaPErr2(ctxt, node, child,
2763 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2764 "Redefining import for default namespace with a different URI: %s\n",
2765 schemaLocation, NULL);
2766 }
2767 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002768 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2769 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002770 return (-1);
2771 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002772 xmlHashAddEntry(schema->schemasImports,
2773 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002774 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002775 }
2776 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002777 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002778 import = xmlHashLookup(schema->schemasImports, namespace);
2779 if (import != NULL)
2780 previous = import->schemaLocation;
2781 else
2782 previous = NULL;
2783
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002784 if (schemaLocation != NULL) {
2785 if (previous != NULL) {
2786 if (!xmlStrEqual(schemaLocation, previous)) {
2787 xmlSchemaPErr2(ctxt, node, child,
2788 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2789 "Redefining import for namespace %s with a different URI: %s\n",
2790 namespace, schemaLocation);
2791 }
2792 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002793 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2794 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002795 return (-1);
2796 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002797 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002798 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002799 }
2800 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002801 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002802
2803 child = node->children;
2804 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002805 /*
2806 * the annotations here are simply discarded ...
2807 */
2808 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002809 }
2810 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002811 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2812 "Import has unexpected content\n", NULL, NULL);
2813 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002814 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002815 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002816}
2817
2818/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002819 * xmlSchemaCleanupDoc:
2820 * @ctxt: a schema validation context
2821 * @node: the root of the document.
2822 *
2823 * removes unwanted nodes in a schemas document tree
2824 */
2825static void
2826xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
2827{
2828 xmlNodePtr delete, cur;
2829
2830 if ((ctxt == NULL) || (root == NULL)) return;
2831
2832 /*
2833 * Remove all the blank text nodes
2834 */
2835 delete = NULL;
2836 cur = root;
2837 while (cur != NULL) {
2838 if (delete != NULL) {
2839 xmlUnlinkNode(delete);
2840 xmlFreeNode(delete);
2841 delete = NULL;
2842 }
2843 if (cur->type == XML_TEXT_NODE) {
2844 if (IS_BLANK_NODE(cur)) {
2845 if (xmlNodeGetSpacePreserve(cur) != 1) {
2846 delete = cur;
2847 }
2848 }
2849 } else if ((cur->type != XML_ELEMENT_NODE) &&
2850 (cur->type != XML_CDATA_SECTION_NODE)) {
2851 delete = cur;
2852 goto skip_children;
2853 }
2854
2855 /*
2856 * Skip to next node
2857 */
2858 if (cur->children != NULL) {
2859 if ((cur->children->type != XML_ENTITY_DECL) &&
2860 (cur->children->type != XML_ENTITY_REF_NODE) &&
2861 (cur->children->type != XML_ENTITY_NODE)) {
2862 cur = cur->children;
2863 continue;
2864 }
2865 }
2866 skip_children:
2867 if (cur->next != NULL) {
2868 cur = cur->next;
2869 continue;
2870 }
2871
2872 do {
2873 cur = cur->parent;
2874 if (cur == NULL)
2875 break;
2876 if (cur == root) {
2877 cur = NULL;
2878 break;
2879 }
2880 if (cur->next != NULL) {
2881 cur = cur->next;
2882 break;
2883 }
2884 } while (cur != NULL);
2885 }
2886 if (delete != NULL) {
2887 xmlUnlinkNode(delete);
2888 xmlFreeNode(delete);
2889 delete = NULL;
2890 }
2891}
2892
2893/**
2894 * xmlSchemaParseSchemaTopLevel:
2895 * @ctxt: a schema validation context
2896 * @schema: the schemas
2897 * @nodes: the list of top level nodes
2898 *
2899 * Returns the internal XML Schema structure built from the resource or
2900 * NULL in case of error
2901 */
2902static void
2903xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
2904 xmlSchemaPtr schema, xmlNodePtr nodes)
2905{
2906 xmlNodePtr child;
2907 xmlSchemaAnnotPtr annot;
2908
2909 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
2910 return;
2911
2912 child = nodes;
2913 while ((IS_SCHEMA(child, "include")) ||
2914 (IS_SCHEMA(child, "import")) ||
2915 (IS_SCHEMA(child, "redefine")) ||
2916 (IS_SCHEMA(child, "annotation"))) {
2917 if (IS_SCHEMA(child, "annotation")) {
2918 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2919 if (schema->annot == NULL)
2920 schema->annot = annot;
2921 else
2922 xmlSchemaFreeAnnot(annot);
2923 } else if (IS_SCHEMA(child, "import")) {
2924 xmlSchemaParseImport(ctxt, schema, child);
2925 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002926 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002927 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002928 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002929 } else if (IS_SCHEMA(child, "redefine")) {
2930 TODO
2931 }
2932 child = child->next;
2933 }
2934 while (child != NULL) {
2935 if (IS_SCHEMA(child, "complexType")) {
2936 xmlSchemaParseComplexType(ctxt, schema, child);
2937 child = child->next;
2938 } else if (IS_SCHEMA(child, "simpleType")) {
2939 xmlSchemaParseSimpleType(ctxt, schema, child);
2940 child = child->next;
2941 } else if (IS_SCHEMA(child, "element")) {
2942 xmlSchemaParseElement(ctxt, schema, child, 1);
2943 child = child->next;
2944 } else if (IS_SCHEMA(child, "attribute")) {
2945 xmlSchemaParseAttribute(ctxt, schema, child);
2946 child = child->next;
2947 } else if (IS_SCHEMA(child, "attributeGroup")) {
2948 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2949 child = child->next;
2950 } else if (IS_SCHEMA(child, "group")) {
2951 xmlSchemaParseGroup(ctxt, schema, child);
2952 child = child->next;
2953 } else if (IS_SCHEMA(child, "notation")) {
2954 xmlSchemaParseNotation(ctxt, schema, child);
2955 child = child->next;
2956 } else {
2957 xmlSchemaPErr2(ctxt, NULL, child,
2958 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
2959 "Schemas: unexpected element %s here \n",
2960 child->name, NULL);
2961 child = child->next;
2962 }
2963 while (IS_SCHEMA(child, "annotation")) {
2964 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2965 if (schema->annot == NULL)
2966 schema->annot = annot;
2967 else
2968 xmlSchemaFreeAnnot(annot);
2969 child = child->next;
2970 }
2971 }
2972}
2973
2974/**
2975 * xmlSchemaParseInclude:
2976 * @ctxt: a schema validation context
2977 * @schema: the schema being built
2978 * @node: a subtree containing XML Schema informations
2979 *
2980 * parse a XML schema Include definition
2981 *
2982 * Returns -1 in case of error, 0 if the declaration is inproper and
2983 * 1 in case of success.
2984 */
2985static int
2986xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2987 xmlNodePtr node)
2988{
2989 xmlNodePtr child = NULL;
2990 const xmlChar *schemaLocation;
2991 xmlURIPtr check;
2992 xmlDocPtr doc;
2993 xmlNodePtr root;
2994 xmlSchemaIncludePtr include;
2995
2996
2997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2998 return (-1);
2999
3000 /*
3001 * Preliminary step, extract the URI-Reference for the include and
3002 * make an URI from the base.
3003 */
3004 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3005 if (schemaLocation != NULL) {
3006 xmlChar *base = NULL;
3007 xmlChar *URI = NULL;
3008 check = xmlParseURI((const char *) schemaLocation);
3009 if (check == NULL) {
3010 xmlSchemaPErr2(ctxt, node, child,
3011 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3012 "Include schemaLocation attribute is not an URI: %s\n",
3013 schemaLocation, NULL);
3014 return (-1);
3015 } else {
3016 xmlFreeURI(check);
3017 }
3018 base = xmlNodeGetBase(node->doc, node);
3019 if (base == NULL) {
3020 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3021 } else {
3022 URI = xmlBuildURI(schemaLocation, base);
3023 xmlFree(base);
3024 }
3025 if (URI != NULL) {
3026 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3027 xmlFree(URI);
3028 }
3029 } else {
3030 xmlSchemaPErr2(ctxt, node, child,
3031 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3032 "Include schemaLocation attribute missing\n",
3033 NULL, NULL);
3034 return (-1);
3035 }
3036
3037 child = node->children;
3038 while (IS_SCHEMA(child, "annotation")) {
3039 /*
3040 * the annotations here are simply discarded ...
3041 */
3042 child = child->next;
3043 }
3044 if (child != NULL) {
3045 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3046 "Include has unexpected content\n", NULL, NULL);
3047 return (-1);
3048 }
3049
3050 /*
3051 * First step is to parse the input document into an DOM/Infoset
3052 */
3053 doc = xmlReadFile((const char *) schemaLocation, NULL,
3054 SCHEMAS_PARSE_OPTIONS);
3055 if (doc == NULL) {
3056 xmlSchemaPErr(ctxt, NULL,
3057 XML_SCHEMAP_FAILED_LOAD,
3058 "xmlSchemaParse: could not load %s\n",
3059 ctxt->URL, NULL);
3060 return(-1);
3061 }
3062
3063 /*
3064 * Then extract the root of the schema
3065 */
3066 root = xmlDocGetRootElement(doc);
3067 if (root == NULL) {
3068 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3069 XML_SCHEMAP_NOROOT,
3070 "schemas %s has no root", schemaLocation, NULL);
3071 xmlFreeDoc(doc);
3072 return (-1);
3073 }
3074
3075 /*
3076 * Remove all the blank text nodes
3077 */
3078 xmlSchemaCleanupDoc(ctxt, root);
3079
3080 /*
3081 * Check the schemas top level element
3082 */
3083 if (!IS_SCHEMA(root, "schema")) {
3084 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3085 XML_SCHEMAP_NOT_SCHEMA,
3086 "File %s is not a schemas", schemaLocation, NULL);
3087 xmlFreeDoc(doc);
3088 return (-1);
3089 }
3090
3091 /*
3092 * register the include
3093 */
3094 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3095 if (include == NULL) {
3096 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3097 xmlFreeDoc(doc);
3098 return (-1);
3099 }
3100
3101 memset(include, 0, sizeof(xmlSchemaInclude));
3102 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3103 include->doc = doc;
3104 include->next = schema->includes;
3105 schema->includes = include;
3106
3107
3108 /*
3109 * parse the declarations in the included file like if they
3110 * were in the original file.
3111 */
3112 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3113
3114 return (1);
3115}
3116
3117/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003118 * xmlSchemaParseChoice:
3119 * @ctxt: a schema validation context
3120 * @schema: the schema being built
3121 * @node: a subtree containing XML Schema informations
3122 *
3123 * parse a XML schema Choice definition
3124 * *WARNING* this interface is highly subject to change
3125 *
3126 * Returns -1 in case of error, 0 if the declaration is inproper and
3127 * 1 in case of success.
3128 */
3129static xmlSchemaTypePtr
3130xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003131 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003132{
3133 xmlSchemaTypePtr type, subtype, last = NULL;
3134 xmlNodePtr child = NULL;
3135 xmlChar name[30];
3136
3137 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3138 return (NULL);
3139
3140
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003141 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003142 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003143 if (type == NULL)
3144 return (NULL);
3145 type->node = node;
3146 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003147 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003148 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3149 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3150
3151 child = node->children;
3152 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003153 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3154 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003155 }
3156 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003157 (IS_SCHEMA(child, "group")) ||
3158 (IS_SCHEMA(child, "any")) ||
3159 (IS_SCHEMA(child, "choice")) ||
3160 (IS_SCHEMA(child, "sequence"))) {
3161 subtype = NULL;
3162 if (IS_SCHEMA(child, "element")) {
3163 subtype = (xmlSchemaTypePtr)
3164 xmlSchemaParseElement(ctxt, schema, child, 0);
3165 } else if (IS_SCHEMA(child, "group")) {
3166 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3167 } else if (IS_SCHEMA(child, "any")) {
3168 subtype = xmlSchemaParseAny(ctxt, schema, child);
3169 } else if (IS_SCHEMA(child, "sequence")) {
3170 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3171 } else if (IS_SCHEMA(child, "choice")) {
3172 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3173 }
3174 if (subtype != NULL) {
3175 if (last == NULL) {
3176 type->subtypes = subtype;
3177 last = subtype;
3178 } else {
3179 last->next = subtype;
3180 last = subtype;
3181 }
3182 last->next = NULL;
3183 }
3184 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 }
3186 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003187 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3188 "Choice %s has unexpected content\n", type->name,
3189 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 }
3191
3192 return (type);
3193}
3194
3195/**
3196 * xmlSchemaParseSequence:
3197 * @ctxt: a schema validation context
3198 * @schema: the schema being built
3199 * @node: a subtree containing XML Schema informations
3200 *
3201 * parse a XML schema Sequence definition
3202 * *WARNING* this interface is highly subject to change
3203 *
3204 * Returns -1 in case of error, 0 if the declaration is inproper and
3205 * 1 in case of success.
3206 */
3207static xmlSchemaTypePtr
3208xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003209 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003210{
3211 xmlSchemaTypePtr type, subtype, last = NULL;
3212 xmlNodePtr child = NULL;
3213 xmlChar name[30];
3214
3215 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3216 return (NULL);
3217
3218
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003219 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003220 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003221 if (type == NULL)
3222 return (NULL);
3223 type->node = node;
3224 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003225 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003226 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3227 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3228
3229 child = node->children;
3230 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003231 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003233 }
3234 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003235 (IS_SCHEMA(child, "group")) ||
3236 (IS_SCHEMA(child, "any")) ||
3237 (IS_SCHEMA(child, "choice")) ||
3238 (IS_SCHEMA(child, "sequence"))) {
3239 subtype = NULL;
3240 if (IS_SCHEMA(child, "element")) {
3241 subtype = (xmlSchemaTypePtr)
3242 xmlSchemaParseElement(ctxt, schema, child, 0);
3243 } else if (IS_SCHEMA(child, "group")) {
3244 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3245 } else if (IS_SCHEMA(child, "any")) {
3246 subtype = xmlSchemaParseAny(ctxt, schema, child);
3247 } else if (IS_SCHEMA(child, "choice")) {
3248 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3249 } else if (IS_SCHEMA(child, "sequence")) {
3250 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3251 }
3252 if (subtype != NULL) {
3253 if (last == NULL) {
3254 type->subtypes = subtype;
3255 last = subtype;
3256 } else {
3257 last->next = subtype;
3258 last = subtype;
3259 }
3260 last->next = NULL;
3261 }
3262 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003263 }
3264 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003265 xmlSchemaPErr2(ctxt, node, child,
3266 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3267 "Sequence %s has unexpected content\n", type->name,
3268 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003269 }
3270
3271 return (type);
3272}
3273
3274/**
3275 * xmlSchemaParseRestriction:
3276 * @ctxt: a schema validation context
3277 * @schema: the schema being built
3278 * @node: a subtree containing XML Schema informations
3279 * @simple: is that part of a simple type.
3280 *
3281 * parse a XML schema Restriction definition
3282 * *WARNING* this interface is highly subject to change
3283 *
3284 * Returns the type definition or NULL in case of error
3285 */
3286static xmlSchemaTypePtr
3287xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3288 xmlNodePtr node, int simple)
3289{
3290 xmlSchemaTypePtr type, subtype;
3291 xmlSchemaFacetPtr facet, lastfacet = NULL;
3292 xmlNodePtr child = NULL;
3293 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003294 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003295
3296 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3297 return (NULL);
3298
3299 oldcontainer = ctxt->container;
3300
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003302 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003303 if (type == NULL)
3304 return (NULL);
3305 type->node = node;
3306 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003307 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003308 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3309 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003310 xmlSchemaPErr2(ctxt, node, child,
3311 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3312 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003313 }
3314 ctxt->container = name;
3315
3316 child = node->children;
3317 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003318 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3319 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003320 }
3321 subtype = NULL;
3322
3323 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003324 subtype = (xmlSchemaTypePtr)
3325 xmlSchemaParseAll(ctxt, schema, child);
3326 child = child->next;
3327 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003328 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003329 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3330 child = child->next;
3331 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003332 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003333 subtype = (xmlSchemaTypePtr)
3334 xmlSchemaParseSequence(ctxt, schema, child);
3335 child = child->next;
3336 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003337 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003338 subtype = (xmlSchemaTypePtr)
3339 xmlSchemaParseGroup(ctxt, schema, child);
3340 child = child->next;
3341 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003342 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003343 if (IS_SCHEMA(child, "simpleType")) {
3344 subtype = (xmlSchemaTypePtr)
3345 xmlSchemaParseSimpleType(ctxt, schema, child);
3346 child = child->next;
3347 type->baseType = subtype;
3348 }
3349 /*
3350 * Facets
3351 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003352 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003353 (IS_SCHEMA(child, "minExclusive")) ||
3354 (IS_SCHEMA(child, "maxInclusive")) ||
3355 (IS_SCHEMA(child, "maxExclusive")) ||
3356 (IS_SCHEMA(child, "totalDigits")) ||
3357 (IS_SCHEMA(child, "fractionDigits")) ||
3358 (IS_SCHEMA(child, "pattern")) ||
3359 (IS_SCHEMA(child, "enumeration")) ||
3360 (IS_SCHEMA(child, "whiteSpace")) ||
3361 (IS_SCHEMA(child, "length")) ||
3362 (IS_SCHEMA(child, "maxLength")) ||
3363 (IS_SCHEMA(child, "minLength"))) {
3364 facet = xmlSchemaParseFacet(ctxt, schema, child);
3365 if (facet != NULL) {
3366 if (lastfacet == NULL) {
3367 type->facets = facet;
3368 lastfacet = facet;
3369 } else {
3370 lastfacet->next = facet;
3371 lastfacet = facet;
3372 }
3373 lastfacet->next = NULL;
3374 }
3375 child = child->next;
3376 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003377 }
3378 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3379 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003380 xmlSchemaPErr2(ctxt, node, child,
3381 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3382 "Restriction %s has unexpected content\n",
3383 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003384 }
3385 ctxt->container = oldcontainer;
3386 return (type);
3387}
3388
3389/**
3390 * xmlSchemaParseExtension:
3391 * @ctxt: a schema validation context
3392 * @schema: the schema being built
3393 * @node: a subtree containing XML Schema informations
3394 *
3395 * parse a XML schema Extension definition
3396 * *WARNING* this interface is highly subject to change
3397 *
3398 * Returns the type definition or NULL in case of error
3399 */
3400static xmlSchemaTypePtr
3401xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003403{
3404 xmlSchemaTypePtr type, subtype;
3405 xmlNodePtr child = NULL;
3406 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003407 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003408
3409 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3410 return (NULL);
3411
3412 oldcontainer = ctxt->container;
3413
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003414 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003415 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003416 if (type == NULL)
3417 return (NULL);
3418 type->node = node;
3419 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003420 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003421 ctxt->container = name;
3422
3423 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3424 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003425 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3426 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003427 }
3428 child = node->children;
3429 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003430 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3431 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003432 }
3433 subtype = NULL;
3434
3435 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003436 subtype = xmlSchemaParseAll(ctxt, schema, child);
3437 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003438 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003439 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3440 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003441 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003442 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3443 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003444 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003445 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3446 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003447 }
3448 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003449 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003450 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3451 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003452 xmlSchemaPErr2(ctxt, node, child,
3453 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3454 "Extension %s has unexpected content\n", type->name,
3455 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003456 }
3457 ctxt->container = oldcontainer;
3458 return (type);
3459}
3460
3461/**
3462 * xmlSchemaParseSimpleContent:
3463 * @ctxt: a schema validation context
3464 * @schema: the schema being built
3465 * @node: a subtree containing XML Schema informations
3466 *
3467 * parse a XML schema SimpleContent definition
3468 * *WARNING* this interface is highly subject to change
3469 *
3470 * Returns the type definition or NULL in case of error
3471 */
3472static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003473xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3474 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003475{
3476 xmlSchemaTypePtr type, subtype;
3477 xmlNodePtr child = NULL;
3478 xmlChar name[30];
3479
3480 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3481 return (NULL);
3482
3483
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003484 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003485 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003486 if (type == NULL)
3487 return (NULL);
3488 type->node = node;
3489 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003490 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003491
3492 child = node->children;
3493 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003494 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3495 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003496 }
3497 subtype = NULL;
3498 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003499 subtype = (xmlSchemaTypePtr)
3500 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3501 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003502 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003503 subtype = (xmlSchemaTypePtr)
3504 xmlSchemaParseExtension(ctxt, schema, child);
3505 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003506 }
3507 type->subtypes = subtype;
3508 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003509 xmlSchemaPErr2(ctxt, node, child,
3510 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3511 "SimpleContent %s has unexpected content\n",
3512 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003513 }
3514 return (type);
3515}
3516
3517/**
3518 * xmlSchemaParseComplexContent:
3519 * @ctxt: a schema validation context
3520 * @schema: the schema being built
3521 * @node: a subtree containing XML Schema informations
3522 *
3523 * parse a XML schema ComplexContent definition
3524 * *WARNING* this interface is highly subject to change
3525 *
3526 * Returns the type definition or NULL in case of error
3527 */
3528static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003529xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3530 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003531{
3532 xmlSchemaTypePtr type, subtype;
3533 xmlNodePtr child = NULL;
3534 xmlChar name[30];
3535
3536 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3537 return (NULL);
3538
3539
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003540 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003541 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003542 if (type == NULL)
3543 return (NULL);
3544 type->node = node;
3545 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003546 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003547
3548 child = node->children;
3549 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003550 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3551 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003552 }
3553 subtype = NULL;
3554 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003555 subtype = (xmlSchemaTypePtr)
3556 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003558 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003559 subtype = (xmlSchemaTypePtr)
3560 xmlSchemaParseExtension(ctxt, schema, child);
3561 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003562 }
3563 type->subtypes = subtype;
3564 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003565 xmlSchemaPErr2(ctxt, node, child,
3566 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3567 "ComplexContent %s has unexpected content\n",
3568 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003569 }
3570 return (type);
3571}
3572
3573/**
3574 * xmlSchemaParseComplexType:
3575 * @ctxt: a schema validation context
3576 * @schema: the schema being built
3577 * @node: a subtree containing XML Schema informations
3578 *
3579 * parse a XML schema Complex Type definition
3580 * *WARNING* this interface is highly subject to change
3581 *
3582 * Returns the type definition or NULL in case of error
3583 */
3584static xmlSchemaTypePtr
3585xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3586 xmlNodePtr node)
3587{
3588 xmlSchemaTypePtr type, subtype;
3589 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003590 const xmlChar *name;
3591 const xmlChar *oldcontainer;
3592 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003593
3594 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3595 return (NULL);
3596
3597 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003598 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003600
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003601 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3602 name = (const xmlChar *)buf;
3603 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3604 } else {
3605 const xmlChar *local, *ns;
3606
3607 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3608 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003610 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 return (NULL);
3612 }
3613 type->node = node;
3614 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003615 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003616 ctxt->container = name;
3617
3618 child = node->children;
3619 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003620 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3621 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003622 }
3623 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3625 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003627 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3628 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003630 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003631
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003632 if (IS_SCHEMA(child, "all")) {
3633 subtype = xmlSchemaParseAll(ctxt, schema, child);
3634 child = child->next;
3635 } else if (IS_SCHEMA(child, "choice")) {
3636 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3637 child = child->next;
3638 } else if (IS_SCHEMA(child, "sequence")) {
3639 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3640 child = child->next;
3641 } else if (IS_SCHEMA(child, "group")) {
3642 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3643 child = child->next;
3644 }
3645 if (subtype != NULL)
3646 type->subtypes = subtype;
3647 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 }
3649 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 xmlSchemaPErr2(ctxt, node, child,
3651 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3652 "ComplexType %s has unexpected content\n",
3653 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003654 }
3655 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003656 return (type);
3657}
3658
Daniel Veillard4255d502002-04-16 15:50:10 +00003659/**
3660 * xmlSchemaParseSchema:
3661 * @ctxt: a schema validation context
3662 * @node: a subtree containing XML Schema informations
3663 *
3664 * parse a XML schema definition from a node set
3665 * *WARNING* this interface is highly subject to change
3666 *
3667 * Returns the internal XML Schema structure built from the resource or
3668 * NULL in case of error
3669 */
3670static xmlSchemaPtr
3671xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3672{
3673 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003675 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003676 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003677
3678 if ((ctxt == NULL) || (node == NULL))
3679 return (NULL);
3680
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003681 nberrors = ctxt->nberrors;
3682 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003683 if (IS_SCHEMA(node, "schema")) {
3684 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003685 if (schema == NULL)
3686 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003687 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3688 if (val != NULL) {
3689 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3690 } else {
3691 schema->targetNamespace = NULL;
3692 }
3693 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3694 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3695 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003696 if (val != NULL) {
3697 if (xmlStrEqual(val, BAD_CAST "qualified"))
3698 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3699 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3700 xmlSchemaPErr2(ctxt, node, child,
3701 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3702 "Invalid value %s for elementFormDefault\n",
3703 val, NULL);
3704 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003705 } else {
3706 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3707 }
3708 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709 if (val != NULL) {
3710 if (xmlStrEqual(val, BAD_CAST "qualified"))
3711 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3712 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3713 xmlSchemaPErr2(ctxt, node, child,
3714 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3715 "Invalid value %s for attributeFormDefault\n",
3716 val, NULL);
3717 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003718 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003719
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003720 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
3721 } else {
3722 xmlDocPtr doc;
3723
3724 doc = node->doc;
3725
3726 if ((doc != NULL) && (doc->URL != NULL)) {
3727 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3728 XML_SCHEMAP_NOT_SCHEMA,
3729 "File %s is not a schemas", doc->URL, NULL);
3730 } else {
3731 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3732 XML_SCHEMAP_NOT_SCHEMA,
3733 "File is not a schemas", NULL, NULL);
3734 }
3735 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003736 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003737 if (ctxt->nberrors != 0) {
3738 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003739 xmlSchemaFree(schema);
3740 schema = NULL;
3741 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003742 }
3743 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003744#ifdef DEBUG
3745 if (schema == NULL)
3746 xmlGenericError(xmlGenericErrorContext,
3747 "xmlSchemaParse() failed\n");
3748#endif
3749
3750 return (schema);
3751}
3752
3753/************************************************************************
3754 * *
3755 * Validating using Schemas *
3756 * *
3757 ************************************************************************/
3758
3759/************************************************************************
3760 * *
3761 * Reading/Writing Schemas *
3762 * *
3763 ************************************************************************/
3764
3765/**
3766 * xmlSchemaNewParserCtxt:
3767 * @URL: the location of the schema
3768 *
3769 * Create an XML Schemas parse context for that file/resource expected
3770 * to contain an XML Schemas file.
3771 *
3772 * Returns the parser context or NULL in case of error
3773 */
3774xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003775xmlSchemaNewParserCtxt(const char *URL)
3776{
Daniel Veillard4255d502002-04-16 15:50:10 +00003777 xmlSchemaParserCtxtPtr ret;
3778
3779 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003780 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003781
3782 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3783 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003784 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3785 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 return (NULL);
3787 }
3788 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003789 ret->dict = xmlDictCreate();
3790 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003791 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003792 return (ret);
3793}
3794
3795/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003796 * xmlSchemaNewMemParserCtxt:
3797 * @buffer: a pointer to a char array containing the schemas
3798 * @size: the size of the array
3799 *
3800 * Create an XML Schemas parse context for that memory buffer expected
3801 * to contain an XML Schemas file.
3802 *
3803 * Returns the parser context or NULL in case of error
3804 */
3805xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003806xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3807{
Daniel Veillard6045c902002-10-09 21:13:59 +00003808 xmlSchemaParserCtxtPtr ret;
3809
3810 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003811 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003812
3813 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3814 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003815 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3816 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003817 return (NULL);
3818 }
3819 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3820 ret->buffer = buffer;
3821 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003822 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00003823 return (ret);
3824}
3825
3826/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003827 * xmlSchemaNewDocParserCtxt:
3828 * @doc: a preparsed document tree
3829 *
3830 * Create an XML Schemas parse context for that document.
3831 * NB. The document may be modified during the parsing process.
3832 *
3833 * Returns the parser context or NULL in case of error
3834 */
3835xmlSchemaParserCtxtPtr
3836xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3837{
3838 xmlSchemaParserCtxtPtr ret;
3839
3840 if (doc == NULL)
3841 return (NULL);
3842
3843 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3844 if (ret == NULL) {
3845 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3846 NULL);
3847 return (NULL);
3848 }
3849 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3850 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003851 ret->dict = xmlDictCreate();
Daniel Veillard9d751502003-10-29 13:21:47 +00003852
3853 return (ret);
3854}
3855
3856/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003857 * xmlSchemaFreeParserCtxt:
3858 * @ctxt: the schema parser context
3859 *
3860 * Free the resources associated to the schema parser context
3861 */
3862void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003863xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3864{
Daniel Veillard4255d502002-04-16 15:50:10 +00003865 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003866 return;
Daniel Veillard6045c902002-10-09 21:13:59 +00003867 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003868 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003869 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 xmlFree(ctxt);
3871}
3872
3873/************************************************************************
3874 * *
3875 * Building the content models *
3876 * *
3877 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003878
Daniel Veillard4255d502002-04-16 15:50:10 +00003879/**
3880 * xmlSchemaBuildAContentModel:
3881 * @type: the schema type definition
3882 * @ctxt: the schema parser context
3883 * @name: the element name whose content is being built
3884 *
3885 * Generate the automata sequence needed for that type
3886 */
3887static void
3888xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 xmlSchemaParserCtxtPtr ctxt,
3890 const xmlChar * name)
3891{
Daniel Veillard4255d502002-04-16 15:50:10 +00003892 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 xmlGenericError(xmlGenericErrorContext,
3894 "Found unexpected type = NULL in %s content model\n",
3895 name);
3896 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 }
3898 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003899 case XML_SCHEMA_TYPE_ANY:
3900 /* TODO : handle the namespace too */
3901 /* TODO : make that a specific transition type */
3902 TODO ctxt->state =
3903 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3904 BAD_CAST "*", NULL);
3905 break;
3906 case XML_SCHEMA_TYPE_ELEMENT:{
3907 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003908
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003909 /* TODO : handle the namespace too */
3910 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003911
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 if (elem->maxOccurs >= UNBOUNDED) {
3913 if (elem->minOccurs > 1) {
3914 xmlAutomataStatePtr tmp;
3915 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003916
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3918 oldstate,
3919 NULL);
3920 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003921
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003922 counter = xmlAutomataNewCounter(ctxt->am,
3923 elem->minOccurs -
3924 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003925
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003926 if (elem->refDecl != NULL) {
3927 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3928 elem->refDecl,
3929 ctxt,
3930 elem->refDecl->
3931 name);
3932 } else {
3933 ctxt->state =
3934 xmlAutomataNewTransition(ctxt->am,
3935 ctxt->state, NULL,
3936 elem->name, type);
3937 }
3938 tmp = ctxt->state;
3939 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3940 counter);
3941 ctxt->state =
3942 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3943 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003944
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003945 } else {
3946 if (elem->refDecl != NULL) {
3947 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3948 elem->refDecl,
3949 ctxt,
3950 elem->refDecl->
3951 name);
3952 } else {
3953 ctxt->state =
3954 xmlAutomataNewTransition(ctxt->am,
3955 ctxt->state, NULL,
3956 elem->name, type);
3957 }
3958 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3959 oldstate);
3960 if (elem->minOccurs == 0) {
3961 /* basically an elem* */
3962 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3963 ctxt->state);
3964 }
3965 }
3966 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3967 xmlAutomataStatePtr tmp;
3968 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003969
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003970 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3971 oldstate, NULL);
3972 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003973
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003974 counter = xmlAutomataNewCounter(ctxt->am,
3975 elem->minOccurs - 1,
3976 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003977
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003978 if (elem->refDecl != NULL) {
3979 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3980 elem->refDecl, ctxt,
3981 elem->refDecl->name);
3982 } else {
3983 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3984 ctxt->state,
3985 NULL,
3986 elem->name,
3987 type);
3988 }
3989 tmp = ctxt->state;
3990 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3991 counter);
3992 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3993 NULL,
3994 counter);
3995 if (elem->minOccurs == 0) {
3996 /* basically an elem? */
3997 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3998 ctxt->state);
3999 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004000
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004001 } else {
4002 if (elem->refDecl != NULL) {
4003 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4004 elem->refDecl, ctxt,
4005 elem->refDecl->name);
4006 } else {
4007 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4008 ctxt->state,
4009 NULL,
4010 elem->name,
4011 type);
4012 }
4013 if (elem->minOccurs == 0) {
4014 /* basically an elem? */
4015 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4016 ctxt->state);
4017 }
4018 }
4019 break;
4020 }
4021 case XML_SCHEMA_TYPE_SEQUENCE:{
4022 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004023
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004024 /*
4025 * If max and min occurances are default (1) then
4026 * simply iterate over the subtypes
4027 */
4028 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4029 subtypes = type->subtypes;
4030 while (subtypes != NULL) {
4031 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4032 subtypes = subtypes->next;
4033 }
4034 } else {
4035 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004036
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004037 if (type->maxOccurs >= UNBOUNDED) {
4038 if (type->minOccurs > 1) {
4039 xmlAutomataStatePtr tmp;
4040 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004041
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004042 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4043 oldstate,
4044 NULL);
4045 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004046
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004047 counter = xmlAutomataNewCounter(ctxt->am,
4048 type->
4049 minOccurs - 1,
4050 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004051
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004052 subtypes = type->subtypes;
4053 while (subtypes != NULL) {
4054 xmlSchemaBuildAContentModel(subtypes, ctxt,
4055 name);
4056 subtypes = subtypes->next;
4057 }
4058 tmp = ctxt->state;
4059 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4060 oldstate, counter);
4061 ctxt->state =
4062 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4063 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004064
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 } else {
4066 subtypes = type->subtypes;
4067 while (subtypes != NULL) {
4068 xmlSchemaBuildAContentModel(subtypes, ctxt,
4069 name);
4070 subtypes = subtypes->next;
4071 }
4072 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4073 oldstate);
4074 if (type->minOccurs == 0) {
4075 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4076 ctxt->state);
4077 }
4078 }
4079 } else if ((type->maxOccurs > 1)
4080 || (type->minOccurs > 1)) {
4081 xmlAutomataStatePtr tmp;
4082 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004083
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4085 oldstate,
4086 NULL);
4087 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004088
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004089 counter = xmlAutomataNewCounter(ctxt->am,
4090 type->minOccurs -
4091 1,
4092 type->maxOccurs -
4093 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004095 subtypes = type->subtypes;
4096 while (subtypes != NULL) {
4097 xmlSchemaBuildAContentModel(subtypes, ctxt,
4098 name);
4099 subtypes = subtypes->next;
4100 }
4101 tmp = ctxt->state;
4102 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4103 counter);
4104 ctxt->state =
4105 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4106 counter);
4107 if (type->minOccurs == 0) {
4108 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4109 ctxt->state);
4110 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004111
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004112 } else {
4113 subtypes = type->subtypes;
4114 while (subtypes != NULL) {
4115 xmlSchemaBuildAContentModel(subtypes, ctxt,
4116 name);
4117 subtypes = subtypes->next;
4118 }
4119 if (type->minOccurs == 0) {
4120 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4121 ctxt->state);
4122 }
4123 }
4124 }
4125 break;
4126 }
4127 case XML_SCHEMA_TYPE_CHOICE:{
4128 xmlSchemaTypePtr subtypes;
4129 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004130
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004131 start = ctxt->state;
4132 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004133
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004134 /*
4135 * iterate over the subtypes and remerge the end with an
4136 * epsilon transition
4137 */
4138 if (type->maxOccurs == 1) {
4139 subtypes = type->subtypes;
4140 while (subtypes != NULL) {
4141 ctxt->state = start;
4142 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4143 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4144 subtypes = subtypes->next;
4145 }
4146 } else {
4147 int counter;
4148 xmlAutomataStatePtr hop;
4149 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4150 UNBOUNDED : type->maxOccurs - 1;
4151 int minOccurs =
4152 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004153
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004154 /*
4155 * use a counter to keep track of the number of transtions
4156 * which went through the choice.
4157 */
4158 counter =
4159 xmlAutomataNewCounter(ctxt->am, minOccurs,
4160 maxOccurs);
4161 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004162
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004163 subtypes = type->subtypes;
4164 while (subtypes != NULL) {
4165 ctxt->state = start;
4166 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4167 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4168 subtypes = subtypes->next;
4169 }
4170 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4171 counter);
4172 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4173 counter);
4174 }
4175 if (type->minOccurs == 0) {
4176 xmlAutomataNewEpsilon(ctxt->am, start, end);
4177 }
4178 ctxt->state = end;
4179 break;
4180 }
4181 case XML_SCHEMA_TYPE_ALL:{
4182 xmlAutomataStatePtr start;
4183 xmlSchemaTypePtr subtypes;
4184 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4185 int lax;
4186
4187 subtypes = type->subtypes;
4188 if (subtypes == NULL)
4189 break;
4190 start = ctxt->state;
4191 while (subtypes != NULL) {
4192 ctxt->state = start;
4193 elem = (xmlSchemaElementPtr) subtypes;
4194
4195 /* TODO : handle the namespace too */
4196 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4197 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4198 ctxt->state, elem->name, 1,
4199 1, subtypes);
4200 } else {
4201 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4202 ctxt->state, elem->name,
4203 elem->minOccurs,
4204 elem->maxOccurs,
4205 subtypes);
4206 }
4207 subtypes = subtypes->next;
4208 }
4209 lax = type->minOccurs == 0;
4210 ctxt->state =
4211 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4212 lax);
4213 break;
4214 }
4215 case XML_SCHEMA_TYPE_RESTRICTION:
4216 if (type->subtypes != NULL)
4217 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4218 break;
4219 case XML_SCHEMA_TYPE_EXTENSION:
4220 if (type->baseType != NULL) {
4221 xmlSchemaTypePtr subtypes;
4222
4223 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4224 subtypes = type->subtypes;
4225 while (subtypes != NULL) {
4226 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4227 subtypes = subtypes->next;
4228 }
4229 } else if (type->subtypes != NULL)
4230 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4231 break;
4232 case XML_SCHEMA_TYPE_GROUP:
4233 if (type->subtypes == NULL) {
4234 }
4235 case XML_SCHEMA_TYPE_COMPLEX:
4236 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4237 if (type->subtypes != NULL)
4238 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4239 break;
4240 default:
4241 xmlGenericError(xmlGenericErrorContext,
4242 "Found unexpected type %d in %s content model\n",
4243 type->type, name);
4244 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004245 }
4246}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247
Daniel Veillard4255d502002-04-16 15:50:10 +00004248/**
4249 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004250 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004251 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004252 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004253 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004254 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 */
4256static void
4257xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004258 xmlSchemaParserCtxtPtr ctxt,
4259 const xmlChar * name)
4260{
Daniel Veillard4255d502002-04-16 15:50:10 +00004261 xmlAutomataStatePtr start;
4262
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004265 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004266 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4267 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004268 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004270 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004271 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4272 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004273 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004274
4275#ifdef DEBUG_CONTENT
4276 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004277 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004278#endif
4279
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 ctxt->am = xmlNewAutomata();
4281 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004282 xmlGenericError(xmlGenericErrorContext,
4283 "Cannot create automata for elem %s\n", name);
4284 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 }
4286 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4287 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4288 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004289 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004290 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004291 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4292 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004293 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4295 "Content model of %s is not determinist:\n", name,
4296 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004297 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004298#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004299 xmlGenericError(xmlGenericErrorContext,
4300 "Content model of %s:\n", name);
4301 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004302#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004303 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004304 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004305 xmlFreeAutomata(ctxt->am);
4306 ctxt->am = NULL;
4307}
4308
4309/**
4310 * xmlSchemaRefFixupCallback:
4311 * @elem: the schema element context
4312 * @ctxt: the schema parser context
4313 *
4314 * Free the resources associated to the schema parser context
4315 */
4316static void
4317xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318 xmlSchemaParserCtxtPtr ctxt,
4319 const xmlChar * name,
4320 const xmlChar * context ATTRIBUTE_UNUSED,
4321 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004322{
4323 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004324 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004325 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004326 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004327
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004328 if (elem->subtypes != NULL) {
4329 xmlSchemaPErr(ctxt, elem->node,
4330 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4331 "Schemas: element %s have both ref and subtype\n",
4332 name, NULL);
4333 return;
4334 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004335 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004336
4337 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004338 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4339 "Schemas: element %s ref to %s not found\n",
4340 name, elem->ref);
4341 return;
4342 }
4343 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004345 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004346
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347 if (elem->subtypes != NULL) {
4348 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4349 "Schemas: element %s have both type and subtype\n",
4350 name, NULL);
4351 return;
4352 }
4353 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4354 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004355
4356 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004357 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4358 "Schemas: element %s type %s not found\n", name,
4359 elem->namedType);
4360 return;
4361 }
4362 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 }
4364}
4365
4366/**
4367 * xmlSchemaTypeFixup:
4368 * @typeDecl: the schema type definition
4369 * @ctxt: the schema parser context
4370 *
4371 * Fixes the content model of the type.
4372 */
4373static void
4374xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004375 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004376{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004377 if (typeDecl == NULL)
4378 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004380 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004382 switch (typeDecl->type) {
4383 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4384 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4385 if (typeDecl->subtypes != NULL)
4386 typeDecl->contentType =
4387 typeDecl->subtypes->contentType;
4388 break;
4389 }
4390 case XML_SCHEMA_TYPE_RESTRICTION:{
4391 if (typeDecl->subtypes != NULL)
4392 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004393
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 if (typeDecl->base != NULL) {
4395 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004396
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004397 baseType =
4398 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4399 typeDecl->baseNs);
4400 if (baseType == NULL) {
4401 xmlSchemaPErr(ctxt, typeDecl->node,
4402 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 name, typeDecl->base);
4405 }
4406 typeDecl->baseType = baseType;
4407 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004408 if (typeDecl->subtypes == NULL)
4409 if (typeDecl->baseType != NULL)
4410 typeDecl->contentType =
4411 typeDecl->baseType->contentType;
4412 else
4413 /* 1.1.1 */
4414 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004415 else if ((typeDecl->subtypes->subtypes == NULL) &&
4416 ((typeDecl->subtypes->type ==
4417 XML_SCHEMA_TYPE_ALL)
4418 || (typeDecl->subtypes->type ==
4419 XML_SCHEMA_TYPE_SEQUENCE)))
4420 /* 1.1.2 */
4421 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4422 else if ((typeDecl->subtypes->type ==
4423 XML_SCHEMA_TYPE_CHOICE)
4424 && (typeDecl->subtypes->subtypes == NULL))
4425 /* 1.1.3 */
4426 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4427 else {
4428 /* 1.2 and 2.X are applied at the other layer */
4429 typeDecl->contentType =
4430 XML_SCHEMA_CONTENT_ELEMENTS;
4431 }
4432 break;
4433 }
4434 case XML_SCHEMA_TYPE_EXTENSION:{
4435 xmlSchemaContentType explicitContentType;
4436 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004437
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004438 if (typeDecl->base != NULL) {
4439 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004440
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 baseType =
4442 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4443 typeDecl->baseNs);
4444 if (baseType == NULL) {
4445 xmlSchemaPErr(ctxt, typeDecl->node,
4446 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004447 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 name, typeDecl->base);
4449 }
4450 typeDecl->baseType = baseType;
4451 }
4452 if (typeDecl->subtypes != NULL)
4453 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004455 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4456 if (typeDecl->subtypes == NULL)
4457 /* 1.1.1 */
4458 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4459 else if ((typeDecl->subtypes->subtypes == NULL) &&
4460 ((typeDecl->subtypes->type ==
4461 XML_SCHEMA_TYPE_ALL)
4462 || (typeDecl->subtypes->type ==
4463 XML_SCHEMA_TYPE_SEQUENCE)))
4464 /* 1.1.2 */
4465 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4466 else if ((typeDecl->subtypes->type ==
4467 XML_SCHEMA_TYPE_CHOICE)
4468 && (typeDecl->subtypes->subtypes == NULL))
4469 /* 1.1.3 */
4470 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004471
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004472 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4473 typeDecl->baseNs);
4474 if (base == NULL) {
4475 xmlSchemaPErr(ctxt, typeDecl->node,
4476 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4477 "Schemas: base type %s of type %s not found\n",
4478 typeDecl->base, name);
4479 return;
4480 }
4481 xmlSchemaTypeFixup(base, ctxt, NULL);
4482 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4483 /* 2.1 */
4484 typeDecl->contentType = base->contentType;
4485 } else if (base->contentType ==
4486 XML_SCHEMA_CONTENT_EMPTY) {
4487 /* 2.2 imbitable ! */
4488 typeDecl->contentType =
4489 XML_SCHEMA_CONTENT_ELEMENTS;
4490 } else {
4491 /* 2.3 imbitable pareil ! */
4492 typeDecl->contentType =
4493 XML_SCHEMA_CONTENT_ELEMENTS;
4494 }
4495 break;
4496 }
4497 case XML_SCHEMA_TYPE_COMPLEX:{
4498 if (typeDecl->subtypes == NULL) {
4499 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4500 } else {
4501 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4502 typeDecl->contentType =
4503 XML_SCHEMA_CONTENT_MIXED;
4504 else {
4505 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4506 NULL);
4507 if (typeDecl->subtypes != NULL)
4508 typeDecl->contentType =
4509 typeDecl->subtypes->contentType;
4510 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004511 if (typeDecl->attributes == NULL)
4512 typeDecl->attributes =
4513 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004514 }
4515 break;
4516 }
4517 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4518 if (typeDecl->subtypes == NULL) {
4519 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4520 } else {
4521 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4522 typeDecl->contentType =
4523 XML_SCHEMA_CONTENT_MIXED;
4524 else {
4525 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4526 NULL);
4527 if (typeDecl->subtypes != NULL)
4528 typeDecl->contentType =
4529 typeDecl->subtypes->contentType;
4530 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004531 if (typeDecl->attributes == NULL)
4532 typeDecl->attributes =
4533 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004534 }
4535 break;
4536 }
4537 case XML_SCHEMA_TYPE_SEQUENCE:
4538 case XML_SCHEMA_TYPE_GROUP:
4539 case XML_SCHEMA_TYPE_ALL:
4540 case XML_SCHEMA_TYPE_CHOICE:
4541 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4542 break;
4543 case XML_SCHEMA_TYPE_BASIC:
4544 case XML_SCHEMA_TYPE_ANY:
4545 case XML_SCHEMA_TYPE_FACET:
4546 case XML_SCHEMA_TYPE_SIMPLE:
4547 case XML_SCHEMA_TYPE_UR:
4548 case XML_SCHEMA_TYPE_ELEMENT:
4549 case XML_SCHEMA_TYPE_ATTRIBUTE:
4550 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4551 case XML_SCHEMA_TYPE_NOTATION:
4552 case XML_SCHEMA_TYPE_LIST:
4553 case XML_SCHEMA_TYPE_UNION:
4554 case XML_SCHEMA_FACET_MININCLUSIVE:
4555 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4556 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4557 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4558 case XML_SCHEMA_FACET_TOTALDIGITS:
4559 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4560 case XML_SCHEMA_FACET_PATTERN:
4561 case XML_SCHEMA_FACET_ENUMERATION:
4562 case XML_SCHEMA_FACET_WHITESPACE:
4563 case XML_SCHEMA_FACET_LENGTH:
4564 case XML_SCHEMA_FACET_MAXLENGTH:
4565 case XML_SCHEMA_FACET_MINLENGTH:
4566 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004567 if (typeDecl->subtypes != NULL)
4568 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004569 break;
4570 }
4571 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004572#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004573 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004574 xmlGenericError(xmlGenericErrorContext,
4575 "Type of %s : %s:%d :", name,
4576 typeDecl->node->doc->URL,
4577 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004578 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004579 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004580 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004581 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004582 case XML_SCHEMA_CONTENT_SIMPLE:
4583 xmlGenericError(xmlGenericErrorContext, "simple\n");
4584 break;
4585 case XML_SCHEMA_CONTENT_ELEMENTS:
4586 xmlGenericError(xmlGenericErrorContext, "elements\n");
4587 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004588 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004589 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4590 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004591 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004592 xmlGenericError(xmlGenericErrorContext, "empty\n");
4593 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004594 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004595 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4596 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004597 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004598 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4599 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004600 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004601 xmlGenericError(xmlGenericErrorContext, "basic\n");
4602 break;
4603 default:
4604 xmlGenericError(xmlGenericErrorContext,
4605 "not registered !!!\n");
4606 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004607 }
4608#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004609}
4610
4611/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004612 * xmlSchemaCheckFacet:
4613 * @facet: the facet
4614 * @typeDecl: the schema type definition
4615 * @ctxt: the schema parser context or NULL
4616 * @name: name of the type
4617 *
4618 * Checks the default values types, especially for facets
4619 *
4620 * Returns 0 if okay or -1 in cae of error
4621 */
4622int
4623xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004624 xmlSchemaTypePtr typeDecl,
4625 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004626{
4627 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4628 int ret = 0;
4629
4630 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 nonNegativeIntegerType =
4632 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4633 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004634 }
4635 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004636 case XML_SCHEMA_FACET_MININCLUSIVE:
4637 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4638 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4639 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4640 /*
4641 * Okay we need to validate the value
4642 * at that point.
4643 */
4644 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004646 vctxt = xmlSchemaNewValidCtxt(NULL);
4647 if (vctxt == NULL)
4648 break;
4649 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4650 facet->value);
4651 facet->val = vctxt->value;
4652 vctxt->value = NULL;
4653 if (facet->val == NULL) {
4654 /* error code */
4655 if (ctxt != NULL) {
4656 xmlSchemaPErr(ctxt, facet->node,
4657 XML_SCHEMAP_INVALID_FACET,
4658 "Schemas: type %s facet value %s invalid\n",
4659 name, facet->value);
4660 }
4661 ret = -1;
4662 }
4663 xmlSchemaFreeValidCtxt(vctxt);
4664 break;
4665 }
4666 case XML_SCHEMA_FACET_ENUMERATION:{
4667 /*
4668 * Okay we need to validate the value
4669 * at that point.
4670 */
4671 xmlSchemaValidCtxtPtr vctxt;
4672 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004673
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004674 vctxt = xmlSchemaNewValidCtxt(NULL);
4675 if (vctxt == NULL)
4676 break;
4677 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4678 facet->value);
4679 if (tmp != 0) {
4680 if (ctxt != NULL) {
4681 xmlSchemaPErr(ctxt, facet->node,
4682 XML_SCHEMAP_INVALID_ENUM,
4683 "Schemas: type %s enumeration value %s invalid\n",
4684 name, facet->value);
4685 }
4686 ret = -1;
4687 }
4688 xmlSchemaFreeValidCtxt(vctxt);
4689 break;
4690 }
4691 case XML_SCHEMA_FACET_PATTERN:
4692 facet->regexp = xmlRegexpCompile(facet->value);
4693 if (facet->regexp == NULL) {
4694 xmlSchemaPErr(ctxt, typeDecl->node,
4695 XML_SCHEMAP_REGEXP_INVALID,
4696 "Schemas: type %s facet regexp %s invalid\n",
4697 name, facet->value);
4698 ret = -1;
4699 }
4700 break;
4701 case XML_SCHEMA_FACET_TOTALDIGITS:
4702 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4703 case XML_SCHEMA_FACET_LENGTH:
4704 case XML_SCHEMA_FACET_MAXLENGTH:
4705 case XML_SCHEMA_FACET_MINLENGTH:{
4706 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004707
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004708 tmp =
4709 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4710 facet->value,
4711 &facet->val);
4712 if (tmp != 0) {
4713 /* error code */
4714 if (ctxt != NULL) {
4715 xmlSchemaPErr(ctxt, facet->node,
4716 XML_SCHEMAP_INVALID_FACET_VALUE,
4717 "Schemas: type %s facet value %s invalid\n",
4718 name, facet->value);
4719 }
4720 ret = -1;
4721 }
4722 break;
4723 }
4724 case XML_SCHEMA_FACET_WHITESPACE:{
4725 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4726 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4727 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4728 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4729 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4730 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4731 } else {
4732 if (ctxt != NULL) {
4733 xmlSchemaPErr(ctxt, facet->node,
4734 XML_SCHEMAP_INVALID_WHITE_SPACE,
4735 "Schemas: type %s whiteSpace value %s invalid\n",
4736 name, facet->value);
4737 }
4738 ret = -1;
4739 }
4740 }
4741 default:
4742 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004743 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004744 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004745}
4746
4747/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004748 * xmlSchemaCheckDefaults:
4749 * @typeDecl: the schema type definition
4750 * @ctxt: the schema parser context
4751 *
4752 * Checks the default values types, especially for facets
4753 */
4754static void
4755xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004756 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004757{
Daniel Veillard4255d502002-04-16 15:50:10 +00004758 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004759 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004760 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004761 if (typeDecl->facets != NULL) {
4762 xmlSchemaFacetPtr facet = typeDecl->facets;
4763
4764 while (facet != NULL) {
4765 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4766 facet = facet->next;
4767 }
4768 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004769 }
4770}
4771
4772/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004773 * xmlSchemaAttrGrpFixup:
4774 * @attrgrpDecl: the schema attribute definition
4775 * @ctxt: the schema parser context
4776 * @name: the attribute name
4777 *
4778 * Fixes finish doing the computations on the attributes definitions
4779 */
4780static void
4781xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004783{
4784 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004785 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004786 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004787 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004788 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004790
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004791 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4792 attrgrpDecl->refNs);
4793 if (ref == NULL) {
4794 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4795 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4796 "Schemas: attribute group %s reference %s not found\n",
4797 name, attrgrpDecl->ref);
4798 return;
4799 }
4800 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4801 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004802 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004803 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4804 "Schemas: attribute %s has no attributes nor reference\n",
4805 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004806 }
4807}
4808
4809/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 * xmlSchemaAttrFixup:
4811 * @attrDecl: the schema attribute definition
4812 * @ctxt: the schema parser context
4813 * @name: the attribute name
4814 *
4815 * Fixes finish doing the computations on the attributes definitions
4816 */
4817static void
4818xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004820{
4821 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004823 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004825 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004826 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4829 attrDecl->typeNs);
4830 if (type == NULL) {
4831 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4832 "Schemas: attribute %s type %s not found\n",
4833 name, attrDecl->typeName);
4834 }
4835 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004836 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004837 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004838
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004839 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4840 attrDecl->refNs);
4841 if (ref == NULL) {
4842 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4843 "Schemas: attribute %s reference %s not found\n",
4844 name, attrDecl->ref);
4845 return;
4846 }
4847 xmlSchemaAttrFixup(ref, ctxt, NULL);
4848 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004849 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004850 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4851 "Schemas: attribute %s has no type nor reference\n",
4852 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004853 }
4854}
4855
4856/**
4857 * xmlSchemaParse:
4858 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004859 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004860 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004861 * XML Shema struture which can be used to validate instances.
4862 * *WARNING* this interface is highly subject to change
4863 *
4864 * Returns the internal XML Schema structure built from the resource or
4865 * NULL in case of error
4866 */
4867xmlSchemaPtr
4868xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4869{
4870 xmlSchemaPtr ret = NULL;
4871 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004872 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004873 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004874
4875 xmlSchemaInitTypes();
4876
Daniel Veillard6045c902002-10-09 21:13:59 +00004877 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004878 return (NULL);
4879
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004880 nberrors = ctxt->nberrors;
4881 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004882 ctxt->counter = 0;
4883 ctxt->container = NULL;
4884
4885 /*
4886 * First step is to parse the input document into an DOM/Infoset
4887 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004888 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004889 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4890 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004891 if (doc == NULL) {
4892 xmlSchemaPErr(ctxt, NULL,
4893 XML_SCHEMAP_FAILED_LOAD,
4894 "xmlSchemaParse: could not load %s\n",
4895 ctxt->URL, NULL);
4896 return (NULL);
4897 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004898 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004899 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4900 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004901 if (doc == NULL) {
4902 xmlSchemaPErr(ctxt, NULL,
4903 XML_SCHEMAP_FAILED_PARSE,
4904 "xmlSchemaParse: could not parse\n",
4905 NULL, NULL);
4906 return (NULL);
4907 }
4908 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4909 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard9d751502003-10-29 13:21:47 +00004910 } else if (ctxt->doc != NULL) {
4911 doc = ctxt->doc;
Daniel Veillard6045c902002-10-09 21:13:59 +00004912 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004913 xmlSchemaPErr(ctxt, NULL,
4914 XML_SCHEMAP_NOTHING_TO_PARSE,
4915 "xmlSchemaParse: could not parse\n",
4916 NULL, NULL);
4917 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004918 }
4919
4920 /*
4921 * Then extract the root and Schema parse it
4922 */
4923 root = xmlDocGetRootElement(doc);
4924 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004925 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4926 XML_SCHEMAP_NOROOT,
4927 "schemas has no root", NULL, NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004928 xmlFreeDoc(doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929 return (NULL);
4930 }
4931
4932 /*
4933 * Remove all the blank text nodes
4934 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004935 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00004936
4937 /*
4938 * Then do the parsing for good
4939 */
4940 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004941 if (ret == NULL) {
4942 xmlFreeDoc(doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004943 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004944 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004945 ret->doc = doc;
4946
4947 /*
4948 * Then fix all the references.
4949 */
4950 ctxt->schema = ret;
4951 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004952 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004953
4954 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004955 * Then fixup all attributes declarations
4956 */
4957 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4958
4959 /*
4960 * Then fixup all attributes group declarations
4961 */
4962 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4963 ctxt);
4964
4965 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00004966 * Then fixup all types properties
4967 */
4968 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4969
4970 /*
4971 * Then build the content model for all elements
4972 */
4973 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004974 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004975
4976 /*
4977 * Then check the defaults part of the type like facets values
4978 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004979 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4980 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004981
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004982 if (ctxt->nberrors != 0) {
4983 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004984 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004985 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004986 return (ret);
4987}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004988
Daniel Veillard4255d502002-04-16 15:50:10 +00004989/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004990 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004991 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004992 * @err: the error callback
4993 * @warn: the warning callback
4994 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004995 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004996 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004997 */
4998void
4999xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005000 xmlSchemaValidityErrorFunc err,
5001 xmlSchemaValidityWarningFunc warn, void *ctx)
5002{
Daniel Veillard4255d502002-04-16 15:50:10 +00005003 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005004 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005005 ctxt->error = err;
5006 ctxt->warning = warn;
5007 ctxt->userData = ctx;
5008}
5009
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005010/**
5011 * xmlSchemaFacetTypeToString:
5012 * @type: the facet type
5013 *
5014 * Convert the xmlSchemaTypeType to a char string.
5015 *
5016 * Returns the char string representation of the facet type if the
5017 * type is a facet and an "Internal Error" string otherwise.
5018 */
5019static const char *
5020xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5021{
5022 switch (type) {
5023 case XML_SCHEMA_FACET_PATTERN:
5024 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005025 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005026 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005027 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005028 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005030 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005031 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005032 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005033 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005034 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005035 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005036 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005037 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005038 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005039 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005040 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005041 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005042 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005043 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005044 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005045 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005046 return ("fractionDigits");
5047 default:
5048 break;
5049 }
5050 return ("Internal Error");
5051}
5052
5053/**
5054 * xmlSchemaValidateFacets:
5055 * @ctxt: a schema validation context
5056 * @base: the base type
5057 * @facets: the list of facets to check
5058 * @value: the lexical repr of the value to validate
5059 * @val: the precomputed value
5060 *
5061 * Check a value against all facet conditions
5062 *
5063 * Returns 0 if the element is schemas valid, a positive error code
5064 * number otherwise and -1 in case of internal or API error.
5065 */
5066static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005067xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5068 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005069 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005070{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005071 int ret = 0;
5072 int tmp = 0;
5073 xmlSchemaTypeType type;
5074 xmlSchemaFacetPtr facet = facets;
5075
5076 while (facet != NULL) {
5077 type = facet->type;
5078 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005079 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005080
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005081 while (facet != NULL) {
5082 tmp =
5083 xmlSchemaValidateFacet(base, facet, value,
5084 ctxt->value);
5085 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005086 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087 }
5088 facet = facet->next;
5089 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005090 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005091 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005092
5093 if (tmp != 0) {
5094 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005095 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 +00005096 }
5097 if (facet != NULL)
5098 facet = facet->next;
5099 }
5100 return (ret);
5101}
5102
Daniel Veillard4255d502002-04-16 15:50:10 +00005103/************************************************************************
5104 * *
5105 * Simple type validation *
5106 * *
5107 ************************************************************************/
5108
5109/**
5110 * xmlSchemaValidateSimpleValue:
5111 * @ctxt: a schema validation context
5112 * @type: the type declaration
5113 * @value: the value to validate
5114 *
5115 * Validate a value against a simple type
5116 *
5117 * Returns 0 if the value is valid, a positive error code
5118 * number otherwise and -1 in case of internal or API error.
5119 */
5120static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005121xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005122 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005123{
Daniel Veillard4255d502002-04-16 15:50:10 +00005124 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005125
Daniel Veillard4255d502002-04-16 15:50:10 +00005126 /*
5127 * First normalize the value accordingly to Schema Datatype
5128 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5129 */
5130 /*
5131 * Then check the normalized value against the lexical space of the
5132 * type.
5133 */
5134 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005135 if (ctxt->value != NULL) {
5136 xmlSchemaFreeValue(ctxt->value);
5137 ctxt->value = NULL;
5138 }
5139 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5140 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005141 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005142 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 +00005143 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005144 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005145 xmlSchemaTypePtr base;
5146 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005147
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005148 base = type->baseType;
5149 if (base != NULL) {
5150 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5151 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005152 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005153 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005154
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005155 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005156 * Do not validate facets or attributes when working on
5157 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005158 */
5159 if (ctxt->schema != NULL) {
5160 if (ret == 0) {
5161 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005162 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005163 }
5164 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005165 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005166 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005167
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005168 base = type->subtypes;
5169 if (base != NULL) {
5170 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5171 } else {
5172 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005173 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005174 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005175 const xmlChar *cur, *end;
5176 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005178
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005179 base = type->subtypes;
5180 if (base == NULL) {
5181 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5182 "Internal: List type %s has no base type\n",
5183 type->name, NULL);
5184 return (-1);
5185 }
5186 cur = value;
5187 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005188 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005189 cur++;
5190 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005191 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005192 end++;
5193 if (end == cur)
5194 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005195 tmp = xmlStrndup(cur, end - cur);
5196 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
5197 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005198 if (ret2 != 0)
5199 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005200 cur = end;
5201 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005202 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005203 TODO
5204 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005206}
5207
5208/************************************************************************
5209 * *
5210 * DOM Validation code *
5211 * *
5212 ************************************************************************/
5213
5214static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005215 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005216static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005217 xmlNodePtr elem,
5218 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005219static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005220 xmlNodePtr elem,
5221 xmlSchemaElementPtr elemDecl,
5222 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005223
5224/**
5225 * xmlSchemaRegisterAttributes:
5226 * @ctxt: a schema validation context
5227 * @attrs: a list of attributes
5228 *
5229 * Register the list of attributes as the set to be validated on that element
5230 *
5231 * Returns -1 in case of error, 0 otherwise
5232 */
5233static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005234xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5235{
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005237 if ((attrs->ns != NULL) &&
5238 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5239 attrs = attrs->next;
5240 continue;
5241 }
5242 if (ctxt->attrNr >= ctxt->attrMax) {
5243 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005245 ctxt->attrMax *= 2;
5246 tmp = (xmlSchemaAttrStatePtr)
5247 xmlRealloc(ctxt->attr, ctxt->attrMax *
5248 sizeof(xmlSchemaAttrState));
5249 if (tmp == NULL) {
5250 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5251 ctxt->attrMax /= 2;
5252 return (-1);
5253 }
5254 ctxt->attr = tmp;
5255 }
5256 ctxt->attr[ctxt->attrNr].attr = attrs;
5257 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5258 ctxt->attrNr++;
5259 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005262}
5263
5264/**
5265 * xmlSchemaCheckAttributes:
5266 * @ctxt: a schema validation context
5267 * @node: the node carrying it.
5268 *
5269 * Check that the registered set of attributes on the current node
5270 * has been properly validated.
5271 *
5272 * Returns 0 if validity constraints are met, 1 otherwise.
5273 */
5274static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005275xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5276{
Daniel Veillard4255d502002-04-16 15:50:10 +00005277 int ret = 0;
5278 int i;
5279
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005280 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5281 if (ctxt->attr[i].attr == NULL)
5282 break;
5283 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5284 ret = 1;
5285 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5286 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005287 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005288 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005289}
5290
5291/**
5292 * xmlSchemaValidateSimpleContent:
5293 * @ctxt: a schema validation context
5294 * @elem: an element
5295 * @type: the type declaration
5296 *
5297 * Validate the content of an element expected to be a simple type
5298 *
5299 * Returns 0 if the element is schemas valid, a positive error code
5300 * number otherwise and -1 in case of internal or API error.
5301 */
5302static int
5303xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005304 xmlNodePtr node ATTRIBUTE_UNUSED)
5305{
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 xmlNodePtr child;
5307 xmlSchemaTypePtr type, base;
5308 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005309 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005310
5311 child = ctxt->node;
5312 type = ctxt->type;
5313
5314 /*
5315 * Validation Rule: Element Locally Valid (Type): 3.1.3
5316 */
5317 value = xmlNodeGetContent(child);
5318 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5319 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005320 case XML_SCHEMA_TYPE_RESTRICTION:{
5321 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005322
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005323 base = type->baseType;
5324 if (base != NULL) {
5325 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5326 } else {
5327 TODO}
5328 if (ret == 0) {
5329 facet = type->facets;
5330 ret =
5331 xmlSchemaValidateFacets(ctxt, base, facet, value);
5332 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005333 if ((ret == 0) && (type->attributes != NULL)) {
5334 ret = xmlSchemaValidateAttributes(ctxt, node,
5335 type->attributes);
5336 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005337 break;
5338 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005339 case XML_SCHEMA_TYPE_EXTENSION:{
5340 TODO
5341 break;
5342 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005343 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005344 TODO
5345 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005346 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005347 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005348
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005349 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005350}
5351
5352/**
5353 * xmlSchemaValidateCheckNodeList
5354 * @nodelist: the list of nodes
5355 *
5356 * Check the node list is only made of text nodes and entities pointing
5357 * to text nodes
5358 *
5359 * Returns 1 if true, 0 if false and -1 in case of error
5360 */
5361static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005362xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5363{
Daniel Veillard4255d502002-04-16 15:50:10 +00005364 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005365 if (nodelist->type == XML_ENTITY_REF_NODE) {
5366 TODO /* implement recursion in the entity content */
5367 }
5368 if ((nodelist->type != XML_TEXT_NODE) &&
5369 (nodelist->type != XML_COMMENT_NODE) &&
5370 (nodelist->type != XML_PI_NODE) &&
5371 (nodelist->type != XML_PI_NODE)) {
5372 return (0);
5373 }
5374 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005375 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005377}
5378
5379/**
5380 * xmlSchemaSkipIgnored:
5381 * @ctxt: a schema validation context
5382 * @type: the current type context
5383 * @node: the top node.
5384 *
5385 * Skip ignorable nodes in that context
5386 *
5387 * Returns the new sibling
5388 * number otherwise and -1 in case of internal or API error.
5389 */
5390static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005391xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005392 xmlSchemaTypePtr type, xmlNodePtr node)
5393{
Daniel Veillard4255d502002-04-16 15:50:10 +00005394 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005395
Daniel Veillard4255d502002-04-16 15:50:10 +00005396 /*
5397 * TODO complete and handle entities
5398 */
5399 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005400 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005401 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005402 ((node->type == XML_COMMENT_NODE) ||
5403 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5404 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5405 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5406 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005407 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005408 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409}
5410
5411/**
5412 * xmlSchemaValidateCallback:
5413 * @ctxt: a schema validation context
5414 * @name: the name of the element detected (might be NULL)
5415 * @type: the type
5416 *
5417 * A transition has been made in the automata associated to an element
5418 * content model
5419 */
5420static void
5421xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005422 const xmlChar * name ATTRIBUTE_UNUSED,
5423 xmlSchemaTypePtr type, xmlNodePtr node)
5424{
Daniel Veillard4255d502002-04-16 15:50:10 +00005425 xmlSchemaTypePtr oldtype = ctxt->type;
5426 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005427
Daniel Veillard4255d502002-04-16 15:50:10 +00005428#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005429 xmlGenericError(xmlGenericErrorContext,
5430 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005431 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005432#endif
5433 ctxt->type = type;
5434 ctxt->node = node;
5435 xmlSchemaValidateContent(ctxt, node);
5436 ctxt->type = oldtype;
5437 ctxt->node = oldnode;
5438}
5439
5440
5441#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005442
Daniel Veillard4255d502002-04-16 15:50:10 +00005443/**
5444 * xmlSchemaValidateSimpleRestrictionType:
5445 * @ctxt: a schema validation context
5446 * @node: the top node.
5447 *
5448 * Validate the content of a restriction type.
5449 *
5450 * Returns 0 if the element is schemas valid, a positive error code
5451 * number otherwise and -1 in case of internal or API error.
5452 */
5453static int
5454xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5455 xmlNodePtr node)
5456{
5457 xmlNodePtr child;
5458 xmlSchemaTypePtr type;
5459 int ret;
5460
5461 child = ctxt->node;
5462 type = ctxt->type;
5463
5464 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005465 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005466 return (-1);
5467 }
5468 /*
5469 * Only text and text based entities references shall be found there
5470 */
5471 ret = xmlSchemaValidateCheckNodeList(child);
5472 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005473 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005474 return (-1);
5475 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005476 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 +00005477 return (-1);
5478 }
5479 ctxt->type = type->subtypes;
5480 xmlSchemaValidateContent(ctxt, node);
5481 ctxt->type = type;
5482 return (ret);
5483}
5484#endif
5485
5486/**
5487 * xmlSchemaValidateSimpleType:
5488 * @ctxt: a schema validation context
5489 * @node: the top node.
5490 *
5491 * Validate the content of an simple type.
5492 *
5493 * Returns 0 if the element is schemas valid, a positive error code
5494 * number otherwise and -1 in case of internal or API error.
5495 */
5496static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005497xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5498{
Daniel Veillard4255d502002-04-16 15:50:10 +00005499 xmlNodePtr child;
5500 xmlSchemaTypePtr type;
5501 xmlAttrPtr attr;
5502 int ret;
5503
5504 child = ctxt->node;
5505 type = ctxt->type;
5506
5507 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005508 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5509 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005510 }
5511 /*
5512 * Only text and text based entities references shall be found there
5513 */
5514 ret = xmlSchemaValidateCheckNodeList(child);
5515 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005516 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5517 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005518 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005519 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5520 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005521 }
5522 /*
5523 * Validation Rule: Element Locally Valid (Type): 3.1.1
5524 */
5525 attr = node->properties;
5526 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005527 if ((attr->ns == NULL) ||
5528 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5529 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5530 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5531 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5532 (!xmlStrEqual
5533 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5534 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5535 return (ctxt->err);
5536 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005537 }
5538
5539 ctxt->type = type->subtypes;
5540 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5541 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005542 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005543}
5544
5545/**
5546 * xmlSchemaValidateElementType:
5547 * @ctxt: a schema validation context
5548 * @node: the top node.
5549 *
5550 * Validate the content of an element type.
5551 * Validation Rule: Element Locally Valid (Complex Type)
5552 *
5553 * Returns 0 if the element is schemas valid, a positive error code
5554 * number otherwise and -1 in case of internal or API error.
5555 */
5556static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005557xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5558{
Daniel Veillard4255d502002-04-16 15:50:10 +00005559 xmlNodePtr child;
5560 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005561 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005562 xmlSchemaElementPtr decl;
5563 int ret, attrBase;
5564
5565 oldregexp = ctxt->regexp;
5566
5567 child = ctxt->node;
5568 type = ctxt->type;
5569
5570 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005571 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5572 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005573 }
5574 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005575 if (type->minOccurs > 0) {
5576 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5577 }
5578 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005579 }
5580
5581 /*
5582 * Verify the element matches
5583 */
5584 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005585 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5586 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005587 }
5588 /*
5589 * Verify the attributes
5590 */
5591 attrBase = ctxt->attrBase;
5592 ctxt->attrBase = ctxt->attrNr;
5593 xmlSchemaRegisterAttributes(ctxt, child->properties);
5594 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5595 /*
5596 * Verify the element content recursively
5597 */
5598 decl = (xmlSchemaElementPtr) type;
5599 oldregexp = ctxt->regexp;
5600 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005601 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5602 (xmlRegExecCallbacks)
5603 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005604#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005605 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005606#endif
5607 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005608 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5609 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005610
5611 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005612 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005613#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005614 xmlGenericError(xmlGenericErrorContext,
5615 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005616#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005617 if (ret == 0) {
5618 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5619 } else if (ret < 0) {
5620 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005621#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 } else {
5623 xmlGenericError(xmlGenericErrorContext,
5624 "Element %s content check succeeded\n",
5625 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005626
5627#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005628 }
5629 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005630 }
5631 /*
5632 * Verify that all attributes were Schemas-validated
5633 */
5634 xmlSchemaCheckAttributes(ctxt, node);
5635 ctxt->attrNr = ctxt->attrBase;
5636 ctxt->attrBase = attrBase;
5637
5638 ctxt->regexp = oldregexp;
5639
5640 ctxt->node = child;
5641 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005643}
5644
5645/**
5646 * xmlSchemaValidateBasicType:
5647 * @ctxt: a schema validation context
5648 * @node: the top node.
5649 *
5650 * Validate the content of an element expected to be a basic type type
5651 *
5652 * Returns 0 if the element is schemas valid, a positive error code
5653 * number otherwise and -1 in case of internal or API error.
5654 */
5655static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005656xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5657{
Daniel Veillard4255d502002-04-16 15:50:10 +00005658 int ret;
5659 xmlNodePtr child, cur;
5660 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005661 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005662
5663 child = ctxt->node;
5664 type = ctxt->type;
5665
5666 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005667 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5668 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005669 }
5670 /*
5671 * First check the content model of the node.
5672 */
5673 cur = child;
5674 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005675 switch (cur->type) {
5676 case XML_TEXT_NODE:
5677 case XML_CDATA_SECTION_NODE:
5678 case XML_PI_NODE:
5679 case XML_COMMENT_NODE:
5680 case XML_XINCLUDE_START:
5681 case XML_XINCLUDE_END:
5682 break;
5683 case XML_ENTITY_REF_NODE:
5684 case XML_ENTITY_NODE:
5685 TODO break;
5686 case XML_ELEMENT_NODE:
5687 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5688 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005689 case XML_ATTRIBUTE_NODE:
5690 case XML_DOCUMENT_NODE:
5691 case XML_DOCUMENT_TYPE_NODE:
5692 case XML_DOCUMENT_FRAG_NODE:
5693 case XML_NOTATION_NODE:
5694 case XML_HTML_DOCUMENT_NODE:
5695 case XML_DTD_NODE:
5696 case XML_ELEMENT_DECL:
5697 case XML_ATTRIBUTE_DECL:
5698 case XML_ENTITY_DECL:
5699 case XML_NAMESPACE_DECL:
5700#ifdef LIBXML_DOCB_ENABLED
5701 case XML_DOCB_DOCUMENT_NODE:
5702#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005703 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5704 return (ctxt->err);
5705 }
5706 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005707 }
5708 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005709 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005710 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005711 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005712
5713 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005714 xmlSchemaFreeValue(ctxt->value);
5715 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005716 }
5717 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5718 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005719 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005720 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005721 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 +00005722 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005723 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005724}
5725
5726/**
5727 * xmlSchemaValidateComplexType:
5728 * @ctxt: a schema validation context
5729 * @node: the top node.
5730 *
5731 * Validate the content of an element expected to be a complex type type
5732 * xmlschema-1.html#cvc-complex-type
5733 * Validation Rule: Element Locally Valid (Complex Type)
5734 *
5735 * Returns 0 if the element is schemas valid, a positive error code
5736 * number otherwise and -1 in case of internal or API error.
5737 */
5738static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005739xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5740{
Daniel Veillard4255d502002-04-16 15:50:10 +00005741 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005742 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005743 int ret;
5744
5745 child = ctxt->node;
5746 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005747 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005748
Daniel Veillard4255d502002-04-16 15:50:10 +00005749 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005750 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005751 if (type->baseType != NULL) {
5752 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005753 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5754 }
5755 if (type->attributes != NULL) {
5756 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5757 }
5758 subtype = type->subtypes;
5759 while (subtype != NULL) {
5760 ctxt->type = subtype;
5761 xmlSchemaValidateComplexType(ctxt, node);
5762 subtype = subtype->next;
5763 }
5764 break;
5765 case XML_SCHEMA_CONTENT_ELEMENTS:
5766 case XML_SCHEMA_CONTENT_MIXED:
5767 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5768 /*
5769 * Skip ignorable nodes in that context
5770 */
5771 child = xmlSchemaSkipIgnored(ctxt, type, child);
5772 while (child != NULL) {
5773 if (child->type == XML_ELEMENT_NODE) {
5774 ret = xmlRegExecPushString(ctxt->regexp,
5775 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005776#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005777 if (ret < 0)
5778 xmlGenericError(xmlGenericErrorContext,
5779 " --> %s Error\n", child->name);
5780 else
5781 xmlGenericError(xmlGenericErrorContext,
5782 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005783#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 }
5785 child = child->next;
5786 /*
5787 * Skip ignorable nodes in that context
5788 */
5789 child = xmlSchemaSkipIgnored(ctxt, type, child);
5790 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005791 if (type->attributes != NULL) {
5792 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5793 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005794 break;
5795 case XML_SCHEMA_CONTENT_BASIC:{
5796 if (type->subtypes != NULL) {
5797 ctxt->type = type->subtypes;
5798 xmlSchemaValidateComplexType(ctxt, node);
5799 }
5800 if (type->baseType != NULL) {
5801 ctxt->type = type->baseType;
5802 xmlSchemaValidateBasicType(ctxt, node);
5803 }
5804 if (type->attributes != NULL) {
5805 xmlSchemaValidateAttributes(ctxt, node,
5806 type->attributes);
5807 }
5808 ctxt->type = type;
5809 break;
5810 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005811 case XML_SCHEMA_CONTENT_SIMPLE:{
5812 if (type->subtypes != NULL) {
5813 ctxt->type = type->subtypes;
5814 xmlSchemaValidateComplexType(ctxt, node);
5815 }
5816 if (type->baseType != NULL) {
5817 ctxt->type = type->baseType;
5818 xmlSchemaValidateComplexType(ctxt, node);
5819 }
5820 if (type->attributes != NULL) {
5821 xmlSchemaValidateAttributes(ctxt, node,
5822 type->attributes);
5823 }
5824 ctxt->type = type;
5825 break;
5826 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005827 default:
5828 TODO xmlGenericError(xmlGenericErrorContext,
5829 "unimplemented content type %d\n",
5830 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005831 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005832 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005833}
5834
5835/**
5836 * xmlSchemaValidateContent:
5837 * @ctxt: a schema validation context
5838 * @elem: an element
5839 * @type: the type declaration
5840 *
5841 * Validate the content of an element against the type.
5842 *
5843 * Returns 0 if the element is schemas valid, a positive error code
5844 * number otherwise and -1 in case of internal or API error.
5845 */
5846static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005847xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5848{
Daniel Veillard4255d502002-04-16 15:50:10 +00005849 xmlNodePtr child;
5850 xmlSchemaTypePtr type;
5851
5852 child = ctxt->node;
5853 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005854 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005855
Daniel Veillarde19fc232002-04-22 16:01:24 +00005856 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005857 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005858
Daniel Veillard4255d502002-04-16 15:50:10 +00005859 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005860 case XML_SCHEMA_TYPE_ANY:
5861 /* Any type will do it, fine */
5862 TODO /* handle recursivity */
5863 break;
5864 case XML_SCHEMA_TYPE_COMPLEX:
5865 xmlSchemaValidateComplexType(ctxt, node);
5866 break;
5867 case XML_SCHEMA_TYPE_ELEMENT:{
5868 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5869
5870 /*
5871 * Handle element reference here
5872 */
5873 if (decl->ref != NULL) {
5874 if (decl->refDecl == NULL) {
5875 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5876 return (-1);
5877 }
5878 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5879 decl = decl->refDecl;
5880 }
5881 xmlSchemaValidateElementType(ctxt, node);
5882 ctxt->type = type;
5883 break;
5884 }
5885 case XML_SCHEMA_TYPE_BASIC:
5886 xmlSchemaValidateBasicType(ctxt, node);
5887 break;
5888 case XML_SCHEMA_TYPE_FACET:
5889 TODO break;
5890 case XML_SCHEMA_TYPE_SIMPLE:
5891 xmlSchemaValidateSimpleType(ctxt, node);
5892 break;
5893 case XML_SCHEMA_TYPE_SEQUENCE:
5894 TODO break;
5895 case XML_SCHEMA_TYPE_CHOICE:
5896 TODO break;
5897 case XML_SCHEMA_TYPE_ALL:
5898 TODO break;
5899 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5900 TODO break;
5901 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5902 TODO break;
5903 case XML_SCHEMA_TYPE_UR:
5904 TODO break;
5905 case XML_SCHEMA_TYPE_RESTRICTION:
5906 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5907 TODO break;
5908 case XML_SCHEMA_TYPE_EXTENSION:
5909 TODO break;
5910 case XML_SCHEMA_TYPE_ATTRIBUTE:
5911 TODO break;
5912 case XML_SCHEMA_TYPE_GROUP:
5913 TODO break;
5914 case XML_SCHEMA_TYPE_NOTATION:
5915 TODO break;
5916 case XML_SCHEMA_TYPE_LIST:
5917 TODO break;
5918 case XML_SCHEMA_TYPE_UNION:
5919 TODO break;
5920 case XML_SCHEMA_FACET_MININCLUSIVE:
5921 TODO break;
5922 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5923 TODO break;
5924 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5925 TODO break;
5926 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5927 TODO break;
5928 case XML_SCHEMA_FACET_TOTALDIGITS:
5929 TODO break;
5930 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5931 TODO break;
5932 case XML_SCHEMA_FACET_PATTERN:
5933 TODO break;
5934 case XML_SCHEMA_FACET_ENUMERATION:
5935 TODO break;
5936 case XML_SCHEMA_FACET_WHITESPACE:
5937 TODO break;
5938 case XML_SCHEMA_FACET_LENGTH:
5939 TODO break;
5940 case XML_SCHEMA_FACET_MAXLENGTH:
5941 TODO break;
5942 case XML_SCHEMA_FACET_MINLENGTH:
5943 TODO break;
5944 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5945 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005946 }
5947 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5948
5949 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005950 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005951 ctxt->node = ctxt->node->next;
5952 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005953 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005954}
5955
5956/**
5957 * xmlSchemaValidateType:
5958 * @ctxt: a schema validation context
5959 * @elem: an element
5960 * @type: the list of type declarations
5961 *
5962 * Validate the content of an element against the types.
5963 *
5964 * Returns 0 if the element is schemas valid, a positive error code
5965 * number otherwise and -1 in case of internal or API error.
5966 */
5967static int
5968xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005969 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5970{
Daniel Veillard4255d502002-04-16 15:50:10 +00005971 xmlChar *nil;
5972
Daniel Veillard2db8c122003-07-08 12:16:59 +00005973 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005974 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005975
Daniel Veillard4255d502002-04-16 15:50:10 +00005976 /*
5977 * 3.3.4 : 2
5978 */
5979 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005980 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5981 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005982 }
5983 /*
5984 * 3.3.4: 3
5985 */
5986 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5987 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005988 /* 3.3.4: 3.2 */
5989 if (xmlStrEqual(nil, BAD_CAST "true")) {
5990 if (elem->children != NULL) {
5991 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5992 return (ctxt->err);
5993 }
5994 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5995 (elemDecl->value != NULL)) {
5996 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5997 return (ctxt->err);
5998 }
5999 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006000 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006001 /* 3.3.4: 3.1 */
6002 if (nil != NULL) {
6003 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6004 xmlFree(nil);
6005 return (ctxt->err);
6006 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006007 }
6008
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006009 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006010
6011 ctxt->type = elemDecl->subtypes;
6012 ctxt->node = elem->children;
6013 xmlSchemaValidateContent(ctxt, elem);
6014 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006015
6016 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006017}
6018
6019
6020/**
6021 * xmlSchemaValidateAttributes:
6022 * @ctxt: a schema validation context
6023 * @elem: an element
6024 * @attributes: the list of attribute declarations
6025 *
6026 * Validate the attributes of an element.
6027 *
6028 * Returns 0 if the element is schemas valid, a positive error code
6029 * number otherwise and -1 in case of internal or API error.
6030 */
6031static int
6032xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006033 xmlSchemaAttributePtr attributes)
6034{
Daniel Veillard4255d502002-04-16 15:50:10 +00006035 int i, ret;
6036 xmlAttrPtr attr;
6037 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006038 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006039
6040 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006041 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006042 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006043 /*
6044 * Handle attribute groups
6045 */
6046 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6047 group = (xmlSchemaAttributeGroupPtr) attributes;
6048 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6049 attributes = group->next;
6050 continue;
6051 }
6052 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6053 attr = ctxt->attr[i].attr;
6054 if (attr == NULL)
6055 continue;
6056 if (attributes->ref != NULL) {
6057 if (!xmlStrEqual(attr->name, attributes->ref))
6058 continue;
6059 if (attr->ns != NULL) {
6060 if ((attributes->refNs == NULL) ||
6061 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6062 continue;
6063 } else if (attributes->refNs != NULL) {
6064 continue;
6065 }
6066 } else {
6067 if (!xmlStrEqual(attr->name, attributes->name))
6068 continue;
6069 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006070 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006071 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006072 if (attr->ns == NULL) {
6073 /*
6074 * accept an unqualified attribute only if the declaration
6075 * is unqualified or if the schemas allowed it.
6076 */
6077 if ((attributes->targetNamespace != NULL) &&
6078 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6079 continue;
6080 } else {
6081 if (attributes->targetNamespace == NULL)
6082 continue;
6083 if (!xmlStrEqual(attributes->targetNamespace,
6084 attr->ns->href))
6085 continue;
6086 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006087 }
6088 ctxt->cur = (xmlNodePtr) attributes;
6089 if (attributes->subtypes == NULL) {
6090 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6091 continue;
6092 }
6093 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6094 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6095 value);
6096 if (ret != 0) {
6097 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6098 } else {
6099 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6100 }
6101 if (value != NULL) {
6102 xmlFree(value);
6103 }
6104 }
6105 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006107 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006108}
6109
6110/**
6111 * xmlSchemaValidateElement:
6112 * @ctxt: a schema validation context
6113 * @elem: an element
6114 *
6115 * Validate an element in a tree
6116 *
6117 * Returns 0 if the element is schemas valid, a positive error code
6118 * number otherwise and -1 in case of internal or API error.
6119 */
6120static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006121xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6122{
Daniel Veillard4255d502002-04-16 15:50:10 +00006123 xmlSchemaElementPtr elemDecl;
6124 int ret, attrBase;
6125
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006126 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006127 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6128 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006129 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006130 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6131 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006132 }
6133 /*
6134 * special case whe elementFormDefault is unqualified for top-level elem.
6135 */
6136 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6137 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6138 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6139 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6140 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6141 elem->name, NULL, NULL);
6142 }
6143
Daniel Veillard4255d502002-04-16 15:50:10 +00006144 /*
6145 * 3.3.4 : 1
6146 */
6147 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006148 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6149 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006150 }
6151 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006152 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6153 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006154 }
6155 /*
6156 * Verify the attributes
6157 */
6158 attrBase = ctxt->attrBase;
6159 ctxt->attrBase = ctxt->attrNr;
6160 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6161 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6162 /*
6163 * Verify the element content recursively
6164 */
6165 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006166 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6167 (xmlRegExecCallbacks)
6168 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006169#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006170 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006171#endif
6172 }
6173 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006174 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006175 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006176#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006177 xmlGenericError(xmlGenericErrorContext,
6178 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006179#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006180 if (ret == 0) {
6181 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6182 } else if (ret < 0) {
6183 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006184#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185 } else {
6186 xmlGenericError(xmlGenericErrorContext,
6187 "Element %s content check succeeded\n",
6188 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006189
6190#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006191 }
6192 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006193 }
6194 /*
6195 * Verify that all attributes were Schemas-validated
6196 */
6197 xmlSchemaCheckAttributes(ctxt, elem);
6198 ctxt->attrNr = ctxt->attrBase;
6199 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006200
6201 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006202}
6203
6204/**
6205 * xmlSchemaValidateDocument:
6206 * @ctxt: a schema validation context
6207 * @doc: a parsed document tree
6208 *
6209 * Validate a document tree in memory.
6210 *
6211 * Returns 0 if the document is schemas valid, a positive error code
6212 * number otherwise and -1 in case of internal or API error.
6213 */
6214static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006215xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6216{
Daniel Veillard4255d502002-04-16 15:50:10 +00006217 xmlNodePtr root;
6218 xmlSchemaElementPtr elemDecl;
6219
6220 root = xmlDocGetRootElement(doc);
6221 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006222 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6223 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006224 }
6225 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006226 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6227 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006228 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6230 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006231 /*
6232 * special case whe elementFormDefault is unqualified for top-level elem.
6233 */
6234 if ((elemDecl == NULL) && (root->ns != NULL) &&
6235 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6236 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6237 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6238 root->name, NULL, NULL);
6239 }
6240
Daniel Veillard4255d502002-04-16 15:50:10 +00006241 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006242 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006243 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006244 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006245 }
6246 /*
6247 * Okay, start the recursive validation
6248 */
6249 xmlSchemaValidateElement(ctxt, root);
6250
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006251 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006252}
6253
6254/************************************************************************
6255 * *
6256 * SAX Validation code *
6257 * *
6258 ************************************************************************/
6259
6260/************************************************************************
6261 * *
6262 * Validation interfaces *
6263 * *
6264 ************************************************************************/
6265
6266/**
6267 * xmlSchemaNewValidCtxt:
6268 * @schema: a precompiled XML Schemas
6269 *
6270 * Create an XML Schemas validation context based on the given schema
6271 *
6272 * Returns the validation context or NULL in case of error
6273 */
6274xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006275xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6276{
Daniel Veillard4255d502002-04-16 15:50:10 +00006277 xmlSchemaValidCtxtPtr ret;
6278
6279 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6280 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006281 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006282 return (NULL);
6283 }
6284 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6285 ret->schema = schema;
6286 ret->attrNr = 0;
6287 ret->attrMax = 10;
6288 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006289 sizeof
6290 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006291 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006292 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6293 free(ret);
6294 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006295 }
6296 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6297 return (ret);
6298}
6299
6300/**
6301 * xmlSchemaFreeValidCtxt:
6302 * @ctxt: the schema validation context
6303 *
6304 * Free the resources associated to the schema validation context
6305 */
6306void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006307xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6308{
Daniel Veillard4255d502002-04-16 15:50:10 +00006309 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006310 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006311 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006312 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006313 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006314 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006315 xmlFree(ctxt);
6316}
6317
6318/**
6319 * xmlSchemaSetValidErrors:
6320 * @ctxt: a schema validation context
6321 * @err: the error function
6322 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006323 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006324 *
6325 * Set the error and warning callback informations
6326 */
6327void
6328xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006329 xmlSchemaValidityErrorFunc err,
6330 xmlSchemaValidityWarningFunc warn, void *ctx)
6331{
Daniel Veillard4255d502002-04-16 15:50:10 +00006332 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006333 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006334 ctxt->error = err;
6335 ctxt->warning = warn;
6336 ctxt->userData = ctx;
6337}
6338
6339/**
6340 * xmlSchemaValidateDoc:
6341 * @ctxt: a schema validation context
6342 * @doc: a parsed document tree
6343 *
6344 * Validate a document tree in memory.
6345 *
6346 * Returns 0 if the document is schemas valid, a positive error code
6347 * number otherwise and -1 in case of internal or API error.
6348 */
6349int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006350xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6351{
Daniel Veillard4255d502002-04-16 15:50:10 +00006352 int ret;
6353
6354 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006355 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006356
6357 ctxt->doc = doc;
6358 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006359 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006360}
6361
6362/**
6363 * xmlSchemaValidateStream:
6364 * @ctxt: a schema validation context
6365 * @input: the input to use for reading the data
6366 * @enc: an optional encoding information
6367 * @sax: a SAX handler for the resulting events
6368 * @user_data: the context to provide to the SAX handler.
6369 *
6370 * Validate a document tree in memory.
6371 *
6372 * Returns 0 if the document is schemas valid, a positive error code
6373 * number otherwise and -1 in case of internal or API error.
6374 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006375int
Daniel Veillard4255d502002-04-16 15:50:10 +00006376xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006377 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6378 xmlSAXHandlerPtr sax, void *user_data)
6379{
Daniel Veillard4255d502002-04-16 15:50:10 +00006380 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006381 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006382 ctxt->input = input;
6383 ctxt->enc = enc;
6384 ctxt->sax = sax;
6385 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006386 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006387}
6388
6389#endif /* LIBXML_SCHEMAS_ENABLED */