blob: 7c6c5fbe5de0bd41f946e5ea20bf0f3876a3acf2 [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
10#define IN_LIBXML
11#include "libxml.h"
12
13#ifdef LIBXML_SCHEMAS_ENABLED
14
15#include <string.h>
16#include <libxml/xmlmemory.h>
17#include <libxml/parser.h>
18#include <libxml/parserInternals.h>
19#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000020#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000021
22#include <libxml/xmlschemas.h>
23#include <libxml/schemasInternals.h>
24#include <libxml/xmlschemastypes.h>
25#include <libxml/xmlautomata.h>
26#include <libxml/xmlregexp.h>
27
Daniel Veillarda84c0b32003-06-02 16:58:46 +000028/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000029
Daniel Veillard82bbbd42003-05-11 20:16:09 +000030/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000031
Daniel Veillard82bbbd42003-05-11 20:16:09 +000032/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000033
Daniel Veillard118aed72002-09-24 14:13:13 +000034/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000035
Daniel Veillard4255d502002-04-16 15:50:10 +000036/* #define DEBUG_AUTOMATA 1 */
37
38#define UNBOUNDED (1 << 30)
39#define TODO \
40 xmlGenericError(xmlGenericErrorContext, \
41 "Unimplemented block at %s:%d\n", \
42 __FILE__, __LINE__);
43
Daniel Veillard5a872412002-05-22 06:40:27 +000044#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
45
Daniel Veillard4255d502002-04-16 15:50:10 +000046/*
47 * The XML Schemas namespaces
48 */
49static const xmlChar *xmlSchemaNs = (const xmlChar *)
50 "http://www.w3.org/2001/XMLSchema";
51
52static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
53 "http://www.w3.org/2001/XMLSchema-instance";
54
55#define IS_SCHEMA(node, type) \
56 ((node != NULL) && (node->ns != NULL) && \
57 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
58 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
59
60#define XML_SCHEMAS_PARSE_ERROR 1
61
62struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000063 void *userData; /* user specific data block */
64 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
65 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000066 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000067 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000068 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000069
Daniel Veillardd0c9c322003-10-10 00:49:42 +000070 xmlSchemaPtr schema; /* The schema in use */
71 xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000072 int counter;
73
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074 xmlChar *URL;
75 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +000076
Daniel Veillardd0c9c322003-10-10 00:49:42 +000077 const char *buffer;
78 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000079
Daniel Veillard4255d502002-04-16 15:50:10 +000080 /*
81 * Used to build complex element content models
82 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000083 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000084 xmlAutomataStatePtr start;
85 xmlAutomataStatePtr end;
86 xmlAutomataStatePtr state;
87};
88
89
90#define XML_SCHEMAS_ATTR_UNKNOWN 1
91#define XML_SCHEMAS_ATTR_CHECKED 2
92
93typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
94typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
95struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAttrPtr attr;
97 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +000098};
99
100/**
101 * xmlSchemaValidCtxt:
102 *
103 * A Schemas validation context
104 */
105
106struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000107 void *userData; /* user specific data block */
108 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
109 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000110 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000111
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlSchemaPtr schema; /* The schema in use */
113 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000115 xmlCharEncoding enc;
116 xmlSAXHandlerPtr sax;
117 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000118
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000119 xmlDocPtr myDoc;
120 int err;
121 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000122
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 xmlNodePtr node;
124 xmlNodePtr cur;
125 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000126
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000127 xmlRegExecCtxtPtr regexp;
128 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000129
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000130 int attrNr;
131 int attrBase;
132 int attrMax;
133 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134};
135
136
137/************************************************************************
138 * *
139 * Some predeclarations *
140 * *
141 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000142static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
143 xmlSchemaTypePtr type,
144 xmlChar * value);
145
146/************************************************************************
147 * *
148 * Datatype error handlers *
149 * *
150 ************************************************************************/
151
152/**
153 * xmlSchemaPErrMemory:
154 * @node: a context node
155 * @extra: extra informations
156 *
157 * Handle an out of memory condition
158 */
159static void
160xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
161 const char *extra, xmlNodePtr node)
162{
163 if (ctxt != NULL)
164 ctxt->nberrors++;
165 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
166 extra);
167}
168
169/**
170 * xmlSchemaPErr:
171 * @ctxt: the parsing context
172 * @node: the context node
173 * @error: the error code
174 * @msg: the error message
175 * @str1: extra data
176 * @str2: extra data
177 *
178 * Handle a parser error
179 */
180static void
181xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
182 const char *msg, const xmlChar * str1, const xmlChar * str2)
183{
184 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000185 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000186 void *data = NULL;
187
188 if (ctxt != NULL) {
189 ctxt->nberrors++;
190 channel = ctxt->error;
191 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000192 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000193 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000194 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000195 error, XML_ERR_ERROR, NULL, 0,
196 (const char *) str1, (const char *) str2, NULL, 0, 0,
197 msg, str1, str2);
198}
199
200/**
201 * xmlSchemaPErr2:
202 * @ctxt: the parsing context
203 * @node: the context node
204 * @node: the current child
205 * @error: the error code
206 * @msg: the error message
207 * @str1: extra data
208 * @str2: extra data
209 *
210 * Handle a parser error
211 */
212static void
213xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
214 xmlNodePtr child, int error,
215 const char *msg, const xmlChar * str1, const xmlChar * str2)
216{
217 if (child != NULL)
218 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
219 else
220 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
221}
222
223/**
224 * xmlSchemaVTypeErrMemory:
225 * @node: a context node
226 * @extra: extra informations
227 *
228 * Handle an out of memory condition
229 */
230static void
231xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
232 const char *extra, xmlNodePtr node)
233{
234 if (ctxt != NULL) {
235 ctxt->nberrors++;
236 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
237 }
238 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
239 extra);
240}
241
242/**
243 * xmlSchemaVErr3:
244 * @ctxt: the validation context
245 * @node: the context node
246 * @error: the error code
247 * @msg: the error message
248 * @str1: extra data
249 * @str2: extra data
250 * @str3: extra data
251 *
252 * Handle a validation error
253 */
254static void
255xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
256 const char *msg, const xmlChar *str1, const xmlChar *str2,
257 const xmlChar *str3)
258{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000259 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000260 xmlGenericErrorFunc channel = NULL;
261 void *data = NULL;
262
263 if (ctxt != NULL) {
264 ctxt->nberrors++;
265 ctxt->err = error;
266 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000267 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000268 data = ctxt->userData;
269 }
270 /* reajust to global error numbers */
271 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000272 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000273 error, XML_ERR_ERROR, NULL, 0,
274 (const char *) str1, (const char *) str2,
275 (const char *) str3, 0, 0,
276 msg, str1, str2, str3);
277}
278/**
279 * xmlSchemaVErr:
280 * @ctxt: the validation context
281 * @node: the context node
282 * @error: the error code
283 * @msg: the error message
284 * @str1: extra data
285 * @str2: extra data
286 *
287 * Handle a validation error
288 */
289static void
290xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
291 const char *msg, const xmlChar * str1, const xmlChar * str2)
292{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000293 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000294 xmlGenericErrorFunc channel = NULL;
295 void *data = NULL;
296
297 if (ctxt != NULL) {
298 ctxt->nberrors++;
299 ctxt->err = error;
300 channel = ctxt->error;
301 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000302 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000303 }
304 /* reajust to global error numbers */
305 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000306 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000307 error, XML_ERR_ERROR, NULL, 0,
308 (const char *) str1, (const char *) str2, NULL, 0, 0,
309 msg, str1, str2);
310}
Daniel Veillard4255d502002-04-16 15:50:10 +0000311
312/************************************************************************
313 * *
314 * Allocation functions *
315 * *
316 ************************************************************************/
317
318/**
319 * xmlSchemaNewSchema:
320 * @ctxt: a schema validation context (optional)
321 *
322 * Allocate a new Schema structure.
323 *
324 * Returns the newly allocated structure or NULL in case or error
325 */
326static xmlSchemaPtr
327xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
328{
329 xmlSchemaPtr ret;
330
331 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
332 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000333 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000334 return (NULL);
335 }
336 memset(ret, 0, sizeof(xmlSchema));
337
338 return (ret);
339}
340
341/**
342 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000343 *
344 * Allocate a new Facet structure.
345 *
346 * Returns the newly allocated structure or NULL in case or error
347 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000348xmlSchemaFacetPtr
349xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000350{
351 xmlSchemaFacetPtr ret;
352
353 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
354 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000355 return (NULL);
356 }
357 memset(ret, 0, sizeof(xmlSchemaFacet));
358
359 return (ret);
360}
361
362/**
363 * xmlSchemaNewAnnot:
364 * @ctxt: a schema validation context (optional)
365 * @node: a node
366 *
367 * Allocate a new annotation structure.
368 *
369 * Returns the newly allocated structure or NULL in case or error
370 */
371static xmlSchemaAnnotPtr
372xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
373{
374 xmlSchemaAnnotPtr ret;
375
376 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
377 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000378 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000379 return (NULL);
380 }
381 memset(ret, 0, sizeof(xmlSchemaAnnot));
382 ret->content = node;
383 return (ret);
384}
385
386/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000387 * xmlSchemaFreeAnnot:
388 * @annot: a schema type structure
389 *
390 * Deallocate a annotation structure
391 */
392static void
393xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
394{
395 if (annot == NULL)
396 return;
397 xmlFree(annot);
398}
399
400/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000401 * xmlSchemaFreeNotation:
402 * @schema: a schema notation structure
403 *
404 * Deallocate a Schema Notation structure.
405 */
406static void
407xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
408{
409 if (nota == NULL)
410 return;
411 if (nota->name != NULL)
412 xmlFree((xmlChar *) nota->name);
413 xmlFree(nota);
414}
415
416/**
417 * xmlSchemaFreeAttribute:
418 * @schema: a schema attribute structure
419 *
420 * Deallocate a Schema Attribute structure.
421 */
422static void
423xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
424{
425 if (attr == NULL)
426 return;
427 if (attr->name != NULL)
428 xmlFree((xmlChar *) attr->name);
429 if (attr->ref != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000430 xmlFree((xmlChar *) attr->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000431 if (attr->refNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000432 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000433 if (attr->typeName != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000434 xmlFree((xmlChar *) attr->typeName);
Daniel Veillard4255d502002-04-16 15:50:10 +0000435 if (attr->typeNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000436 xmlFree((xmlChar *) attr->typeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000437 xmlFree(attr);
438}
439
440/**
441 * xmlSchemaFreeAttributeGroup:
442 * @schema: a schema attribute group structure
443 *
444 * Deallocate a Schema Attribute Group structure.
445 */
446static void
447xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
448{
449 if (attr == NULL)
450 return;
451 if (attr->name != NULL)
452 xmlFree((xmlChar *) attr->name);
Daniel Veillard91a13252003-03-27 23:44:43 +0000453 if (attr->ref != NULL)
454 xmlFree((xmlChar *) attr->ref);
455 if (attr->refNs != NULL)
456 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000457 xmlFree(attr);
458}
459
460/**
461 * xmlSchemaFreeElement:
462 * @schema: a schema element structure
463 *
464 * Deallocate a Schema Element structure.
465 */
466static void
467xmlSchemaFreeElement(xmlSchemaElementPtr elem)
468{
469 if (elem == NULL)
470 return;
471 if (elem->name != NULL)
472 xmlFree((xmlChar *) elem->name);
473 if (elem->namedType != NULL)
474 xmlFree((xmlChar *) elem->namedType);
475 if (elem->namedTypeNs != NULL)
476 xmlFree((xmlChar *) elem->namedTypeNs);
477 if (elem->ref != NULL)
478 xmlFree((xmlChar *) elem->ref);
479 if (elem->refNs != NULL)
480 xmlFree((xmlChar *) elem->refNs);
Daniel Veillard32370232002-10-16 14:08:14 +0000481 if (elem->annot != NULL)
482 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000483 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000484 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000485 xmlFree(elem);
486}
487
488/**
489 * xmlSchemaFreeFacet:
490 * @facet: a schema facet structure
491 *
492 * Deallocate a Schema Facet structure.
493 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000494void
Daniel Veillard4255d502002-04-16 15:50:10 +0000495xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
496{
497 if (facet == NULL)
498 return;
499 if (facet->value != NULL)
500 xmlFree((xmlChar *) facet->value);
501 if (facet->id != NULL)
502 xmlFree((xmlChar *) facet->id);
503 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000504 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000505 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000506 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000507 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000508 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000509 xmlFree(facet);
510}
511
512/**
513 * xmlSchemaFreeType:
514 * @type: a schema type structure
515 *
516 * Deallocate a Schema Type structure.
517 */
518void
519xmlSchemaFreeType(xmlSchemaTypePtr type)
520{
521 if (type == NULL)
522 return;
523 if (type->name != NULL)
524 xmlFree((xmlChar *) type->name);
525 if (type->base != NULL)
526 xmlFree((xmlChar *) type->base);
527 if (type->baseNs != NULL)
528 xmlFree((xmlChar *) type->baseNs);
529 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000530 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000531 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000532 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000533
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000534 facet = type->facets;
535 while (facet != NULL) {
536 next = facet->next;
537 xmlSchemaFreeFacet(facet);
538 facet = next;
539 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000540 }
541 xmlFree(type);
542}
543
544/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000545 * xmlSchemaFree:
546 * @schema: a schema structure
547 *
548 * Deallocate a Schema structure.
549 */
550void
551xmlSchemaFree(xmlSchemaPtr schema)
552{
553 if (schema == NULL)
554 return;
555
Daniel Veillard91a13252003-03-27 23:44:43 +0000556 if (schema->id != NULL)
557 xmlFree((xmlChar *) schema->id);
558 if (schema->targetNamespace != NULL)
559 xmlFree((xmlChar *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000560 if (schema->name != NULL)
561 xmlFree((xmlChar *) schema->name);
562 if (schema->notaDecl != NULL)
563 xmlHashFree(schema->notaDecl,
564 (xmlHashDeallocator) xmlSchemaFreeNotation);
565 if (schema->attrDecl != NULL)
566 xmlHashFree(schema->attrDecl,
567 (xmlHashDeallocator) xmlSchemaFreeAttribute);
568 if (schema->attrgrpDecl != NULL)
569 xmlHashFree(schema->attrgrpDecl,
570 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
571 if (schema->elemDecl != NULL)
572 xmlHashFree(schema->elemDecl,
573 (xmlHashDeallocator) xmlSchemaFreeElement);
574 if (schema->typeDecl != NULL)
575 xmlHashFree(schema->typeDecl,
576 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000577 if (schema->groupDecl != NULL)
578 xmlHashFree(schema->groupDecl,
579 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard4255d502002-04-16 15:50:10 +0000580 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000581 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000582 if (schema->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000583 xmlFreeDoc(schema->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +0000584
585 xmlFree(schema);
586}
587
588/************************************************************************
589 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000590 * Debug functions *
591 * *
592 ************************************************************************/
593
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000594#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000595
Daniel Veillard4255d502002-04-16 15:50:10 +0000596/**
597 * xmlSchemaElementDump:
598 * @elem: an element
599 * @output: the file output
600 *
601 * Dump the element
602 */
603static void
604xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000605 const xmlChar * name ATTRIBUTE_UNUSED,
606 const xmlChar * context ATTRIBUTE_UNUSED,
607 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000608{
609 if (elem == NULL)
610 return;
611
612 fprintf(output, "Element ");
613 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000614 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000615 fprintf(output, ": %s ", elem->name);
616 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 fprintf(output, "namespace '%s' ", namespace);
618
Daniel Veillard4255d502002-04-16 15:50:10 +0000619 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000620 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000621 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000624 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000625 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000626 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000627 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000629 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000631 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000632 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000633 fprintf(output, "\n");
634 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000635 fprintf(output, " ");
636 if (elem->minOccurs != 1)
637 fprintf(output, "min: %d ", elem->minOccurs);
638 if (elem->maxOccurs >= UNBOUNDED)
639 fprintf(output, "max: unbounded\n");
640 else if (elem->maxOccurs != 1)
641 fprintf(output, "max: %d\n", elem->maxOccurs);
642 else
643 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000644 }
645 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000646 fprintf(output, " type: %s", elem->namedType);
647 if (elem->namedTypeNs != NULL)
648 fprintf(output, " ns %s\n", elem->namedTypeNs);
649 else
650 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000651 }
652 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653 fprintf(output, " substitutionGroup: %s", elem->substGroup);
654 if (elem->substGroupNs != NULL)
655 fprintf(output, " ns %s\n", elem->substGroupNs);
656 else
657 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000658 }
659 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000660 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000661}
662
663/**
664 * xmlSchemaAnnotDump:
665 * @output: the file output
666 * @annot: a annotation
667 *
668 * Dump the annotation
669 */
670static void
671xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
672{
673 xmlChar *content;
674
675 if (annot == NULL)
676 return;
677
678 content = xmlNodeGetContent(annot->content);
679 if (content != NULL) {
680 fprintf(output, " Annot: %s\n", content);
681 xmlFree(content);
682 } else
683 fprintf(output, " Annot: empty\n");
684}
685
686/**
687 * xmlSchemaTypeDump:
688 * @output: the file output
689 * @type: a type structure
690 *
691 * Dump a SchemaType structure
692 */
693static void
694xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
695{
696 if (type == NULL) {
697 fprintf(output, "Type: NULL\n");
698 return;
699 }
700 fprintf(output, "Type: ");
701 if (type->name != NULL)
702 fprintf(output, "%s, ", type->name);
703 else
704 fprintf(output, "no name");
705 switch (type->type) {
706 case XML_SCHEMA_TYPE_BASIC:
707 fprintf(output, "basic ");
708 break;
709 case XML_SCHEMA_TYPE_SIMPLE:
710 fprintf(output, "simple ");
711 break;
712 case XML_SCHEMA_TYPE_COMPLEX:
713 fprintf(output, "complex ");
714 break;
715 case XML_SCHEMA_TYPE_SEQUENCE:
716 fprintf(output, "sequence ");
717 break;
718 case XML_SCHEMA_TYPE_CHOICE:
719 fprintf(output, "choice ");
720 break;
721 case XML_SCHEMA_TYPE_ALL:
722 fprintf(output, "all ");
723 break;
724 case XML_SCHEMA_TYPE_UR:
725 fprintf(output, "ur ");
726 break;
727 case XML_SCHEMA_TYPE_RESTRICTION:
728 fprintf(output, "restriction ");
729 break;
730 case XML_SCHEMA_TYPE_EXTENSION:
731 fprintf(output, "extension ");
732 break;
733 default:
734 fprintf(output, "unknowntype%d ", type->type);
735 break;
736 }
737 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000738 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000739 }
740 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000741 case XML_SCHEMA_CONTENT_UNKNOWN:
742 fprintf(output, "unknown ");
743 break;
744 case XML_SCHEMA_CONTENT_EMPTY:
745 fprintf(output, "empty ");
746 break;
747 case XML_SCHEMA_CONTENT_ELEMENTS:
748 fprintf(output, "element ");
749 break;
750 case XML_SCHEMA_CONTENT_MIXED:
751 fprintf(output, "mixed ");
752 break;
753 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
754 fprintf(output, "mixed_or_elems ");
755 break;
756 case XML_SCHEMA_CONTENT_BASIC:
757 fprintf(output, "basic ");
758 break;
759 case XML_SCHEMA_CONTENT_SIMPLE:
760 fprintf(output, "simple ");
761 break;
762 case XML_SCHEMA_CONTENT_ANY:
763 fprintf(output, "any ");
764 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000765 }
766 fprintf(output, "\n");
767 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000768 fprintf(output, " ");
769 if (type->minOccurs != 1)
770 fprintf(output, "min: %d ", type->minOccurs);
771 if (type->maxOccurs >= UNBOUNDED)
772 fprintf(output, "max: unbounded\n");
773 else if (type->maxOccurs != 1)
774 fprintf(output, "max: %d\n", type->maxOccurs);
775 else
776 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000777 }
778 if (type->annot != NULL)
779 xmlSchemaAnnotDump(output, type->annot);
780 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000781 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000782
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783 fprintf(output, " subtypes: ");
784 while (sub != NULL) {
785 fprintf(output, "%s ", sub->name);
786 sub = sub->next;
787 }
788 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000789 }
790
791}
792
793/**
794 * xmlSchemaDump:
795 * @output: the file output
796 * @schema: a schema structure
797 *
798 * Dump a Schema structure.
799 */
800void
801xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
802{
803 if (schema == NULL) {
804 fprintf(output, "Schemas: NULL\n");
805 return;
806 }
807 fprintf(output, "Schemas: ");
808 if (schema->name != NULL)
809 fprintf(output, "%s, ", schema->name);
810 else
811 fprintf(output, "no name, ");
812 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000813 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000814 else
815 fprintf(output, "no target namespace");
816 fprintf(output, "\n");
817 if (schema->annot != NULL)
818 xmlSchemaAnnotDump(output, schema->annot);
819
820 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
821 output);
822 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000823 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000824}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000825#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000826
827/************************************************************************
828 * *
829 * Parsing functions *
830 * *
831 ************************************************************************/
832
833/**
834 * xmlSchemaGetType:
835 * @schema: the schemas context
836 * @name: the type name
837 * @ns: the type namespace
838 *
839 * Lookup a type in the schemas or the predefined types
840 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000841 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +0000842 */
843static xmlSchemaTypePtr
844xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000845 const xmlChar * namespace)
846{
Daniel Veillard4255d502002-04-16 15:50:10 +0000847 xmlSchemaTypePtr ret;
848
849 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000850 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000851 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000852 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
853 if (ret != NULL)
854 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000855 }
856 ret = xmlSchemaGetPredefinedType(name, namespace);
857#ifdef DEBUG
858 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000859 if (namespace == NULL)
860 fprintf(stderr, "Unable to lookup type %s", name);
861 else
862 fprintf(stderr, "Unable to lookup type %s:%s", name,
863 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000864 }
865#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000866 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000867}
868
869/************************************************************************
870 * *
871 * Parsing functions *
872 * *
873 ************************************************************************/
874
875#define IS_BLANK_NODE(n) \
876 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
877
878/**
879 * xmlSchemaIsBlank:
880 * @str: a string
881 *
882 * Check if a string is ignorable
883 *
884 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
885 */
886static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000887xmlSchemaIsBlank(xmlChar * str)
888{
Daniel Veillard4255d502002-04-16 15:50:10 +0000889 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000890 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000891 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +0000892 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000893 return (0);
894 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +0000895 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000896 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000897}
898
899/**
900 * xmlSchemaAddNotation:
901 * @ctxt: a schema validation context
902 * @schema: the schema being built
903 * @name: the item name
904 *
905 * Add an XML schema Attrribute declaration
906 * *WARNING* this interface is highly subject to change
907 *
908 * Returns the new struture or NULL in case of error
909 */
910static xmlSchemaNotationPtr
911xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000912 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +0000913{
914 xmlSchemaNotationPtr ret = NULL;
915 int val;
916
917 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
918 return (NULL);
919
920 if (schema->notaDecl == NULL)
921 schema->notaDecl = xmlHashCreate(10);
922 if (schema->notaDecl == NULL)
923 return (NULL);
924
925 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
926 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000927 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000928 return (NULL);
929 }
930 memset(ret, 0, sizeof(xmlSchemaNotation));
931 ret->name = xmlStrdup(name);
932 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
933 ret);
934 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000935 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
936 XML_SCHEMAP_REDEFINED_NOTATION,
937 "Notation %s already defined\n",
938 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000939 xmlFree((char *) ret->name);
940 xmlFree(ret);
941 return (NULL);
942 }
943 return (ret);
944}
945
946
947/**
948 * xmlSchemaAddAttribute:
949 * @ctxt: a schema validation context
950 * @schema: the schema being built
951 * @name: the item name
952 * @container: the container's name
953 *
954 * Add an XML schema Attrribute declaration
955 * *WARNING* this interface is highly subject to change
956 *
957 * Returns the new struture or NULL in case of error
958 */
959static xmlSchemaAttributePtr
960xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
961 const xmlChar * name)
962{
963 xmlSchemaAttributePtr ret = NULL;
964 int val;
965
966 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
967 return (NULL);
968
969 if (schema->attrDecl == NULL)
970 schema->attrDecl = xmlHashCreate(10);
971 if (schema->attrDecl == NULL)
972 return (NULL);
973
974 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
975 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000976 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000977 return (NULL);
978 }
979 memset(ret, 0, sizeof(xmlSchemaAttribute));
980 ret->name = xmlStrdup(name);
981 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000982 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000983 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000984 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
985 XML_SCHEMAP_REDEFINED_ATTR,
986 "Attribute %s already defined\n",
987 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000988 xmlFree((char *) ret->name);
989 xmlFree(ret);
990 return (NULL);
991 }
992 return (ret);
993}
994
995/**
996 * xmlSchemaAddAttributeGroup:
997 * @ctxt: a schema validation context
998 * @schema: the schema being built
999 * @name: the item name
1000 *
1001 * Add an XML schema Attrribute Group declaration
1002 *
1003 * Returns the new struture or NULL in case of error
1004 */
1005static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001006xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1007 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001008{
1009 xmlSchemaAttributeGroupPtr ret = NULL;
1010 int val;
1011
1012 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1013 return (NULL);
1014
1015 if (schema->attrgrpDecl == NULL)
1016 schema->attrgrpDecl = xmlHashCreate(10);
1017 if (schema->attrgrpDecl == NULL)
1018 return (NULL);
1019
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001020 ret =
1021 (xmlSchemaAttributeGroupPtr)
1022 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001023 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001024 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001025 return (NULL);
1026 }
1027 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
1028 ret->name = xmlStrdup(name);
1029 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001030 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001031 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001032 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1033 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1034 "Attribute group %s already defined\n",
1035 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001036 xmlFree((char *) ret->name);
1037 xmlFree(ret);
1038 return (NULL);
1039 }
1040 return (ret);
1041}
1042
1043/**
1044 * xmlSchemaAddElement:
1045 * @ctxt: a schema validation context
1046 * @schema: the schema being built
1047 * @name: the type name
1048 * @namespace: the type namespace
1049 *
1050 * Add an XML schema Element declaration
1051 * *WARNING* this interface is highly subject to change
1052 *
1053 * Returns the new struture or NULL in case of error
1054 */
1055static xmlSchemaElementPtr
1056xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1057 const xmlChar * name, const xmlChar * namespace)
1058{
1059 xmlSchemaElementPtr ret = NULL;
1060 int val;
1061
1062 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1063 return (NULL);
1064
1065 if (schema->elemDecl == NULL)
1066 schema->elemDecl = xmlHashCreate(10);
1067 if (schema->elemDecl == NULL)
1068 return (NULL);
1069
1070 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1071 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001072 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001073 return (NULL);
1074 }
1075 memset(ret, 0, sizeof(xmlSchemaElement));
1076 ret->name = xmlStrdup(name);
1077 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001078 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001079 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001080 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001081
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001082 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
1083 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1084 namespace, ret);
1085 if (val != 0) {
1086 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1087 XML_SCHEMAP_REDEFINED_ELEMENT,
1088 "Element %s already defined\n",
1089 name, NULL);
1090 xmlFree((char *) ret->name);
1091 xmlFree(ret);
1092 return (NULL);
1093 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001094 }
1095 return (ret);
1096}
1097
1098/**
1099 * xmlSchemaAddType:
1100 * @ctxt: a schema validation context
1101 * @schema: the schema being built
1102 * @name: the item name
1103 *
1104 * Add an XML schema Simple Type definition
1105 * *WARNING* this interface is highly subject to change
1106 *
1107 * Returns the new struture or NULL in case of error
1108 */
1109static xmlSchemaTypePtr
1110xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1111 const xmlChar * name)
1112{
1113 xmlSchemaTypePtr ret = NULL;
1114 int val;
1115
1116 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1117 return (NULL);
1118
1119 if (schema->typeDecl == NULL)
1120 schema->typeDecl = xmlHashCreate(10);
1121 if (schema->typeDecl == NULL)
1122 return (NULL);
1123
1124 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1125 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001126 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001127 return (NULL);
1128 }
1129 memset(ret, 0, sizeof(xmlSchemaType));
1130 ret->name = xmlStrdup(name);
1131 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1132 ret);
1133 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001134 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1135 XML_SCHEMAP_REDEFINED_TYPE,
1136 "Type %s already defined\n",
1137 name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001138 xmlFree((char *) ret->name);
1139 xmlFree(ret);
1140 return (NULL);
1141 }
1142 ret->minOccurs = 1;
1143 ret->maxOccurs = 1;
1144
1145 return (ret);
1146}
1147
1148/**
1149 * xmlSchemaAddGroup:
1150 * @ctxt: a schema validation context
1151 * @schema: the schema being built
1152 * @name: the group name
1153 *
1154 * Add an XML schema Group definition
1155 *
1156 * Returns the new struture or NULL in case of error
1157 */
1158static xmlSchemaTypePtr
1159xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001160 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001161{
1162 xmlSchemaTypePtr ret = NULL;
1163 int val;
1164
1165 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1166 return (NULL);
1167
1168 if (schema->groupDecl == NULL)
1169 schema->groupDecl = xmlHashCreate(10);
1170 if (schema->groupDecl == NULL)
1171 return (NULL);
1172
1173 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1174 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001175 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001176 return (NULL);
1177 }
1178 memset(ret, 0, sizeof(xmlSchemaType));
1179 ret->name = xmlStrdup(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001180 val =
1181 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1182 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001183 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001184 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1185 XML_SCHEMAP_REDEFINED_GROUP,
1186 "Group %s already defined\n",
1187 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001188 xmlFree((char *) ret->name);
1189 xmlFree(ret);
1190 return (NULL);
1191 }
1192 ret->minOccurs = 1;
1193 ret->maxOccurs = 1;
1194
1195 return (ret);
1196}
1197
1198/************************************************************************
1199 * *
1200 * Utilities for parsing *
1201 * *
1202 ************************************************************************/
1203
1204/**
1205 * xmlGetQNameProp:
1206 * @ctxt: a schema validation context
1207 * @node: a subtree containing XML Schema informations
1208 * @name: the attribute name
1209 * @namespace: the result namespace if any
1210 *
1211 * Extract a QName Attribute value
1212 *
1213 * Returns the NCName or NULL if not found, and also update @namespace
1214 * with the namespace URI
1215 */
1216static xmlChar *
1217xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001218 const char *name, xmlChar ** namespace)
1219{
Daniel Veillard4255d502002-04-16 15:50:10 +00001220 xmlChar *val, *ret, *prefix;
1221 xmlNsPtr ns;
1222
1223
1224 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001225 *namespace = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001226 val = xmlGetProp(node, (const xmlChar *) name);
1227 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001228 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001229
1230 ret = xmlSplitQName2(val, &prefix);
1231 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001232 return (val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001233 xmlFree(val);
1234
1235 ns = xmlSearchNs(node->doc, node, prefix);
1236 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001237 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1238 "Attribute %s: the QName prefix %s is undefined\n",
1239 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001240 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001241 *namespace = xmlStrdup(ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +00001242 }
1243 xmlFree(prefix);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001244 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001245}
1246
1247/**
1248 * xmlGetMaxOccurs:
1249 * @ctxt: a schema validation context
1250 * @node: a subtree containing XML Schema informations
1251 *
1252 * Get the maxOccurs property
1253 *
1254 * Returns the default if not found, or the value
1255 */
1256static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001257xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1258{
Daniel Veillard4255d502002-04-16 15:50:10 +00001259 xmlChar *val, *cur;
1260 int ret = 0;
1261
1262 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1263 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001264 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001265
1266 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001267 xmlFree(val);
1268 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001269 }
1270
1271 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001272 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001273 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001274 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001275 ret = ret * 10 + (*cur - '0');
1276 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001277 }
William M. Brack76e95df2003-10-18 16:20:14 +00001278 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001279 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001280 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001281 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1282 "invalid value for maxOccurs: %s\n", val, NULL);
1283 xmlFree(val);
1284 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001285 }
1286 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001287 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001288}
1289
1290/**
1291 * xmlGetMinOccurs:
1292 * @ctxt: a schema validation context
1293 * @node: a subtree containing XML Schema informations
1294 *
1295 * Get the minOccurs property
1296 *
1297 * Returns the default if not found, or the value
1298 */
1299static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001300xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1301{
Daniel Veillard4255d502002-04-16 15:50:10 +00001302 xmlChar *val, *cur;
1303 int ret = 0;
1304
1305 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1306 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001307 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001308
1309 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001310 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001311 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001312 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001313 ret = ret * 10 + (*cur - '0');
1314 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001315 }
William M. Brack76e95df2003-10-18 16:20:14 +00001316 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001317 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001318 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001319 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1320 "invalid value for minOccurs: %s\n", val, NULL);
1321 xmlFree(val);
1322 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001323 }
1324 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001325 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001326}
1327
1328/**
1329 * xmlGetBooleanProp:
1330 * @ctxt: a schema validation context
1331 * @node: a subtree containing XML Schema informations
1332 * @name: the attribute name
1333 * @def: the default value
1334 *
1335 * Get is a bolean property is set
1336 *
1337 * Returns the default if not found, 0 if found to be false,
1338 * 1 if found to be true
1339 */
1340static int
1341xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001342 const char *name, int def)
1343{
Daniel Veillard4255d502002-04-16 15:50:10 +00001344 xmlChar *val;
1345
1346 val = xmlGetProp(node, (const xmlChar *) name);
1347 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001348 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001349
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 if (xmlStrEqual(val, BAD_CAST "true"))
1351 def = 1;
1352 else if (xmlStrEqual(val, BAD_CAST "false"))
1353 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001354 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001355 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1356 "Attribute %s: the value %s is not boolean\n",
1357 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001358 }
1359 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001360 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001361}
1362
1363/************************************************************************
1364 * *
1365 * Shema extraction from an Infoset *
1366 * *
1367 ************************************************************************/
1368static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1369 ctxt, xmlSchemaPtr schema,
1370 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001371static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1372 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001373 xmlSchemaPtr schema,
1374 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001375static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1376 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001377 xmlSchemaPtr schema,
1378 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001379 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001380static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1381 xmlSchemaPtr schema,
1382 xmlNodePtr node);
1383static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1384 xmlSchemaPtr schema,
1385 xmlNodePtr node);
1386static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1387 ctxt,
1388 xmlSchemaPtr schema,
1389 xmlNodePtr node);
1390static xmlSchemaAttributeGroupPtr
1391xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1392 xmlSchemaPtr schema, xmlNodePtr node);
1393static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1394 xmlSchemaPtr schema,
1395 xmlNodePtr node);
1396static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1397 xmlSchemaPtr schema,
1398 xmlNodePtr node);
1399static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001400xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1401 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001402
1403/**
1404 * xmlSchemaParseAttrDecls:
1405 * @ctxt: a schema validation context
1406 * @schema: the schema being built
1407 * @node: a subtree containing XML Schema informations
1408 * @type: the hosting type
1409 *
1410 * parse a XML schema attrDecls declaration corresponding to
1411 * <!ENTITY % attrDecls
1412 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1413 */
1414static xmlNodePtr
1415xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1416 xmlNodePtr child, xmlSchemaTypePtr type)
1417{
1418 xmlSchemaAttributePtr lastattr, attr;
1419
1420 lastattr = NULL;
1421 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001422 (IS_SCHEMA(child, "attributeGroup"))) {
1423 attr = NULL;
1424 if (IS_SCHEMA(child, "attribute")) {
1425 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1426 } else if (IS_SCHEMA(child, "attributeGroup")) {
1427 attr = (xmlSchemaAttributePtr)
1428 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1429 }
1430 if (attr != NULL) {
1431 if (lastattr == NULL) {
1432 type->attributes = attr;
1433 lastattr = attr;
1434 } else {
1435 lastattr->next = attr;
1436 lastattr = attr;
1437 }
1438 }
1439 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001440 }
1441 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001442 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1443 if (attr != NULL) {
1444 if (lastattr == NULL) {
1445 type->attributes = attr;
1446 lastattr = attr;
1447 } else {
1448 lastattr->next = attr;
1449 lastattr = attr;
1450 }
1451 }
1452 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001453 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001455}
1456
1457/**
1458 * xmlSchemaParseAnnotation:
1459 * @ctxt: a schema validation context
1460 * @schema: the schema being built
1461 * @node: a subtree containing XML Schema informations
1462 *
1463 * parse a XML schema Attrribute declaration
1464 * *WARNING* this interface is highly subject to change
1465 *
1466 * Returns -1 in case of error, 0 if the declaration is inproper and
1467 * 1 in case of success.
1468 */
1469static xmlSchemaAnnotPtr
1470xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1471 xmlNodePtr node)
1472{
1473 xmlSchemaAnnotPtr ret;
1474
1475 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1476 return (NULL);
1477 ret = xmlSchemaNewAnnot(ctxt, node);
1478
1479 return (ret);
1480}
1481
1482/**
1483 * xmlSchemaParseFacet:
1484 * @ctxt: a schema validation context
1485 * @schema: the schema being built
1486 * @node: a subtree containing XML Schema informations
1487 *
1488 * parse a XML schema Facet declaration
1489 * *WARNING* this interface is highly subject to change
1490 *
1491 * Returns the new type structure or NULL in case of error
1492 */
1493static xmlSchemaFacetPtr
1494xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001495 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001496{
1497 xmlSchemaFacetPtr facet;
1498 xmlNodePtr child = NULL;
1499 xmlChar *value;
1500
1501 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1502 return (NULL);
1503
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001504 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001505 if (facet == NULL) {
1506 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1507 return (NULL);
1508 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001509 facet->node = node;
1510 value = xmlGetProp(node, (const xmlChar *) "value");
1511 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001512 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1513 "Facet %s has no value\n", node->name, NULL);
1514 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001515 return (NULL);
1516 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001518 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001519 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001520 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001521 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001522 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001524 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001525 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001527 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001528 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001530 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001532 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001533 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001534 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001535 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001536 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001537 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001538 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1539 } else if (IS_SCHEMA(node, "minLength")) {
1540 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1541 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1543 "Unknown facet type %s\n", node->name, NULL);
1544 xmlSchemaFreeFacet(facet);
1545 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001546 }
1547 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1548 facet->value = value;
1549 child = node->children;
1550
1551 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1553 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001554 }
1555 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001556 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1557 "Facet %s has unexpected child content\n",
1558 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001559 }
1560 return (facet);
1561}
1562
1563/**
1564 * xmlSchemaParseAny:
1565 * @ctxt: a schema validation context
1566 * @schema: the schema being built
1567 * @node: a subtree containing XML Schema informations
1568 *
1569 * parse a XML schema Any declaration
1570 * *WARNING* this interface is highly subject to change
1571 *
1572 * Returns the new type structure or NULL in case of error
1573 */
1574static xmlSchemaTypePtr
1575xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1576 xmlNodePtr node)
1577{
1578 xmlSchemaTypePtr type;
1579 xmlNodePtr child = NULL;
1580 xmlChar name[30];
1581
1582 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1583 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001585 type = xmlSchemaAddType(ctxt, schema, name);
1586 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001587 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001588 type->node = node;
1589 type->type = XML_SCHEMA_TYPE_ANY;
1590 child = node->children;
1591 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1592 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1593
1594 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001595 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1596 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001597 }
1598 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001599 xmlSchemaPErr2(ctxt, node, child,
1600 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1601 "Sequence %s has unexpected content\n", type->name,
1602 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001603 }
1604
1605 return (type);
1606}
1607
1608/**
1609 * xmlSchemaParseNotation:
1610 * @ctxt: a schema validation context
1611 * @schema: the schema being built
1612 * @node: a subtree containing XML Schema informations
1613 *
1614 * parse a XML schema Notation declaration
1615 *
1616 * Returns the new structure or NULL in case of error
1617 */
1618static xmlSchemaNotationPtr
1619xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001621{
1622 xmlChar *name;
1623 xmlSchemaNotationPtr ret;
1624 xmlNodePtr child = NULL;
1625
1626 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1627 return (NULL);
1628 name = xmlGetProp(node, (const xmlChar *) "name");
1629 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001630 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1631 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001632 return (NULL);
1633 }
1634 ret = xmlSchemaAddNotation(ctxt, schema, name);
1635 if (ret == NULL) {
1636 xmlFree(name);
1637 return (NULL);
1638 }
1639 child = node->children;
1640 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001641 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1642 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001643 }
1644 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001645 xmlSchemaPErr2(ctxt, node, child,
1646 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1647 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001648 }
1649
1650 return (ret);
1651}
1652
1653/**
1654 * xmlSchemaParseAnyAttribute:
1655 * @ctxt: a schema validation context
1656 * @schema: the schema being built
1657 * @node: a subtree containing XML Schema informations
1658 *
1659 * parse a XML schema AnyAttrribute declaration
1660 * *WARNING* this interface is highly subject to change
1661 *
1662 * Returns an attribute def structure or NULL
1663 */
1664static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001665xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1666 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001667{
1668 xmlChar *processContents;
1669 xmlSchemaAttributePtr ret;
1670 xmlNodePtr child = NULL;
1671 char name[100];
1672
1673 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1674 return (NULL);
1675
1676 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001677 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *) name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001678 if (ret == NULL) {
1679 return (NULL);
1680 }
1681 ret->id = xmlGetProp(node, (const xmlChar *) "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001682 processContents =
1683 xmlGetProp(node, (const xmlChar *) "processContents");
1684 if ((processContents == NULL)
1685 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1686 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1687 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1688 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1689 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1690 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001691 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001692 xmlSchemaPErr2(ctxt, node, child,
1693 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1694 "anyAttribute has unexpected content for processContents: %s\n",
1695 processContents, NULL);
1696 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001697 }
1698 if (processContents != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001699 xmlFree(processContents);
Daniel Veillard4255d502002-04-16 15:50:10 +00001700
1701 child = node->children;
1702 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001703 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1704 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001705 }
1706 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001707 xmlSchemaPErr2(ctxt, node, child,
1708 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1709 "anyAttribute %s has unexpected content\n",
1710 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001711 }
1712
1713 return (ret);
1714}
1715
1716
1717/**
1718 * xmlSchemaParseAttribute:
1719 * @ctxt: a schema validation context
1720 * @schema: the schema being built
1721 * @node: a subtree containing XML Schema informations
1722 *
1723 * parse a XML schema Attrribute declaration
1724 * *WARNING* this interface is highly subject to change
1725 *
1726 * Returns -1 in case of error, 0 if the declaration is inproper and
1727 * 1 in case of success.
1728 */
1729static xmlSchemaAttributePtr
1730xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1731 xmlNodePtr node)
1732{
1733 xmlChar *name, *refNs = NULL, *ref = NULL;
1734 xmlSchemaAttributePtr ret;
1735 xmlNodePtr child = NULL;
1736
1737 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1738 return (NULL);
1739 name = xmlGetProp(node, (const xmlChar *) "name");
1740 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001741 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001742
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001743 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1744 if (ref == NULL) {
1745 xmlSchemaPErr2(ctxt, node, child,
1746 XML_SCHEMAP_ATTR_NONAME_NOREF,
1747 "Attribute has no name nor ref\n", NULL, NULL);
1748 return (NULL);
1749 }
1750 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1751 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001752 }
1753 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1754 if (ret == NULL) {
1755 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001756 if (ref != NULL)
1757 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001758 return (NULL);
1759 }
1760 xmlFree(name);
1761 ret->ref = ref;
1762 ret->refNs = refNs;
1763 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001764 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001765 child = node->children;
1766 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001767 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1768 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001769 }
1770 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001771 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1772 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001773 }
1774 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001775 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
1776 "attribute %s has unexpected content\n", name,
1777 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001778 }
1779
1780 return (ret);
1781}
1782
1783/**
1784 * xmlSchemaParseAttributeGroup:
1785 * @ctxt: a schema validation context
1786 * @schema: the schema being built
1787 * @node: a subtree containing XML Schema informations
1788 *
1789 * parse a XML schema Attribute Group declaration
1790 * *WARNING* this interface is highly subject to change
1791 *
1792 * Returns the attribute group or NULL in case of error.
1793 */
1794static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001795xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1796 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001797{
1798 xmlChar *name, *refNs = NULL, *ref = NULL;
1799 xmlSchemaAttributeGroupPtr ret;
1800 xmlSchemaAttributePtr last = NULL, attr;
1801 xmlNodePtr child = NULL;
1802 xmlChar *oldcontainer;
1803
1804 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1805 return (NULL);
1806 oldcontainer = ctxt->container;
1807 name = xmlGetProp(node, (const xmlChar *) "name");
1808 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001809 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001810
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001811 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1812 if (ref == NULL) {
1813 xmlSchemaPErr2(ctxt, node, child,
1814 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
1815 "AttributeGroup has no name nor ref\n", NULL,
1816 NULL);
1817 return (NULL);
1818 }
1819 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1820 name = xmlStrdup((xmlChar *) buf);
1821 if (name == NULL) {
1822 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
1823 return (NULL);
1824 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001825 }
1826 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1827 if (ret == NULL) {
1828 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001829 if (ref != NULL)
1830 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001831 return (NULL);
1832 }
1833 ret->ref = ref;
1834 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00001835 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001836 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001837 child = node->children;
1838 ctxt->container = name;
1839 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001840 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1841 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001842 }
1843 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001844 (IS_SCHEMA(child, "attributeGroup"))) {
1845 attr = NULL;
1846 if (IS_SCHEMA(child, "attribute")) {
1847 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1848 } else if (IS_SCHEMA(child, "attributeGroup")) {
1849 attr = (xmlSchemaAttributePtr)
1850 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1851 }
1852 if (attr != NULL) {
1853 if (last == NULL) {
1854 ret->attributes = attr;
1855 last = attr;
1856 } else {
1857 last->next = attr;
1858 last = attr;
1859 }
1860 }
1861 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001862 }
1863 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001864 TODO 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_ATTRGRP_CHILD,
1869 "attribute group %s has unexpected content\n", name,
1870 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001871 }
1872
1873 ctxt->container = oldcontainer;
Daniel Veillard91a13252003-03-27 23:44:43 +00001874 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001875 return (ret);
1876}
1877
1878/**
1879 * xmlSchemaParseElement:
1880 * @ctxt: a schema validation context
1881 * @schema: the schema being built
1882 * @node: a subtree containing XML Schema informations
1883 *
1884 * parse a XML schema Element declaration
1885 * *WARNING* this interface is highly subject to change
1886 *
1887 * Returns -1 in case of error, 0 if the declaration is inproper and
1888 * 1 in case of success.
1889 */
1890static xmlSchemaElementPtr
1891xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1892 xmlNodePtr node, int toplevel)
1893{
1894 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1895 xmlSchemaElementPtr ret;
1896 xmlNodePtr child = NULL;
1897 xmlChar *oldcontainer;
1898
1899 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1900 return (NULL);
1901 oldcontainer = ctxt->container;
1902 name = xmlGetProp(node, (const xmlChar *) "name");
1903 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001904 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001905
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001906 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1907 if (ref == NULL) {
1908 xmlSchemaPErr2(ctxt, node, child,
1909 XML_SCHEMAP_ELEM_NONAME_NOREF,
1910 "Element has no name nor ref\n", NULL, NULL);
1911 return (NULL);
1912 }
1913 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1914 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001915 }
1916 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1917 if (namespace == NULL)
1918 ret =
1919 xmlSchemaAddElement(ctxt, schema, name,
1920 schema->targetNamespace);
1921 else
1922 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001923 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001924 if (namespace != NULL)
1925 xmlFree(namespace);
1926 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001927 xmlFree(name);
1928 if (ref != NULL)
1929 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001930 return (NULL);
1931 }
1932 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1933 ret->ref = ref;
1934 ret->refNs = refNs;
1935 if (ref != NULL)
1936 ret->flags |= XML_SCHEMAS_ELEM_REF;
1937 if (toplevel)
1938 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1939 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1940 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1941 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1942 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1943 ctxt->container = name;
1944
1945 ret->id = xmlGetProp(node, BAD_CAST "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001946 ret->namedType =
1947 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1948 ret->substGroup =
1949 xmlGetQNameProp(ctxt, node, "substitutionGroup",
1950 &(ret->substGroupNs));
Daniel Veillard4255d502002-04-16 15:50:10 +00001951 fixed = xmlGetProp(node, BAD_CAST "fixed");
1952 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1953 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001954
Daniel Veillard4255d502002-04-16 15:50:10 +00001955 ret->value = xmlGetProp(node, BAD_CAST "default");
1956 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001957 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
1958 "Element %s has both default and fixed\n",
1959 ret->name, NULL);
1960 xmlFree(fixed);
Daniel Veillard4255d502002-04-16 15:50:10 +00001961 } else if (fixed != NULL) {
1962 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001963 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00001964 }
1965
1966 child = node->children;
1967 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001968 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1969 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001970 }
1971 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001972 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001973 child = child->next;
1974 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001975 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001976 child = child->next;
1977 }
1978 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001979 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
1980 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001981 }
1982 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001983 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
1984 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001985 }
1986
1987 ctxt->container = oldcontainer;
1988 xmlFree(name);
1989 return (ret);
1990}
1991
1992/**
1993 * xmlSchemaParseUnion:
1994 * @ctxt: a schema validation context
1995 * @schema: the schema being built
1996 * @node: a subtree containing XML Schema informations
1997 *
1998 * parse a XML schema Union definition
1999 * *WARNING* this interface is highly subject to change
2000 *
2001 * Returns -1 in case of error, 0 if the declaration is inproper and
2002 * 1 in case of success.
2003 */
2004static xmlSchemaTypePtr
2005xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002006 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002007{
2008 xmlSchemaTypePtr type, subtype, last = NULL;
2009 xmlNodePtr child = NULL;
2010 xmlChar name[30];
2011
2012 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2013 return (NULL);
2014
2015
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002016 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002017 type = xmlSchemaAddType(ctxt, schema, name);
2018 if (type == NULL)
2019 return (NULL);
2020 type->node = node;
2021 type->type = XML_SCHEMA_TYPE_LIST;
2022 type->id = xmlGetProp(node, BAD_CAST "id");
2023 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
2024
2025 child = node->children;
2026 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002027 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2028 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 }
2030 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002031 subtype = (xmlSchemaTypePtr)
2032 xmlSchemaParseSimpleType(ctxt, schema, child);
2033 if (subtype != NULL) {
2034 if (last == NULL) {
2035 type->subtypes = subtype;
2036 last = subtype;
2037 } else {
2038 last->next = subtype;
2039 last = subtype;
2040 }
2041 last->next = NULL;
2042 }
2043 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002044 }
2045 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002046 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2047 "Union %s has unexpected content\n", type->name,
2048 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002049 }
2050 return (type);
2051}
2052
2053/**
2054 * xmlSchemaParseList:
2055 * @ctxt: a schema validation context
2056 * @schema: the schema being built
2057 * @node: a subtree containing XML Schema informations
2058 *
2059 * parse a XML schema List definition
2060 * *WARNING* this interface is highly subject to change
2061 *
2062 * Returns -1 in case of error, 0 if the declaration is inproper and
2063 * 1 in case of success.
2064 */
2065static xmlSchemaTypePtr
2066xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002067 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002068{
2069 xmlSchemaTypePtr type, subtype;
2070 xmlNodePtr child = NULL;
2071 xmlChar name[30];
2072
2073 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2074 return (NULL);
2075
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002076 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002077 type = xmlSchemaAddType(ctxt, schema, name);
2078 if (type == NULL)
2079 return (NULL);
2080 type->node = node;
2081 type->type = XML_SCHEMA_TYPE_LIST;
2082 type->id = xmlGetProp(node, BAD_CAST "id");
2083 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2084
2085 child = node->children;
2086 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002087 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 }
2090 subtype = NULL;
2091 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002092 subtype = (xmlSchemaTypePtr)
2093 xmlSchemaParseSimpleType(ctxt, schema, child);
2094 child = child->next;
2095 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002096 }
2097 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002098 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2099 "List %s has unexpected content\n", type->name,
2100 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002101 }
2102 return (type);
2103}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002104
Daniel Veillard4255d502002-04-16 15:50:10 +00002105/**
2106 * xmlSchemaParseSimpleType:
2107 * @ctxt: a schema validation context
2108 * @schema: the schema being built
2109 * @node: a subtree containing XML Schema informations
2110 *
2111 * parse a XML schema Simple Type definition
2112 * *WARNING* this interface is highly subject to change
2113 *
2114 * Returns -1 in case of error, 0 if the declaration is inproper and
2115 * 1 in case of success.
2116 */
2117static xmlSchemaTypePtr
2118xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2119 xmlNodePtr node)
2120{
2121 xmlSchemaTypePtr type, subtype;
2122 xmlNodePtr child = NULL;
2123 xmlChar *name;
2124
2125 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2126 return (NULL);
2127
2128
2129 name = xmlGetProp(node, (const xmlChar *) "name");
2130 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002131 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002132
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002133 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
2134 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002135 }
2136 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002137 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_SIMPLETYPE_NONAME,
2138 "simpleType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 return (NULL);
2140 }
2141 type = xmlSchemaAddType(ctxt, schema, name);
2142 xmlFree(name);
2143 if (type == NULL)
2144 return (NULL);
2145 type->node = node;
2146 type->type = XML_SCHEMA_TYPE_SIMPLE;
2147 type->id = xmlGetProp(node, BAD_CAST "id");
2148
2149 child = node->children;
2150 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002151 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2152 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002153 }
2154 subtype = NULL;
2155 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002156 subtype = (xmlSchemaTypePtr)
2157 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002160 subtype = (xmlSchemaTypePtr)
2161 xmlSchemaParseList(ctxt, schema, child);
2162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002163 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002164 subtype = (xmlSchemaTypePtr)
2165 xmlSchemaParseUnion(ctxt, schema, child);
2166 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002167 }
2168 type->subtypes = subtype;
2169 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002170 xmlSchemaPErr2(ctxt, node, child,
2171 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2172 "SimpleType %s has unexpected content\n",
2173 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002174 }
2175
2176 return (type);
2177}
2178
2179
2180/**
2181 * xmlSchemaParseGroup:
2182 * @ctxt: a schema validation context
2183 * @schema: the schema being built
2184 * @node: a subtree containing XML Schema informations
2185 *
2186 * parse a XML schema Group definition
2187 * *WARNING* this interface is highly subject to change
2188 *
2189 * Returns -1 in case of error, 0 if the declaration is inproper and
2190 * 1 in case of success.
2191 */
2192static xmlSchemaTypePtr
2193xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002194 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002195{
2196 xmlSchemaTypePtr type, subtype;
2197 xmlNodePtr child = NULL;
2198 xmlChar *name, *ref = NULL, *refNs = NULL;
2199
2200 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2201 return (NULL);
2202
2203
2204 name = xmlGetProp(node, (const xmlChar *) "name");
2205 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002206 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002207
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002208 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2209 if (ref == NULL) {
2210 xmlSchemaPErr2(ctxt, node, child,
2211 XML_SCHEMAP_GROUP_NONAME_NOREF,
2212 "Group has no name nor ref\n", NULL, NULL);
2213 return (NULL);
2214 }
2215 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2216 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002218 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 if (type == NULL)
2220 return (NULL);
2221 type->node = node;
2222 type->type = XML_SCHEMA_TYPE_GROUP;
2223 type->id = xmlGetProp(node, BAD_CAST "id");
2224 type->ref = ref;
2225 type->refNs = refNs;
2226 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2227 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2228
2229 child = node->children;
2230 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002233 }
2234 subtype = NULL;
2235 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002236 subtype = (xmlSchemaTypePtr)
2237 xmlSchemaParseAll(ctxt, schema, child);
2238 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002239 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002240 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002242 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 subtype = (xmlSchemaTypePtr)
2244 xmlSchemaParseSequence(ctxt, schema, child);
2245 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 }
2247 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002250 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2251 "Group %s has unexpected content\n", type->name,
2252 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002253 }
2254
2255 return (type);
2256}
2257
2258/**
2259 * xmlSchemaParseAll:
2260 * @ctxt: a schema validation context
2261 * @schema: the schema being built
2262 * @node: a subtree containing XML Schema informations
2263 *
2264 * parse a XML schema All definition
2265 * *WARNING* this interface is highly subject to change
2266 *
2267 * Returns -1 in case of error, 0 if the declaration is inproper and
2268 * 1 in case of success.
2269 */
2270static xmlSchemaTypePtr
2271xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002272 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002273{
2274 xmlSchemaTypePtr type, subtype, last = NULL;
2275 xmlNodePtr child = NULL;
2276 xmlChar name[30];
2277
2278 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2279 return (NULL);
2280
2281
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002282 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002283 type = xmlSchemaAddType(ctxt, schema, name);
2284 if (type == NULL)
2285 return (NULL);
2286 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002287 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 type->id = xmlGetProp(node, BAD_CAST "id");
2289 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2290 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2291
2292 child = node->children;
2293 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2295 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002296 }
2297 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002298 subtype = (xmlSchemaTypePtr)
2299 xmlSchemaParseElement(ctxt, schema, child, 0);
2300 if (subtype != NULL) {
2301 if (last == NULL) {
2302 type->subtypes = subtype;
2303 last = subtype;
2304 } else {
2305 last->next = subtype;
2306 last = subtype;
2307 }
2308 last->next = NULL;
2309 }
2310 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002311 }
2312 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002313 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2314 "All %s has unexpected content\n", type->name,
2315 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002316 }
2317
2318 return (type);
2319}
2320
2321/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002322 * xmlSchemaParseImport:
2323 * @ctxt: a schema validation context
2324 * @schema: the schema being built
2325 * @node: a subtree containing XML Schema informations
2326 *
2327 * parse a XML schema Import definition
2328 * *WARNING* this interface is highly subject to change
2329 *
2330 * Returns -1 in case of error, 0 if the declaration is inproper and
2331 * 1 in case of success.
2332 */
2333static int
2334xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002335 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002336{
2337 xmlNodePtr child = NULL;
2338 xmlChar *namespace;
2339 xmlChar *schemaLocation;
2340 xmlChar *previous;
2341 xmlURIPtr check;
2342
2343 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2344 return (-1);
2345
2346 namespace = xmlGetProp(node, BAD_CAST "namespace");
2347 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 check = xmlParseURI((const char *) namespace);
2349 if (check == NULL) {
2350 xmlSchemaPErr2(ctxt, node, child,
2351 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2352 "Import namespace attribute is not an URI: %s\n",
2353 namespace, NULL);
2354 xmlFree(namespace);
2355 return (-1);
2356 } else {
2357 xmlFreeURI(check);
2358 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002359 }
2360 schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2361 if (schemaLocation != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002362 check = xmlParseURI((const char *) schemaLocation);
2363 if (check == NULL) {
2364 xmlSchemaPErr2(ctxt, node, child,
2365 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2366 "Import schemaLocation attribute is not an URI: %s\n",
2367 schemaLocation, NULL);
2368 if (namespace != NULL)
2369 xmlFree(namespace);
2370 xmlFree(schemaLocation);
2371 return (-1);
2372 } else {
2373 xmlFreeURI(check);
2374 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002375 }
2376 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002377 schema->schemasImports = xmlHashCreate(10);
2378 if (schema->schemasImports == NULL) {
2379 xmlSchemaPErr2(ctxt, node, child,
2380 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2381 "Internal: failed to build import table\n",
2382 NULL, NULL);
2383 if (namespace != NULL)
2384 xmlFree(namespace);
2385 if (schemaLocation != NULL)
2386 xmlFree(schemaLocation);
2387 return (-1);
2388 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002389 }
2390 if (namespace == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002391 previous = xmlHashLookup(schema->schemasImports,
2392 XML_SCHEMAS_DEFAULT_NAMESPACE);
2393 if (schemaLocation != NULL) {
2394 if (previous != NULL) {
2395 if (!xmlStrEqual(schemaLocation, previous)) {
2396 xmlSchemaPErr2(ctxt, node, child,
2397 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2398 "Redefining import for default namespace with a different URI: %s\n",
2399 schemaLocation, NULL);
2400 }
2401 } else {
2402 xmlHashAddEntry(schema->schemasImports,
2403 XML_SCHEMAS_DEFAULT_NAMESPACE,
2404 schemaLocation);
2405 }
2406 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002407 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002408 previous = xmlHashLookup(schema->schemasImports, namespace);
2409 if (schemaLocation != NULL) {
2410 if (previous != NULL) {
2411 if (!xmlStrEqual(schemaLocation, previous)) {
2412 xmlSchemaPErr2(ctxt, node, child,
2413 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2414 "Redefining import for namespace %s with a different URI: %s\n",
2415 namespace, schemaLocation);
2416 }
2417 } else {
2418 xmlHashAddEntry(schema->schemasImports,
2419 namespace, schemaLocation);
2420 }
2421 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002422 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002423
2424 child = node->children;
2425 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002426 /*
2427 * the annotations here are simply discarded ...
2428 */
2429 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002430 }
2431 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002432 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2433 "Import has unexpected content\n", NULL, NULL);
2434 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002435 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002436 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002437}
2438
2439/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002440 * xmlSchemaParseChoice:
2441 * @ctxt: a schema validation context
2442 * @schema: the schema being built
2443 * @node: a subtree containing XML Schema informations
2444 *
2445 * parse a XML schema Choice definition
2446 * *WARNING* this interface is highly subject to change
2447 *
2448 * Returns -1 in case of error, 0 if the declaration is inproper and
2449 * 1 in case of success.
2450 */
2451static xmlSchemaTypePtr
2452xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002453 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002454{
2455 xmlSchemaTypePtr type, subtype, last = NULL;
2456 xmlNodePtr child = NULL;
2457 xmlChar name[30];
2458
2459 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2460 return (NULL);
2461
2462
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002463 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002464 type = xmlSchemaAddType(ctxt, schema, name);
2465 if (type == NULL)
2466 return (NULL);
2467 type->node = node;
2468 type->type = XML_SCHEMA_TYPE_CHOICE;
2469 type->id = xmlGetProp(node, BAD_CAST "id");
2470 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2471 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2472
2473 child = node->children;
2474 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002475 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2476 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002477 }
2478 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002479 (IS_SCHEMA(child, "group")) ||
2480 (IS_SCHEMA(child, "any")) ||
2481 (IS_SCHEMA(child, "choice")) ||
2482 (IS_SCHEMA(child, "sequence"))) {
2483 subtype = NULL;
2484 if (IS_SCHEMA(child, "element")) {
2485 subtype = (xmlSchemaTypePtr)
2486 xmlSchemaParseElement(ctxt, schema, child, 0);
2487 } else if (IS_SCHEMA(child, "group")) {
2488 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2489 } else if (IS_SCHEMA(child, "any")) {
2490 subtype = xmlSchemaParseAny(ctxt, schema, child);
2491 } else if (IS_SCHEMA(child, "sequence")) {
2492 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2493 } else if (IS_SCHEMA(child, "choice")) {
2494 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2495 }
2496 if (subtype != NULL) {
2497 if (last == NULL) {
2498 type->subtypes = subtype;
2499 last = subtype;
2500 } else {
2501 last->next = subtype;
2502 last = subtype;
2503 }
2504 last->next = NULL;
2505 }
2506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 }
2508 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002509 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
2510 "Choice %s has unexpected content\n", type->name,
2511 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002512 }
2513
2514 return (type);
2515}
2516
2517/**
2518 * xmlSchemaParseSequence:
2519 * @ctxt: a schema validation context
2520 * @schema: the schema being built
2521 * @node: a subtree containing XML Schema informations
2522 *
2523 * parse a XML schema Sequence definition
2524 * *WARNING* this interface is highly subject to change
2525 *
2526 * Returns -1 in case of error, 0 if the declaration is inproper and
2527 * 1 in case of success.
2528 */
2529static xmlSchemaTypePtr
2530xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002531 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002532{
2533 xmlSchemaTypePtr type, subtype, last = NULL;
2534 xmlNodePtr child = NULL;
2535 xmlChar name[30];
2536
2537 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2538 return (NULL);
2539
2540
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002541 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002542 type = xmlSchemaAddType(ctxt, schema, name);
2543 if (type == NULL)
2544 return (NULL);
2545 type->node = node;
2546 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2547 type->id = xmlGetProp(node, BAD_CAST "id");
2548 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2549 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2550
2551 child = node->children;
2552 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002553 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2554 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002555 }
2556 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002557 (IS_SCHEMA(child, "group")) ||
2558 (IS_SCHEMA(child, "any")) ||
2559 (IS_SCHEMA(child, "choice")) ||
2560 (IS_SCHEMA(child, "sequence"))) {
2561 subtype = NULL;
2562 if (IS_SCHEMA(child, "element")) {
2563 subtype = (xmlSchemaTypePtr)
2564 xmlSchemaParseElement(ctxt, schema, child, 0);
2565 } else if (IS_SCHEMA(child, "group")) {
2566 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2567 } else if (IS_SCHEMA(child, "any")) {
2568 subtype = xmlSchemaParseAny(ctxt, schema, child);
2569 } else if (IS_SCHEMA(child, "choice")) {
2570 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2571 } else if (IS_SCHEMA(child, "sequence")) {
2572 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2573 }
2574 if (subtype != NULL) {
2575 if (last == NULL) {
2576 type->subtypes = subtype;
2577 last = subtype;
2578 } else {
2579 last->next = subtype;
2580 last = subtype;
2581 }
2582 last->next = NULL;
2583 }
2584 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002585 }
2586 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002587 xmlSchemaPErr2(ctxt, node, child,
2588 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2589 "Sequence %s has unexpected content\n", type->name,
2590 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002591 }
2592
2593 return (type);
2594}
2595
2596/**
2597 * xmlSchemaParseRestriction:
2598 * @ctxt: a schema validation context
2599 * @schema: the schema being built
2600 * @node: a subtree containing XML Schema informations
2601 * @simple: is that part of a simple type.
2602 *
2603 * parse a XML schema Restriction definition
2604 * *WARNING* this interface is highly subject to change
2605 *
2606 * Returns the type definition or NULL in case of error
2607 */
2608static xmlSchemaTypePtr
2609xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2610 xmlNodePtr node, int simple)
2611{
2612 xmlSchemaTypePtr type, subtype;
2613 xmlSchemaFacetPtr facet, lastfacet = NULL;
2614 xmlNodePtr child = NULL;
2615 xmlChar name[30];
2616 xmlChar *oldcontainer;
2617
2618 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2619 return (NULL);
2620
2621 oldcontainer = ctxt->container;
2622
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002623 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002624 type = xmlSchemaAddType(ctxt, schema, name);
2625 if (type == NULL)
2626 return (NULL);
2627 type->node = node;
2628 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2629 type->id = xmlGetProp(node, BAD_CAST "id");
2630 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2631 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002632 xmlSchemaPErr2(ctxt, node, child,
2633 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
2634 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002635 }
2636 ctxt->container = name;
2637
2638 child = node->children;
2639 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002640 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002642 }
2643 subtype = NULL;
2644
2645 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002646 subtype = (xmlSchemaTypePtr)
2647 xmlSchemaParseAll(ctxt, schema, child);
2648 child = child->next;
2649 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002650 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002651 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2652 child = child->next;
2653 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 subtype = (xmlSchemaTypePtr)
2656 xmlSchemaParseSequence(ctxt, schema, child);
2657 child = child->next;
2658 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002660 subtype = (xmlSchemaTypePtr)
2661 xmlSchemaParseGroup(ctxt, schema, child);
2662 child = child->next;
2663 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002664 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002665 if (IS_SCHEMA(child, "simpleType")) {
2666 subtype = (xmlSchemaTypePtr)
2667 xmlSchemaParseSimpleType(ctxt, schema, child);
2668 child = child->next;
2669 type->baseType = subtype;
2670 }
2671 /*
2672 * Facets
2673 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002674 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002675 (IS_SCHEMA(child, "minExclusive")) ||
2676 (IS_SCHEMA(child, "maxInclusive")) ||
2677 (IS_SCHEMA(child, "maxExclusive")) ||
2678 (IS_SCHEMA(child, "totalDigits")) ||
2679 (IS_SCHEMA(child, "fractionDigits")) ||
2680 (IS_SCHEMA(child, "pattern")) ||
2681 (IS_SCHEMA(child, "enumeration")) ||
2682 (IS_SCHEMA(child, "whiteSpace")) ||
2683 (IS_SCHEMA(child, "length")) ||
2684 (IS_SCHEMA(child, "maxLength")) ||
2685 (IS_SCHEMA(child, "minLength"))) {
2686 facet = xmlSchemaParseFacet(ctxt, schema, child);
2687 if (facet != NULL) {
2688 if (lastfacet == NULL) {
2689 type->facets = facet;
2690 lastfacet = facet;
2691 } else {
2692 lastfacet->next = facet;
2693 lastfacet = facet;
2694 }
2695 lastfacet->next = NULL;
2696 }
2697 child = child->next;
2698 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002699 }
2700 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2701 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002702 xmlSchemaPErr2(ctxt, node, child,
2703 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
2704 "Restriction %s has unexpected content\n",
2705 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 }
2707 ctxt->container = oldcontainer;
2708 return (type);
2709}
2710
2711/**
2712 * xmlSchemaParseExtension:
2713 * @ctxt: a schema validation context
2714 * @schema: the schema being built
2715 * @node: a subtree containing XML Schema informations
2716 *
2717 * parse a XML schema Extension definition
2718 * *WARNING* this interface is highly subject to change
2719 *
2720 * Returns the type definition or NULL in case of error
2721 */
2722static xmlSchemaTypePtr
2723xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002724 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002725{
2726 xmlSchemaTypePtr type, subtype;
2727 xmlNodePtr child = NULL;
2728 xmlChar name[30];
2729 xmlChar *oldcontainer;
2730
2731 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2732 return (NULL);
2733
2734 oldcontainer = ctxt->container;
2735
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002736 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002737 type = xmlSchemaAddType(ctxt, schema, name);
2738 if (type == NULL)
2739 return (NULL);
2740 type->node = node;
2741 type->type = XML_SCHEMA_TYPE_EXTENSION;
2742 type->id = xmlGetProp(node, BAD_CAST "id");
2743 ctxt->container = name;
2744
2745 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2746 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002747 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
2748 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 }
2750 child = node->children;
2751 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002752 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2753 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002754 }
2755 subtype = NULL;
2756
2757 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002758 subtype = xmlSchemaParseAll(ctxt, schema, child);
2759 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002760 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002761 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2762 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002763 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2765 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002767 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2768 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002769 }
2770 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002771 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002772 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2773 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002774 xmlSchemaPErr2(ctxt, node, child,
2775 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
2776 "Extension %s has unexpected content\n", type->name,
2777 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002778 }
2779 ctxt->container = oldcontainer;
2780 return (type);
2781}
2782
2783/**
2784 * xmlSchemaParseSimpleContent:
2785 * @ctxt: a schema validation context
2786 * @schema: the schema being built
2787 * @node: a subtree containing XML Schema informations
2788 *
2789 * parse a XML schema SimpleContent definition
2790 * *WARNING* this interface is highly subject to change
2791 *
2792 * Returns the type definition or NULL in case of error
2793 */
2794static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002795xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
2796 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002797{
2798 xmlSchemaTypePtr type, subtype;
2799 xmlNodePtr child = NULL;
2800 xmlChar name[30];
2801
2802 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2803 return (NULL);
2804
2805
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002806 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002807 type = xmlSchemaAddType(ctxt, schema, name);
2808 if (type == NULL)
2809 return (NULL);
2810 type->node = node;
2811 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2812 type->id = xmlGetProp(node, BAD_CAST "id");
2813
2814 child = node->children;
2815 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002816 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2817 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002818 }
2819 subtype = NULL;
2820 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002821 subtype = (xmlSchemaTypePtr)
2822 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2823 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002824 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002825 subtype = (xmlSchemaTypePtr)
2826 xmlSchemaParseExtension(ctxt, schema, child);
2827 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002828 }
2829 type->subtypes = subtype;
2830 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002831 xmlSchemaPErr2(ctxt, node, child,
2832 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
2833 "SimpleContent %s has unexpected content\n",
2834 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 }
2836 return (type);
2837}
2838
2839/**
2840 * xmlSchemaParseComplexContent:
2841 * @ctxt: a schema validation context
2842 * @schema: the schema being built
2843 * @node: a subtree containing XML Schema informations
2844 *
2845 * parse a XML schema ComplexContent definition
2846 * *WARNING* this interface is highly subject to change
2847 *
2848 * Returns the type definition or NULL in case of error
2849 */
2850static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002851xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
2852 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002853{
2854 xmlSchemaTypePtr type, subtype;
2855 xmlNodePtr child = NULL;
2856 xmlChar name[30];
2857
2858 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2859 return (NULL);
2860
2861
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002862 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002863 type = xmlSchemaAddType(ctxt, schema, name);
2864 if (type == NULL)
2865 return (NULL);
2866 type->node = node;
2867 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2868 type->id = xmlGetProp(node, BAD_CAST "id");
2869
2870 child = node->children;
2871 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002872 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2873 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002874 }
2875 subtype = NULL;
2876 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 subtype = (xmlSchemaTypePtr)
2878 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2879 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002880 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002881 subtype = (xmlSchemaTypePtr)
2882 xmlSchemaParseExtension(ctxt, schema, child);
2883 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002884 }
2885 type->subtypes = subtype;
2886 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002887 xmlSchemaPErr2(ctxt, node, child,
2888 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
2889 "ComplexContent %s has unexpected content\n",
2890 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002891 }
2892 return (type);
2893}
2894
2895/**
2896 * xmlSchemaParseComplexType:
2897 * @ctxt: a schema validation context
2898 * @schema: the schema being built
2899 * @node: a subtree containing XML Schema informations
2900 *
2901 * parse a XML schema Complex Type definition
2902 * *WARNING* this interface is highly subject to change
2903 *
2904 * Returns the type definition or NULL in case of error
2905 */
2906static xmlSchemaTypePtr
2907xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2908 xmlNodePtr node)
2909{
2910 xmlSchemaTypePtr type, subtype;
2911 xmlNodePtr child = NULL;
2912 xmlChar *name;
2913 xmlChar *oldcontainer;
2914
2915 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2916 return (NULL);
2917
2918 oldcontainer = ctxt->container;
2919 name = xmlGetProp(node, (const xmlChar *) "name");
2920 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002921 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002922
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002923 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2924 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002925 }
2926 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002927 xmlSchemaPErr2(ctxt, node, child,
2928 XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF,
2929 "complexType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002930 return (NULL);
2931 }
2932 type = xmlSchemaAddType(ctxt, schema, name);
2933 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002934 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002935 return (NULL);
2936 }
2937 type->node = node;
2938 type->type = XML_SCHEMA_TYPE_COMPLEX;
2939 type->id = xmlGetProp(node, BAD_CAST "id");
2940 ctxt->container = name;
2941
2942 child = node->children;
2943 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002944 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2945 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002946 }
2947 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002948 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
2949 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002950 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002951 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2952 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002953 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002954 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002955
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002956 if (IS_SCHEMA(child, "all")) {
2957 subtype = xmlSchemaParseAll(ctxt, schema, child);
2958 child = child->next;
2959 } else if (IS_SCHEMA(child, "choice")) {
2960 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2961 child = child->next;
2962 } else if (IS_SCHEMA(child, "sequence")) {
2963 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2964 child = child->next;
2965 } else if (IS_SCHEMA(child, "group")) {
2966 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2967 child = child->next;
2968 }
2969 if (subtype != NULL)
2970 type->subtypes = subtype;
2971 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002972 }
2973 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002974 xmlSchemaPErr2(ctxt, node, child,
2975 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
2976 "ComplexType %s has unexpected content\n",
2977 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 }
2979 ctxt->container = oldcontainer;
2980 xmlFree(name);
2981 return (type);
2982}
2983
2984
2985/**
2986 * xmlSchemaParseSchema:
2987 * @ctxt: a schema validation context
2988 * @node: a subtree containing XML Schema informations
2989 *
2990 * parse a XML schema definition from a node set
2991 * *WARNING* this interface is highly subject to change
2992 *
2993 * Returns the internal XML Schema structure built from the resource or
2994 * NULL in case of error
2995 */
2996static xmlSchemaPtr
2997xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2998{
2999 xmlSchemaPtr schema = NULL;
3000 xmlSchemaAnnotPtr annot;
3001 xmlNodePtr child = NULL;
3002 xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003003 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003004
3005 if ((ctxt == NULL) || (node == NULL))
3006 return (NULL);
3007
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003008 nberrors = ctxt->nberrors;
3009 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003010 if (IS_SCHEMA(node, "schema")) {
3011 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003012 if (schema == NULL)
3013 return (NULL);
3014 schema->targetNamespace =
3015 xmlGetProp(node, BAD_CAST "targetNamespace");
3016 schema->id = xmlGetProp(node, BAD_CAST "id");
3017 schema->version = xmlGetProp(node, BAD_CAST "version");
3018 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
3019 if (val != NULL) {
3020 if (xmlStrEqual(val, BAD_CAST "qualified"))
3021 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3022 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3023 xmlSchemaPErr2(ctxt, node, child,
3024 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3025 "Invalid value %s for elementFormDefault\n",
3026 val, NULL);
3027 }
3028 xmlFree(val);
3029 }
3030 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
3031 if (val != NULL) {
3032 if (xmlStrEqual(val, BAD_CAST "qualified"))
3033 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3034 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3035 xmlSchemaPErr2(ctxt, node, child,
3036 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3037 "Invalid value %s for attributeFormDefault\n",
3038 val, NULL);
3039 }
3040 xmlFree(val);
3041 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003042
3043 child = node->children;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003044 while ((IS_SCHEMA(child, "include")) ||
3045 (IS_SCHEMA(child, "import")) ||
3046 (IS_SCHEMA(child, "redefine")) ||
3047 (IS_SCHEMA(child, "annotation"))) {
3048 if (IS_SCHEMA(child, "annotation")) {
3049 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3050 if (schema->annot == NULL)
3051 schema->annot = annot;
3052 else
3053 xmlSchemaFreeAnnot(annot);
3054 } else if (IS_SCHEMA(child, "include")) {
3055 TODO} else if (IS_SCHEMA(child, "import")) {
3056 xmlSchemaParseImport(ctxt, schema, child);
3057 } else if (IS_SCHEMA(child, "redefine")) {
3058 TODO}
3059 child = child->next;
3060 }
3061 while (child != NULL) {
3062 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003064 child = child->next;
3065 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003066 xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003067 child = child->next;
3068 } else if (IS_SCHEMA(child, "element")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003069 xmlSchemaParseElement(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003070 child = child->next;
3071 } else if (IS_SCHEMA(child, "attribute")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 xmlSchemaParseAttribute(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003073 child = child->next;
3074 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003075 xmlSchemaParseAttributeGroup(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003076 child = child->next;
3077 } else if (IS_SCHEMA(child, "group")) {
3078 xmlSchemaParseGroup(ctxt, schema, child);
3079 child = child->next;
3080 } else if (IS_SCHEMA(child, "notation")) {
3081 xmlSchemaParseNotation(ctxt, schema, child);
3082 child = child->next;
3083 } else {
3084 xmlSchemaPErr2(ctxt, node, child,
3085 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3086 "Schemas: unexpected element %s here \n",
3087 child->name, NULL);
3088 child = child->next;
3089 }
3090 while (IS_SCHEMA(child, "annotation")) {
3091 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3092 if (schema->annot == NULL)
3093 schema->annot = annot;
3094 else
3095 xmlSchemaFreeAnnot(annot);
3096 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003097 }
3098 }
3099 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003100 if (ctxt->nberrors != 0) {
3101 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003102 xmlSchemaFree(schema);
3103 schema = NULL;
3104 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003105 }
3106 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003107#ifdef DEBUG
3108 if (schema == NULL)
3109 xmlGenericError(xmlGenericErrorContext,
3110 "xmlSchemaParse() failed\n");
3111#endif
3112
3113 return (schema);
3114}
3115
3116/************************************************************************
3117 * *
3118 * Validating using Schemas *
3119 * *
3120 ************************************************************************/
3121
3122/************************************************************************
3123 * *
3124 * Reading/Writing Schemas *
3125 * *
3126 ************************************************************************/
3127
3128/**
3129 * xmlSchemaNewParserCtxt:
3130 * @URL: the location of the schema
3131 *
3132 * Create an XML Schemas parse context for that file/resource expected
3133 * to contain an XML Schemas file.
3134 *
3135 * Returns the parser context or NULL in case of error
3136 */
3137xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003138xmlSchemaNewParserCtxt(const char *URL)
3139{
Daniel Veillard4255d502002-04-16 15:50:10 +00003140 xmlSchemaParserCtxtPtr ret;
3141
3142 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003143 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003144
3145 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3146 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003147 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3148 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003149 return (NULL);
3150 }
3151 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003152 ret->URL = xmlStrdup((const xmlChar *) URL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 return (ret);
3154}
3155
3156/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003157 * xmlSchemaNewMemParserCtxt:
3158 * @buffer: a pointer to a char array containing the schemas
3159 * @size: the size of the array
3160 *
3161 * Create an XML Schemas parse context for that memory buffer expected
3162 * to contain an XML Schemas file.
3163 *
3164 * Returns the parser context or NULL in case of error
3165 */
3166xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003167xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3168{
Daniel Veillard6045c902002-10-09 21:13:59 +00003169 xmlSchemaParserCtxtPtr ret;
3170
3171 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003172 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003173
3174 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3175 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003176 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3177 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003178 return (NULL);
3179 }
3180 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3181 ret->buffer = buffer;
3182 ret->size = size;
3183 return (ret);
3184}
3185
3186/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003187 * xmlSchemaFreeParserCtxt:
3188 * @ctxt: the schema parser context
3189 *
3190 * Free the resources associated to the schema parser context
3191 */
3192void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003193xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3194{
Daniel Veillard4255d502002-04-16 15:50:10 +00003195 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003196 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003197 if (ctxt->URL != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003198 xmlFree(ctxt->URL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003199 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003200 xmlFreeDoc(ctxt->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00003201 xmlFree(ctxt);
3202}
3203
3204/************************************************************************
3205 * *
3206 * Building the content models *
3207 * *
3208 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003209
Daniel Veillard4255d502002-04-16 15:50:10 +00003210/**
3211 * xmlSchemaBuildAContentModel:
3212 * @type: the schema type definition
3213 * @ctxt: the schema parser context
3214 * @name: the element name whose content is being built
3215 *
3216 * Generate the automata sequence needed for that type
3217 */
3218static void
3219xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003220 xmlSchemaParserCtxtPtr ctxt,
3221 const xmlChar * name)
3222{
Daniel Veillard4255d502002-04-16 15:50:10 +00003223 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003224 xmlGenericError(xmlGenericErrorContext,
3225 "Found unexpected type = NULL in %s content model\n",
3226 name);
3227 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003228 }
3229 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003230 case XML_SCHEMA_TYPE_ANY:
3231 /* TODO : handle the namespace too */
3232 /* TODO : make that a specific transition type */
3233 TODO ctxt->state =
3234 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3235 BAD_CAST "*", NULL);
3236 break;
3237 case XML_SCHEMA_TYPE_ELEMENT:{
3238 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003239
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003240 /* TODO : handle the namespace too */
3241 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003242
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003243 if (elem->maxOccurs >= UNBOUNDED) {
3244 if (elem->minOccurs > 1) {
3245 xmlAutomataStatePtr tmp;
3246 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003247
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003248 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3249 oldstate,
3250 NULL);
3251 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003252
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003253 counter = xmlAutomataNewCounter(ctxt->am,
3254 elem->minOccurs -
3255 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003256
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003257 if (elem->refDecl != NULL) {
3258 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3259 elem->refDecl,
3260 ctxt,
3261 elem->refDecl->
3262 name);
3263 } else {
3264 ctxt->state =
3265 xmlAutomataNewTransition(ctxt->am,
3266 ctxt->state, NULL,
3267 elem->name, type);
3268 }
3269 tmp = ctxt->state;
3270 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3271 counter);
3272 ctxt->state =
3273 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3274 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003275
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003276 } else {
3277 if (elem->refDecl != NULL) {
3278 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3279 elem->refDecl,
3280 ctxt,
3281 elem->refDecl->
3282 name);
3283 } else {
3284 ctxt->state =
3285 xmlAutomataNewTransition(ctxt->am,
3286 ctxt->state, NULL,
3287 elem->name, type);
3288 }
3289 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3290 oldstate);
3291 if (elem->minOccurs == 0) {
3292 /* basically an elem* */
3293 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3294 ctxt->state);
3295 }
3296 }
3297 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3298 xmlAutomataStatePtr tmp;
3299 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003300
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3302 oldstate, NULL);
3303 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003304
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003305 counter = xmlAutomataNewCounter(ctxt->am,
3306 elem->minOccurs - 1,
3307 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003308
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003309 if (elem->refDecl != NULL) {
3310 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3311 elem->refDecl, ctxt,
3312 elem->refDecl->name);
3313 } else {
3314 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3315 ctxt->state,
3316 NULL,
3317 elem->name,
3318 type);
3319 }
3320 tmp = ctxt->state;
3321 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3322 counter);
3323 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3324 NULL,
3325 counter);
3326 if (elem->minOccurs == 0) {
3327 /* basically an elem? */
3328 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3329 ctxt->state);
3330 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003331
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003332 } else {
3333 if (elem->refDecl != NULL) {
3334 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3335 elem->refDecl, ctxt,
3336 elem->refDecl->name);
3337 } else {
3338 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3339 ctxt->state,
3340 NULL,
3341 elem->name,
3342 type);
3343 }
3344 if (elem->minOccurs == 0) {
3345 /* basically an elem? */
3346 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3347 ctxt->state);
3348 }
3349 }
3350 break;
3351 }
3352 case XML_SCHEMA_TYPE_SEQUENCE:{
3353 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003354
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003355 /*
3356 * If max and min occurances are default (1) then
3357 * simply iterate over the subtypes
3358 */
3359 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
3360 subtypes = type->subtypes;
3361 while (subtypes != NULL) {
3362 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3363 subtypes = subtypes->next;
3364 }
3365 } else {
3366 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003367
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003368 if (type->maxOccurs >= UNBOUNDED) {
3369 if (type->minOccurs > 1) {
3370 xmlAutomataStatePtr tmp;
3371 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003372
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003373 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3374 oldstate,
3375 NULL);
3376 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003377
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003378 counter = xmlAutomataNewCounter(ctxt->am,
3379 type->
3380 minOccurs - 1,
3381 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003382
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003383 subtypes = type->subtypes;
3384 while (subtypes != NULL) {
3385 xmlSchemaBuildAContentModel(subtypes, ctxt,
3386 name);
3387 subtypes = subtypes->next;
3388 }
3389 tmp = ctxt->state;
3390 xmlAutomataNewCountedTrans(ctxt->am, tmp,
3391 oldstate, counter);
3392 ctxt->state =
3393 xmlAutomataNewCounterTrans(ctxt->am, tmp,
3394 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003395
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003396 } else {
3397 subtypes = type->subtypes;
3398 while (subtypes != NULL) {
3399 xmlSchemaBuildAContentModel(subtypes, ctxt,
3400 name);
3401 subtypes = subtypes->next;
3402 }
3403 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3404 oldstate);
3405 if (type->minOccurs == 0) {
3406 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3407 ctxt->state);
3408 }
3409 }
3410 } else if ((type->maxOccurs > 1)
3411 || (type->minOccurs > 1)) {
3412 xmlAutomataStatePtr tmp;
3413 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003414
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003415 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3416 oldstate,
3417 NULL);
3418 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00003419
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003420 counter = xmlAutomataNewCounter(ctxt->am,
3421 type->minOccurs -
3422 1,
3423 type->maxOccurs -
3424 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003425
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003426 subtypes = type->subtypes;
3427 while (subtypes != NULL) {
3428 xmlSchemaBuildAContentModel(subtypes, ctxt,
3429 name);
3430 subtypes = subtypes->next;
3431 }
3432 tmp = ctxt->state;
3433 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3434 counter);
3435 ctxt->state =
3436 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3437 counter);
3438 if (type->minOccurs == 0) {
3439 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3440 ctxt->state);
3441 }
Daniel Veillardb509f152002-04-17 16:28:10 +00003442
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003443 } else {
3444 subtypes = type->subtypes;
3445 while (subtypes != NULL) {
3446 xmlSchemaBuildAContentModel(subtypes, ctxt,
3447 name);
3448 subtypes = subtypes->next;
3449 }
3450 if (type->minOccurs == 0) {
3451 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3452 ctxt->state);
3453 }
3454 }
3455 }
3456 break;
3457 }
3458 case XML_SCHEMA_TYPE_CHOICE:{
3459 xmlSchemaTypePtr subtypes;
3460 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00003461
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003462 start = ctxt->state;
3463 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00003464
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003465 /*
3466 * iterate over the subtypes and remerge the end with an
3467 * epsilon transition
3468 */
3469 if (type->maxOccurs == 1) {
3470 subtypes = type->subtypes;
3471 while (subtypes != NULL) {
3472 ctxt->state = start;
3473 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3474 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3475 subtypes = subtypes->next;
3476 }
3477 } else {
3478 int counter;
3479 xmlAutomataStatePtr hop;
3480 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3481 UNBOUNDED : type->maxOccurs - 1;
3482 int minOccurs =
3483 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00003484
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003485 /*
3486 * use a counter to keep track of the number of transtions
3487 * which went through the choice.
3488 */
3489 counter =
3490 xmlAutomataNewCounter(ctxt->am, minOccurs,
3491 maxOccurs);
3492 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00003493
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003494 subtypes = type->subtypes;
3495 while (subtypes != NULL) {
3496 ctxt->state = start;
3497 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3498 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3499 subtypes = subtypes->next;
3500 }
3501 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
3502 counter);
3503 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
3504 counter);
3505 }
3506 if (type->minOccurs == 0) {
3507 xmlAutomataNewEpsilon(ctxt->am, start, end);
3508 }
3509 ctxt->state = end;
3510 break;
3511 }
3512 case XML_SCHEMA_TYPE_ALL:{
3513 xmlAutomataStatePtr start;
3514 xmlSchemaTypePtr subtypes;
3515 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3516 int lax;
3517
3518 subtypes = type->subtypes;
3519 if (subtypes == NULL)
3520 break;
3521 start = ctxt->state;
3522 while (subtypes != NULL) {
3523 ctxt->state = start;
3524 elem = (xmlSchemaElementPtr) subtypes;
3525
3526 /* TODO : handle the namespace too */
3527 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3528 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
3529 ctxt->state, elem->name, 1,
3530 1, subtypes);
3531 } else {
3532 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
3533 ctxt->state, elem->name,
3534 elem->minOccurs,
3535 elem->maxOccurs,
3536 subtypes);
3537 }
3538 subtypes = subtypes->next;
3539 }
3540 lax = type->minOccurs == 0;
3541 ctxt->state =
3542 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3543 lax);
3544 break;
3545 }
3546 case XML_SCHEMA_TYPE_RESTRICTION:
3547 if (type->subtypes != NULL)
3548 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3549 break;
3550 case XML_SCHEMA_TYPE_EXTENSION:
3551 if (type->baseType != NULL) {
3552 xmlSchemaTypePtr subtypes;
3553
3554 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3555 subtypes = type->subtypes;
3556 while (subtypes != NULL) {
3557 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3558 subtypes = subtypes->next;
3559 }
3560 } else if (type->subtypes != NULL)
3561 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3562 break;
3563 case XML_SCHEMA_TYPE_GROUP:
3564 if (type->subtypes == NULL) {
3565 }
3566 case XML_SCHEMA_TYPE_COMPLEX:
3567 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3568 if (type->subtypes != NULL)
3569 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3570 break;
3571 default:
3572 xmlGenericError(xmlGenericErrorContext,
3573 "Found unexpected type %d in %s content model\n",
3574 type->type, name);
3575 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003576 }
3577}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003578
Daniel Veillard4255d502002-04-16 15:50:10 +00003579/**
3580 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003581 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00003582 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003583 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00003584 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003585 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00003586 */
3587static void
3588xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003589 xmlSchemaParserCtxtPtr ctxt,
3590 const xmlChar * name)
3591{
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 xmlAutomataStatePtr start;
3593
Daniel Veillard4255d502002-04-16 15:50:10 +00003594 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003595 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003596 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003597 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3598 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003599 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003601 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003602 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003603 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003604
3605#ifdef DEBUG_CONTENT
3606 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003607 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003608#endif
3609
Daniel Veillard4255d502002-04-16 15:50:10 +00003610 ctxt->am = xmlNewAutomata();
3611 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003612 xmlGenericError(xmlGenericErrorContext,
3613 "Cannot create automata for elem %s\n", name);
3614 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 }
3616 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3617 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3618 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00003619 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003620 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003621 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
3622 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003623 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
3625 "Content model of %s is not determinist:\n", name,
3626 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003627 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00003628#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003629 xmlGenericError(xmlGenericErrorContext,
3630 "Content model of %s:\n", name);
3631 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003632#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003633 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003634 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 xmlFreeAutomata(ctxt->am);
3636 ctxt->am = NULL;
3637}
3638
3639/**
3640 * xmlSchemaRefFixupCallback:
3641 * @elem: the schema element context
3642 * @ctxt: the schema parser context
3643 *
3644 * Free the resources associated to the schema parser context
3645 */
3646static void
3647xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 xmlSchemaParserCtxtPtr ctxt,
3649 const xmlChar * name,
3650 const xmlChar * context ATTRIBUTE_UNUSED,
3651 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003652{
3653 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003654 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003655 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003657
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003658 if (elem->subtypes != NULL) {
3659 xmlSchemaPErr(ctxt, elem->node,
3660 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
3661 "Schemas: element %s have both ref and subtype\n",
3662 name, NULL);
3663 return;
3664 }
3665 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3666 elem->ref, elem->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003667
3668 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003669 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
3670 "Schemas: element %s ref to %s not found\n",
3671 name, elem->ref);
3672 return;
3673 }
3674 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003675 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003676 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 if (elem->subtypes != NULL) {
3679 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
3680 "Schemas: element %s have both type and subtype\n",
3681 name, NULL);
3682 return;
3683 }
3684 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3685 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003686
3687 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
3689 "Schemas: element %s type %s not found\n", name,
3690 elem->namedType);
3691 return;
3692 }
3693 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 }
3695}
3696
3697/**
3698 * xmlSchemaTypeFixup:
3699 * @typeDecl: the schema type definition
3700 * @ctxt: the schema parser context
3701 *
3702 * Fixes the content model of the type.
3703 */
3704static void
3705xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003706 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003707{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00003708 if (typeDecl == NULL)
3709 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003711 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003713 switch (typeDecl->type) {
3714 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
3715 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3716 if (typeDecl->subtypes != NULL)
3717 typeDecl->contentType =
3718 typeDecl->subtypes->contentType;
3719 break;
3720 }
3721 case XML_SCHEMA_TYPE_RESTRICTION:{
3722 if (typeDecl->subtypes != NULL)
3723 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003724
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003725 if (typeDecl->base != NULL) {
3726 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003727
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003728 baseType =
3729 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3730 typeDecl->baseNs);
3731 if (baseType == NULL) {
3732 xmlSchemaPErr(ctxt, typeDecl->node,
3733 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003735 name, typeDecl->base);
3736 }
3737 typeDecl->baseType = baseType;
3738 }
3739 if (typeDecl->subtypes == NULL)
3740 /* 1.1.1 */
3741 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3742 else if ((typeDecl->subtypes->subtypes == NULL) &&
3743 ((typeDecl->subtypes->type ==
3744 XML_SCHEMA_TYPE_ALL)
3745 || (typeDecl->subtypes->type ==
3746 XML_SCHEMA_TYPE_SEQUENCE)))
3747 /* 1.1.2 */
3748 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3749 else if ((typeDecl->subtypes->type ==
3750 XML_SCHEMA_TYPE_CHOICE)
3751 && (typeDecl->subtypes->subtypes == NULL))
3752 /* 1.1.3 */
3753 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3754 else {
3755 /* 1.2 and 2.X are applied at the other layer */
3756 typeDecl->contentType =
3757 XML_SCHEMA_CONTENT_ELEMENTS;
3758 }
3759 break;
3760 }
3761 case XML_SCHEMA_TYPE_EXTENSION:{
3762 xmlSchemaContentType explicitContentType;
3763 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00003764
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003765 if (typeDecl->base != NULL) {
3766 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003767
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003768 baseType =
3769 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3770 typeDecl->baseNs);
3771 if (baseType == NULL) {
3772 xmlSchemaPErr(ctxt, typeDecl->node,
3773 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003775 name, typeDecl->base);
3776 }
3777 typeDecl->baseType = baseType;
3778 }
3779 if (typeDecl->subtypes != NULL)
3780 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003781
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003782 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3783 if (typeDecl->subtypes == NULL)
3784 /* 1.1.1 */
3785 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3786 else if ((typeDecl->subtypes->subtypes == NULL) &&
3787 ((typeDecl->subtypes->type ==
3788 XML_SCHEMA_TYPE_ALL)
3789 || (typeDecl->subtypes->type ==
3790 XML_SCHEMA_TYPE_SEQUENCE)))
3791 /* 1.1.2 */
3792 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3793 else if ((typeDecl->subtypes->type ==
3794 XML_SCHEMA_TYPE_CHOICE)
3795 && (typeDecl->subtypes->subtypes == NULL))
3796 /* 1.1.3 */
3797 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003798
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003799 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3800 typeDecl->baseNs);
3801 if (base == NULL) {
3802 xmlSchemaPErr(ctxt, typeDecl->node,
3803 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
3804 "Schemas: base type %s of type %s not found\n",
3805 typeDecl->base, name);
3806 return;
3807 }
3808 xmlSchemaTypeFixup(base, ctxt, NULL);
3809 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3810 /* 2.1 */
3811 typeDecl->contentType = base->contentType;
3812 } else if (base->contentType ==
3813 XML_SCHEMA_CONTENT_EMPTY) {
3814 /* 2.2 imbitable ! */
3815 typeDecl->contentType =
3816 XML_SCHEMA_CONTENT_ELEMENTS;
3817 } else {
3818 /* 2.3 imbitable pareil ! */
3819 typeDecl->contentType =
3820 XML_SCHEMA_CONTENT_ELEMENTS;
3821 }
3822 break;
3823 }
3824 case XML_SCHEMA_TYPE_COMPLEX:{
3825 if (typeDecl->subtypes == NULL) {
3826 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3827 } else {
3828 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3829 typeDecl->contentType =
3830 XML_SCHEMA_CONTENT_MIXED;
3831 else {
3832 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
3833 NULL);
3834 if (typeDecl->subtypes != NULL)
3835 typeDecl->contentType =
3836 typeDecl->subtypes->contentType;
3837 }
3838 }
3839 break;
3840 }
3841 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
3842 if (typeDecl->subtypes == NULL) {
3843 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3844 } else {
3845 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3846 typeDecl->contentType =
3847 XML_SCHEMA_CONTENT_MIXED;
3848 else {
3849 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
3850 NULL);
3851 if (typeDecl->subtypes != NULL)
3852 typeDecl->contentType =
3853 typeDecl->subtypes->contentType;
3854 }
3855 }
3856 break;
3857 }
3858 case XML_SCHEMA_TYPE_SEQUENCE:
3859 case XML_SCHEMA_TYPE_GROUP:
3860 case XML_SCHEMA_TYPE_ALL:
3861 case XML_SCHEMA_TYPE_CHOICE:
3862 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3863 break;
3864 case XML_SCHEMA_TYPE_BASIC:
3865 case XML_SCHEMA_TYPE_ANY:
3866 case XML_SCHEMA_TYPE_FACET:
3867 case XML_SCHEMA_TYPE_SIMPLE:
3868 case XML_SCHEMA_TYPE_UR:
3869 case XML_SCHEMA_TYPE_ELEMENT:
3870 case XML_SCHEMA_TYPE_ATTRIBUTE:
3871 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3872 case XML_SCHEMA_TYPE_NOTATION:
3873 case XML_SCHEMA_TYPE_LIST:
3874 case XML_SCHEMA_TYPE_UNION:
3875 case XML_SCHEMA_FACET_MININCLUSIVE:
3876 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3877 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3878 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3879 case XML_SCHEMA_FACET_TOTALDIGITS:
3880 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3881 case XML_SCHEMA_FACET_PATTERN:
3882 case XML_SCHEMA_FACET_ENUMERATION:
3883 case XML_SCHEMA_FACET_WHITESPACE:
3884 case XML_SCHEMA_FACET_LENGTH:
3885 case XML_SCHEMA_FACET_MAXLENGTH:
3886 case XML_SCHEMA_FACET_MINLENGTH:
3887 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3888 break;
3889 }
3890 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003891#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003892 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 xmlGenericError(xmlGenericErrorContext,
3894 "Type of %s : %s:%d :", name,
3895 typeDecl->node->doc->URL,
3896 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003897 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003899 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003900 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003901 case XML_SCHEMA_CONTENT_SIMPLE:
3902 xmlGenericError(xmlGenericErrorContext, "simple\n");
3903 break;
3904 case XML_SCHEMA_CONTENT_ELEMENTS:
3905 xmlGenericError(xmlGenericErrorContext, "elements\n");
3906 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003907 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003908 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
3909 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003910 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 xmlGenericError(xmlGenericErrorContext, "empty\n");
3912 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003913 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003914 xmlGenericError(xmlGenericErrorContext, "mixed\n");
3915 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003916 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
3918 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003919 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003920 xmlGenericError(xmlGenericErrorContext, "basic\n");
3921 break;
3922 default:
3923 xmlGenericError(xmlGenericErrorContext,
3924 "not registered !!!\n");
3925 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003926 }
3927#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003928}
3929
3930/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003931 * xmlSchemaCheckFacet:
3932 * @facet: the facet
3933 * @typeDecl: the schema type definition
3934 * @ctxt: the schema parser context or NULL
3935 * @name: name of the type
3936 *
3937 * Checks the default values types, especially for facets
3938 *
3939 * Returns 0 if okay or -1 in cae of error
3940 */
3941int
3942xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003943 xmlSchemaTypePtr typeDecl,
3944 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003945{
3946 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3947 int ret = 0;
3948
3949 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003950 nonNegativeIntegerType =
3951 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
3952 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003953 }
3954 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003955 case XML_SCHEMA_FACET_MININCLUSIVE:
3956 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3957 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3958 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
3959 /*
3960 * Okay we need to validate the value
3961 * at that point.
3962 */
3963 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003964
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003965 vctxt = xmlSchemaNewValidCtxt(NULL);
3966 if (vctxt == NULL)
3967 break;
3968 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3969 facet->value);
3970 facet->val = vctxt->value;
3971 vctxt->value = NULL;
3972 if (facet->val == NULL) {
3973 /* error code */
3974 if (ctxt != NULL) {
3975 xmlSchemaPErr(ctxt, facet->node,
3976 XML_SCHEMAP_INVALID_FACET,
3977 "Schemas: type %s facet value %s invalid\n",
3978 name, facet->value);
3979 }
3980 ret = -1;
3981 }
3982 xmlSchemaFreeValidCtxt(vctxt);
3983 break;
3984 }
3985 case XML_SCHEMA_FACET_ENUMERATION:{
3986 /*
3987 * Okay we need to validate the value
3988 * at that point.
3989 */
3990 xmlSchemaValidCtxtPtr vctxt;
3991 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003992
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003993 vctxt = xmlSchemaNewValidCtxt(NULL);
3994 if (vctxt == NULL)
3995 break;
3996 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3997 facet->value);
3998 if (tmp != 0) {
3999 if (ctxt != NULL) {
4000 xmlSchemaPErr(ctxt, facet->node,
4001 XML_SCHEMAP_INVALID_ENUM,
4002 "Schemas: type %s enumeration value %s invalid\n",
4003 name, facet->value);
4004 }
4005 ret = -1;
4006 }
4007 xmlSchemaFreeValidCtxt(vctxt);
4008 break;
4009 }
4010 case XML_SCHEMA_FACET_PATTERN:
4011 facet->regexp = xmlRegexpCompile(facet->value);
4012 if (facet->regexp == NULL) {
4013 xmlSchemaPErr(ctxt, typeDecl->node,
4014 XML_SCHEMAP_REGEXP_INVALID,
4015 "Schemas: type %s facet regexp %s invalid\n",
4016 name, facet->value);
4017 ret = -1;
4018 }
4019 break;
4020 case XML_SCHEMA_FACET_TOTALDIGITS:
4021 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4022 case XML_SCHEMA_FACET_LENGTH:
4023 case XML_SCHEMA_FACET_MAXLENGTH:
4024 case XML_SCHEMA_FACET_MINLENGTH:{
4025 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004026
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004027 tmp =
4028 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4029 facet->value,
4030 &facet->val);
4031 if (tmp != 0) {
4032 /* error code */
4033 if (ctxt != NULL) {
4034 xmlSchemaPErr(ctxt, facet->node,
4035 XML_SCHEMAP_INVALID_FACET_VALUE,
4036 "Schemas: type %s facet value %s invalid\n",
4037 name, facet->value);
4038 }
4039 ret = -1;
4040 }
4041 break;
4042 }
4043 case XML_SCHEMA_FACET_WHITESPACE:{
4044 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4045 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4046 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4047 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4048 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4049 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4050 } else {
4051 if (ctxt != NULL) {
4052 xmlSchemaPErr(ctxt, facet->node,
4053 XML_SCHEMAP_INVALID_WHITE_SPACE,
4054 "Schemas: type %s whiteSpace value %s invalid\n",
4055 name, facet->value);
4056 }
4057 ret = -1;
4058 }
4059 }
4060 default:
4061 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004062 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004063 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004064}
4065
4066/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 * xmlSchemaCheckDefaults:
4068 * @typeDecl: the schema type definition
4069 * @ctxt: the schema parser context
4070 *
4071 * Checks the default values types, especially for facets
4072 */
4073static void
4074xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004075 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004076{
Daniel Veillard4255d502002-04-16 15:50:10 +00004077 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004078 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004079 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004080 if (typeDecl->facets != NULL) {
4081 xmlSchemaFacetPtr facet = typeDecl->facets;
4082
4083 while (facet != NULL) {
4084 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4085 facet = facet->next;
4086 }
4087 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004088 }
4089}
4090
4091/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004092 * xmlSchemaAttrGrpFixup:
4093 * @attrgrpDecl: the schema attribute definition
4094 * @ctxt: the schema parser context
4095 * @name: the attribute name
4096 *
4097 * Fixes finish doing the computations on the attributes definitions
4098 */
4099static void
4100xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004101 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004102{
4103 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004104 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004105 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004106 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004107 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004108 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004109
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004110 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4111 attrgrpDecl->refNs);
4112 if (ref == NULL) {
4113 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4114 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4115 "Schemas: attribute group %s reference %s not found\n",
4116 name, attrgrpDecl->ref);
4117 return;
4118 }
4119 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4120 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004121 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004122 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4123 "Schemas: attribute %s has no attributes nor reference\n",
4124 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004125 }
4126}
4127
4128/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004129 * xmlSchemaAttrFixup:
4130 * @attrDecl: the schema attribute definition
4131 * @ctxt: the schema parser context
4132 * @name: the attribute name
4133 *
4134 * Fixes finish doing the computations on the attributes definitions
4135 */
4136static void
4137xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004138 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004139{
4140 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004141 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004142 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004143 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004144 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004145 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004146
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004147 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4148 attrDecl->typeNs);
4149 if (type == NULL) {
4150 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4151 "Schemas: attribute %s type %s not found\n",
4152 name, attrDecl->typeName);
4153 }
4154 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004155 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004156 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004157
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4159 attrDecl->refNs);
4160 if (ref == NULL) {
4161 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4162 "Schemas: attribute %s reference %s not found\n",
4163 name, attrDecl->ref);
4164 return;
4165 }
4166 xmlSchemaAttrFixup(ref, ctxt, NULL);
4167 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004168 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004169 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4170 "Schemas: attribute %s has no type nor reference\n",
4171 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004172 }
4173}
4174
4175/**
4176 * xmlSchemaParse:
4177 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004178 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004179 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004180 * XML Shema struture which can be used to validate instances.
4181 * *WARNING* this interface is highly subject to change
4182 *
4183 * Returns the internal XML Schema structure built from the resource or
4184 * NULL in case of error
4185 */
4186xmlSchemaPtr
4187xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4188{
4189 xmlSchemaPtr ret = NULL;
4190 xmlDocPtr doc;
4191 xmlNodePtr root, cur, delete;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004192 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004193
4194 xmlSchemaInitTypes();
4195
Daniel Veillard6045c902002-10-09 21:13:59 +00004196 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004197 return (NULL);
4198
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004199 nberrors = ctxt->nberrors;
4200 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004201 ctxt->counter = 0;
4202 ctxt->container = NULL;
4203
4204 /*
4205 * First step is to parse the input document into an DOM/Infoset
4206 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004207 if (ctxt->URL != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004208 doc = xmlParseFile((const char *) ctxt->URL);
4209 if (doc == NULL) {
4210 xmlSchemaPErr(ctxt, NULL,
4211 XML_SCHEMAP_FAILED_LOAD,
4212 "xmlSchemaParse: could not load %s\n",
4213 ctxt->URL, NULL);
4214 return (NULL);
4215 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004216 } else if (ctxt->buffer != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004217 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4218 if (doc == NULL) {
4219 xmlSchemaPErr(ctxt, NULL,
4220 XML_SCHEMAP_FAILED_PARSE,
4221 "xmlSchemaParse: could not parse\n",
4222 NULL, NULL);
4223 return (NULL);
4224 }
4225 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4226 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard6045c902002-10-09 21:13:59 +00004227 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004228 xmlSchemaPErr(ctxt, NULL,
4229 XML_SCHEMAP_NOTHING_TO_PARSE,
4230 "xmlSchemaParse: could not parse\n",
4231 NULL, NULL);
4232 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004233 }
4234
4235 /*
4236 * Then extract the root and Schema parse it
4237 */
4238 root = xmlDocGetRootElement(doc);
4239 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004240 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4241 XML_SCHEMAP_NOROOT,
4242 "schemas has no root", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004243 return (NULL);
4244 }
4245
4246 /*
4247 * Remove all the blank text nodes
4248 */
4249 delete = NULL;
4250 cur = root;
4251 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004252 if (delete != NULL) {
4253 xmlUnlinkNode(delete);
4254 xmlFreeNode(delete);
4255 delete = NULL;
4256 }
4257 if (cur->type == XML_TEXT_NODE) {
4258 if (IS_BLANK_NODE(cur)) {
4259 if (xmlNodeGetSpacePreserve(cur) != 1) {
4260 delete = cur;
4261 }
4262 }
4263 } else if ((cur->type != XML_ELEMENT_NODE) &&
4264 (cur->type != XML_CDATA_SECTION_NODE)) {
4265 delete = cur;
4266 goto skip_children;
4267 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004268
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004269 /*
4270 * Skip to next node
4271 */
4272 if (cur->children != NULL) {
4273 if ((cur->children->type != XML_ENTITY_DECL) &&
4274 (cur->children->type != XML_ENTITY_REF_NODE) &&
4275 (cur->children->type != XML_ENTITY_NODE)) {
4276 cur = cur->children;
4277 continue;
4278 }
4279 }
4280 skip_children:
4281 if (cur->next != NULL) {
4282 cur = cur->next;
4283 continue;
4284 }
4285
4286 do {
4287 cur = cur->parent;
4288 if (cur == NULL)
4289 break;
4290 if (cur == root) {
4291 cur = NULL;
4292 break;
4293 }
4294 if (cur->next != NULL) {
4295 cur = cur->next;
4296 break;
4297 }
4298 } while (cur != NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 }
4300 if (delete != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004301 xmlUnlinkNode(delete);
4302 xmlFreeNode(delete);
4303 delete = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004304 }
4305
4306 /*
4307 * Then do the parsing for good
4308 */
4309 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillardb4398962002-04-19 07:01:55 +00004310 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004311 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004312 ret->doc = doc;
4313
4314 /*
4315 * Then fix all the references.
4316 */
4317 ctxt->schema = ret;
4318 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004320
4321 /*
4322 * Then fixup all types properties
4323 */
4324 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4325
4326 /*
4327 * Then build the content model for all elements
4328 */
4329 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004330 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004331
4332 /*
4333 * Then check the defaults part of the type like facets values
4334 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4336 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004337
4338 /*
4339 * Then fixup all attributes declarations
4340 */
4341 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4342
Daniel Veillard13e04c62002-04-23 17:51:29 +00004343 /*
4344 * Then fixup all attributes group declarations
4345 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004346 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4347 ctxt);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004348
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004349 if (ctxt->nberrors != 0) {
4350 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004351 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004352 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 return (ret);
4354}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004355
Daniel Veillard4255d502002-04-16 15:50:10 +00004356/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004357 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004359 * @err: the error callback
4360 * @warn: the warning callback
4361 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004363 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 */
4365void
4366xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004367 xmlSchemaValidityErrorFunc err,
4368 xmlSchemaValidityWarningFunc warn, void *ctx)
4369{
Daniel Veillard4255d502002-04-16 15:50:10 +00004370 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004371 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 ctxt->error = err;
4373 ctxt->warning = warn;
4374 ctxt->userData = ctx;
4375}
4376
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004377/**
4378 * xmlSchemaFacetTypeToString:
4379 * @type: the facet type
4380 *
4381 * Convert the xmlSchemaTypeType to a char string.
4382 *
4383 * Returns the char string representation of the facet type if the
4384 * type is a facet and an "Internal Error" string otherwise.
4385 */
4386static const char *
4387xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4388{
4389 switch (type) {
4390 case XML_SCHEMA_FACET_PATTERN:
4391 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004392 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004393 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004395 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004397 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004399 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004400 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004401 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004403 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004405 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004406 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004407 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004409 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004410 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004411 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004412 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004413 return ("fractionDigits");
4414 default:
4415 break;
4416 }
4417 return ("Internal Error");
4418}
4419
4420/**
4421 * xmlSchemaValidateFacets:
4422 * @ctxt: a schema validation context
4423 * @base: the base type
4424 * @facets: the list of facets to check
4425 * @value: the lexical repr of the value to validate
4426 * @val: the precomputed value
4427 *
4428 * Check a value against all facet conditions
4429 *
4430 * Returns 0 if the element is schemas valid, a positive error code
4431 * number otherwise and -1 in case of internal or API error.
4432 */
4433static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004434xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4435 xmlSchemaTypePtr base,
4436 xmlSchemaFacetPtr facets, xmlChar * value)
4437{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004438 int ret = 0;
4439 int tmp = 0;
4440 xmlSchemaTypeType type;
4441 xmlSchemaFacetPtr facet = facets;
4442
4443 while (facet != NULL) {
4444 type = facet->type;
4445 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004447
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 while (facet != NULL) {
4449 tmp =
4450 xmlSchemaValidateFacet(base, facet, value,
4451 ctxt->value);
4452 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004453 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004454 }
4455 facet = facet->next;
4456 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004457 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004458 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004459
4460 if (tmp != 0) {
4461 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004462 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 +00004463 }
4464 if (facet != NULL)
4465 facet = facet->next;
4466 }
4467 return (ret);
4468}
4469
Daniel Veillard4255d502002-04-16 15:50:10 +00004470/************************************************************************
4471 * *
4472 * Simple type validation *
4473 * *
4474 ************************************************************************/
4475
4476/**
4477 * xmlSchemaValidateSimpleValue:
4478 * @ctxt: a schema validation context
4479 * @type: the type declaration
4480 * @value: the value to validate
4481 *
4482 * Validate a value against a simple type
4483 *
4484 * Returns 0 if the value is valid, a positive error code
4485 * number otherwise and -1 in case of internal or API error.
4486 */
4487static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004488xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
4489 xmlSchemaTypePtr type, xmlChar * value)
4490{
Daniel Veillard4255d502002-04-16 15:50:10 +00004491 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004492
Daniel Veillard4255d502002-04-16 15:50:10 +00004493 /*
4494 * First normalize the value accordingly to Schema Datatype
4495 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4496 */
4497 /*
4498 * Then check the normalized value against the lexical space of the
4499 * type.
4500 */
4501 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004502 if (ctxt->value != NULL) {
4503 xmlSchemaFreeValue(ctxt->value);
4504 ctxt->value = NULL;
4505 }
4506 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4507 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004508 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004509 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 +00004510 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004511 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004512 xmlSchemaTypePtr base;
4513 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004514
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004515 base = type->baseType;
4516 if (base != NULL) {
4517 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4518 } else if (type->subtypes != NULL) {
4519
4520 }
4521 /*
4522 * Do not validate facets when working on building the Schemas
4523 */
4524 if (ctxt->schema != NULL) {
4525 if (ret == 0) {
4526 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004527 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004528 }
4529 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004530 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004531 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004532
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004533 base = type->subtypes;
4534 if (base != NULL) {
4535 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4536 } else {
4537 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004538 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004539 xmlSchemaTypePtr base;
4540 xmlChar *cur, *end, tmp;
4541 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00004542
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004543 base = type->subtypes;
4544 if (base == NULL) {
4545 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
4546 "Internal: List type %s has no base type\n",
4547 type->name, NULL);
4548 return (-1);
4549 }
4550 cur = value;
4551 do {
William M. Brack76e95df2003-10-18 16:20:14 +00004552 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004553 cur++;
4554 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00004555 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004556 end++;
4557 if (end == cur)
4558 break;
4559 tmp = *end;
4560 *end = 0;
4561 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4562 if (ret2 != 0)
4563 ret = 1;
4564 *end = tmp;
4565 cur = end;
4566 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004567 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004568 TODO}
4569 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004570}
4571
4572/************************************************************************
4573 * *
4574 * DOM Validation code *
4575 * *
4576 ************************************************************************/
4577
4578static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004579 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004580static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004581 xmlNodePtr elem,
4582 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004583static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004584 xmlNodePtr elem,
4585 xmlSchemaElementPtr elemDecl,
4586 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004587
4588/**
4589 * xmlSchemaRegisterAttributes:
4590 * @ctxt: a schema validation context
4591 * @attrs: a list of attributes
4592 *
4593 * Register the list of attributes as the set to be validated on that element
4594 *
4595 * Returns -1 in case of error, 0 otherwise
4596 */
4597static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004598xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
4599{
Daniel Veillard4255d502002-04-16 15:50:10 +00004600 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004601 if ((attrs->ns != NULL) &&
4602 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4603 attrs = attrs->next;
4604 continue;
4605 }
4606 if (ctxt->attrNr >= ctxt->attrMax) {
4607 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00004608
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004609 ctxt->attrMax *= 2;
4610 tmp = (xmlSchemaAttrStatePtr)
4611 xmlRealloc(ctxt->attr, ctxt->attrMax *
4612 sizeof(xmlSchemaAttrState));
4613 if (tmp == NULL) {
4614 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
4615 ctxt->attrMax /= 2;
4616 return (-1);
4617 }
4618 ctxt->attr = tmp;
4619 }
4620 ctxt->attr[ctxt->attrNr].attr = attrs;
4621 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4622 ctxt->attrNr++;
4623 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004626}
4627
4628/**
4629 * xmlSchemaCheckAttributes:
4630 * @ctxt: a schema validation context
4631 * @node: the node carrying it.
4632 *
4633 * Check that the registered set of attributes on the current node
4634 * has been properly validated.
4635 *
4636 * Returns 0 if validity constraints are met, 1 otherwise.
4637 */
4638static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004639xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4640{
Daniel Veillard4255d502002-04-16 15:50:10 +00004641 int ret = 0;
4642 int i;
4643
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004644 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
4645 if (ctxt->attr[i].attr == NULL)
4646 break;
4647 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4648 ret = 1;
4649 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
4650 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004651 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004652 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004653}
4654
4655/**
4656 * xmlSchemaValidateSimpleContent:
4657 * @ctxt: a schema validation context
4658 * @elem: an element
4659 * @type: the type declaration
4660 *
4661 * Validate the content of an element expected to be a simple type
4662 *
4663 * Returns 0 if the element is schemas valid, a positive error code
4664 * number otherwise and -1 in case of internal or API error.
4665 */
4666static int
4667xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004668 xmlNodePtr node ATTRIBUTE_UNUSED)
4669{
Daniel Veillard4255d502002-04-16 15:50:10 +00004670 xmlNodePtr child;
4671 xmlSchemaTypePtr type, base;
4672 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004673 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004674
4675 child = ctxt->node;
4676 type = ctxt->type;
4677
4678 /*
4679 * Validation Rule: Element Locally Valid (Type): 3.1.3
4680 */
4681 value = xmlNodeGetContent(child);
4682 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4683 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004684 case XML_SCHEMA_TYPE_RESTRICTION:{
4685 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004686
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004687 base = type->baseType;
4688 if (base != NULL) {
4689 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4690 } else {
4691 TODO}
4692 if (ret == 0) {
4693 facet = type->facets;
4694 ret =
4695 xmlSchemaValidateFacets(ctxt, base, facet, value);
4696 }
4697 break;
4698 }
4699 default:
4700 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004701 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004702 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00004703
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004704 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004705}
4706
4707/**
4708 * xmlSchemaValidateCheckNodeList
4709 * @nodelist: the list of nodes
4710 *
4711 * Check the node list is only made of text nodes and entities pointing
4712 * to text nodes
4713 *
4714 * Returns 1 if true, 0 if false and -1 in case of error
4715 */
4716static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004717xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
4718{
Daniel Veillard4255d502002-04-16 15:50:10 +00004719 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004720 if (nodelist->type == XML_ENTITY_REF_NODE) {
4721 TODO /* implement recursion in the entity content */
4722 }
4723 if ((nodelist->type != XML_TEXT_NODE) &&
4724 (nodelist->type != XML_COMMENT_NODE) &&
4725 (nodelist->type != XML_PI_NODE) &&
4726 (nodelist->type != XML_PI_NODE)) {
4727 return (0);
4728 }
4729 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004730 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004731 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004732}
4733
4734/**
4735 * xmlSchemaSkipIgnored:
4736 * @ctxt: a schema validation context
4737 * @type: the current type context
4738 * @node: the top node.
4739 *
4740 * Skip ignorable nodes in that context
4741 *
4742 * Returns the new sibling
4743 * number otherwise and -1 in case of internal or API error.
4744 */
4745static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00004746xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004747 xmlSchemaTypePtr type, xmlNodePtr node)
4748{
Daniel Veillard4255d502002-04-16 15:50:10 +00004749 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004750
Daniel Veillard4255d502002-04-16 15:50:10 +00004751 /*
4752 * TODO complete and handle entities
4753 */
4754 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004755 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00004756 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004757 ((node->type == XML_COMMENT_NODE) ||
4758 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4759 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4760 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
4761 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004762 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004763 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004764}
4765
4766/**
4767 * xmlSchemaValidateCallback:
4768 * @ctxt: a schema validation context
4769 * @name: the name of the element detected (might be NULL)
4770 * @type: the type
4771 *
4772 * A transition has been made in the automata associated to an element
4773 * content model
4774 */
4775static void
4776xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004777 const xmlChar * name ATTRIBUTE_UNUSED,
4778 xmlSchemaTypePtr type, xmlNodePtr node)
4779{
Daniel Veillard4255d502002-04-16 15:50:10 +00004780 xmlSchemaTypePtr oldtype = ctxt->type;
4781 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782
Daniel Veillard4255d502002-04-16 15:50:10 +00004783#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004784 xmlGenericError(xmlGenericErrorContext,
4785 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004786 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004787#endif
4788 ctxt->type = type;
4789 ctxt->node = node;
4790 xmlSchemaValidateContent(ctxt, node);
4791 ctxt->type = oldtype;
4792 ctxt->node = oldnode;
4793}
4794
4795
4796#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004797
Daniel Veillard4255d502002-04-16 15:50:10 +00004798/**
4799 * xmlSchemaValidateSimpleRestrictionType:
4800 * @ctxt: a schema validation context
4801 * @node: the top node.
4802 *
4803 * Validate the content of a restriction type.
4804 *
4805 * Returns 0 if the element is schemas valid, a positive error code
4806 * number otherwise and -1 in case of internal or API error.
4807 */
4808static int
4809xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4810 xmlNodePtr node)
4811{
4812 xmlNodePtr child;
4813 xmlSchemaTypePtr type;
4814 int ret;
4815
4816 child = ctxt->node;
4817 type = ctxt->type;
4818
4819 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 return (-1);
4822 }
4823 /*
4824 * Only text and text based entities references shall be found there
4825 */
4826 ret = xmlSchemaValidateCheckNodeList(child);
4827 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004829 return (-1);
4830 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 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 +00004832 return (-1);
4833 }
4834 ctxt->type = type->subtypes;
4835 xmlSchemaValidateContent(ctxt, node);
4836 ctxt->type = type;
4837 return (ret);
4838}
4839#endif
4840
4841/**
4842 * xmlSchemaValidateSimpleType:
4843 * @ctxt: a schema validation context
4844 * @node: the top node.
4845 *
4846 * Validate the content of an simple type.
4847 *
4848 * Returns 0 if the element is schemas valid, a positive error code
4849 * number otherwise and -1 in case of internal or API error.
4850 */
4851static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004852xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4853{
Daniel Veillard4255d502002-04-16 15:50:10 +00004854 xmlNodePtr child;
4855 xmlSchemaTypePtr type;
4856 xmlAttrPtr attr;
4857 int ret;
4858
4859 child = ctxt->node;
4860 type = ctxt->type;
4861
4862 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004863 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
4864 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004865 }
4866 /*
4867 * Only text and text based entities references shall be found there
4868 */
4869 ret = xmlSchemaValidateCheckNodeList(child);
4870 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004871 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
4872 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004873 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004874 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
4875 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004876 }
4877 /*
4878 * Validation Rule: Element Locally Valid (Type): 3.1.1
4879 */
4880 attr = node->properties;
4881 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004882 if ((attr->ns == NULL) ||
4883 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4884 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
4885 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
4886 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
4887 (!xmlStrEqual
4888 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
4889 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
4890 return (ctxt->err);
4891 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004892 }
4893
4894 ctxt->type = type->subtypes;
4895 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4896 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004897 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004898}
4899
4900/**
4901 * xmlSchemaValidateElementType:
4902 * @ctxt: a schema validation context
4903 * @node: the top node.
4904 *
4905 * Validate the content of an element type.
4906 * Validation Rule: Element Locally Valid (Complex Type)
4907 *
4908 * Returns 0 if the element is schemas valid, a positive error code
4909 * number otherwise and -1 in case of internal or API error.
4910 */
4911static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004912xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4913{
Daniel Veillard4255d502002-04-16 15:50:10 +00004914 xmlNodePtr child;
4915 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004916 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00004917 xmlSchemaElementPtr decl;
4918 int ret, attrBase;
4919
4920 oldregexp = ctxt->regexp;
4921
4922 child = ctxt->node;
4923 type = ctxt->type;
4924
4925 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004926 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
4927 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004928 }
4929 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930 if (type->minOccurs > 0) {
4931 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
4932 }
4933 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004934 }
4935
4936 /*
4937 * Verify the element matches
4938 */
4939 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004940 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
4941 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004942 }
4943 /*
4944 * Verify the attributes
4945 */
4946 attrBase = ctxt->attrBase;
4947 ctxt->attrBase = ctxt->attrNr;
4948 xmlSchemaRegisterAttributes(ctxt, child->properties);
4949 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4950 /*
4951 * Verify the element content recursively
4952 */
4953 decl = (xmlSchemaElementPtr) type;
4954 oldregexp = ctxt->regexp;
4955 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004956 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4957 (xmlRegExecCallbacks)
4958 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004959#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004960 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004961#endif
4962 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004963 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
4964 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004965
4966 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004967 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004968#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004969 xmlGenericError(xmlGenericErrorContext,
4970 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004971#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004972 if (ret == 0) {
4973 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
4974 } else if (ret < 0) {
4975 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004976#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004977 } else {
4978 xmlGenericError(xmlGenericErrorContext,
4979 "Element %s content check succeeded\n",
4980 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004981
4982#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004983 }
4984 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00004985 }
4986 /*
4987 * Verify that all attributes were Schemas-validated
4988 */
4989 xmlSchemaCheckAttributes(ctxt, node);
4990 ctxt->attrNr = ctxt->attrBase;
4991 ctxt->attrBase = attrBase;
4992
4993 ctxt->regexp = oldregexp;
4994
4995 ctxt->node = child;
4996 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004998}
4999
5000/**
5001 * xmlSchemaValidateBasicType:
5002 * @ctxt: a schema validation context
5003 * @node: the top node.
5004 *
5005 * Validate the content of an element expected to be a basic type type
5006 *
5007 * Returns 0 if the element is schemas valid, a positive error code
5008 * number otherwise and -1 in case of internal or API error.
5009 */
5010static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005011xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5012{
Daniel Veillard4255d502002-04-16 15:50:10 +00005013 int ret;
5014 xmlNodePtr child, cur;
5015 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005016 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005017
5018 child = ctxt->node;
5019 type = ctxt->type;
5020
5021 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005022 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5023 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005024 }
5025 /*
5026 * First check the content model of the node.
5027 */
5028 cur = child;
5029 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005030 switch (cur->type) {
5031 case XML_TEXT_NODE:
5032 case XML_CDATA_SECTION_NODE:
5033 case XML_PI_NODE:
5034 case XML_COMMENT_NODE:
5035 case XML_XINCLUDE_START:
5036 case XML_XINCLUDE_END:
5037 break;
5038 case XML_ENTITY_REF_NODE:
5039 case XML_ENTITY_NODE:
5040 TODO break;
5041 case XML_ELEMENT_NODE:
5042 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5043 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005044 case XML_ATTRIBUTE_NODE:
5045 case XML_DOCUMENT_NODE:
5046 case XML_DOCUMENT_TYPE_NODE:
5047 case XML_DOCUMENT_FRAG_NODE:
5048 case XML_NOTATION_NODE:
5049 case XML_HTML_DOCUMENT_NODE:
5050 case XML_DTD_NODE:
5051 case XML_ELEMENT_DECL:
5052 case XML_ATTRIBUTE_DECL:
5053 case XML_ENTITY_DECL:
5054 case XML_NAMESPACE_DECL:
5055#ifdef LIBXML_DOCB_ENABLED
5056 case XML_DOCB_DOCUMENT_NODE:
5057#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005058 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5059 return (ctxt->err);
5060 }
5061 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005062 }
5063 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005064 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005065 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005066 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005067
5068 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005069 xmlSchemaFreeValue(ctxt->value);
5070 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005071 }
5072 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5073 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005074 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005075 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005076 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 +00005077 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005078 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005079}
5080
5081/**
5082 * xmlSchemaValidateComplexType:
5083 * @ctxt: a schema validation context
5084 * @node: the top node.
5085 *
5086 * Validate the content of an element expected to be a complex type type
5087 * xmlschema-1.html#cvc-complex-type
5088 * Validation Rule: Element Locally Valid (Complex Type)
5089 *
5090 * Returns 0 if the element is schemas valid, a positive error code
5091 * number otherwise and -1 in case of internal or API error.
5092 */
5093static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005094xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5095{
Daniel Veillard4255d502002-04-16 15:50:10 +00005096 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005097 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005098 int ret;
5099
5100 child = ctxt->node;
5101 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005102 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005103
Daniel Veillard4255d502002-04-16 15:50:10 +00005104 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 case XML_SCHEMA_CONTENT_EMPTY:
5106 if (child != NULL) {
5107 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5108 }
5109 if (type->attributes != NULL) {
5110 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5111 }
5112 subtype = type->subtypes;
5113 while (subtype != NULL) {
5114 ctxt->type = subtype;
5115 xmlSchemaValidateComplexType(ctxt, node);
5116 subtype = subtype->next;
5117 }
5118 break;
5119 case XML_SCHEMA_CONTENT_ELEMENTS:
5120 case XML_SCHEMA_CONTENT_MIXED:
5121 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5122 /*
5123 * Skip ignorable nodes in that context
5124 */
5125 child = xmlSchemaSkipIgnored(ctxt, type, child);
5126 while (child != NULL) {
5127 if (child->type == XML_ELEMENT_NODE) {
5128 ret = xmlRegExecPushString(ctxt->regexp,
5129 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005130#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 if (ret < 0)
5132 xmlGenericError(xmlGenericErrorContext,
5133 " --> %s Error\n", child->name);
5134 else
5135 xmlGenericError(xmlGenericErrorContext,
5136 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005137#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005138 }
5139 child = child->next;
5140 /*
5141 * Skip ignorable nodes in that context
5142 */
5143 child = xmlSchemaSkipIgnored(ctxt, type, child);
5144 }
5145 break;
5146 case XML_SCHEMA_CONTENT_BASIC:{
5147 if (type->subtypes != NULL) {
5148 ctxt->type = type->subtypes;
5149 xmlSchemaValidateComplexType(ctxt, node);
5150 }
5151 if (type->baseType != NULL) {
5152 ctxt->type = type->baseType;
5153 xmlSchemaValidateBasicType(ctxt, node);
5154 }
5155 if (type->attributes != NULL) {
5156 xmlSchemaValidateAttributes(ctxt, node,
5157 type->attributes);
5158 }
5159 ctxt->type = type;
5160 break;
5161 }
5162 default:
5163 TODO xmlGenericError(xmlGenericErrorContext,
5164 "unimplemented content type %d\n",
5165 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005166 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005168}
5169
5170/**
5171 * xmlSchemaValidateContent:
5172 * @ctxt: a schema validation context
5173 * @elem: an element
5174 * @type: the type declaration
5175 *
5176 * Validate the content of an element against the type.
5177 *
5178 * Returns 0 if the element is schemas valid, a positive error code
5179 * number otherwise and -1 in case of internal or API error.
5180 */
5181static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005182xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5183{
Daniel Veillard4255d502002-04-16 15:50:10 +00005184 xmlNodePtr child;
5185 xmlSchemaTypePtr type;
5186
5187 child = ctxt->node;
5188 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005189 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005190
Daniel Veillarde19fc232002-04-22 16:01:24 +00005191 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005192 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005193
Daniel Veillard4255d502002-04-16 15:50:10 +00005194 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005195 case XML_SCHEMA_TYPE_ANY:
5196 /* Any type will do it, fine */
5197 TODO /* handle recursivity */
5198 break;
5199 case XML_SCHEMA_TYPE_COMPLEX:
5200 xmlSchemaValidateComplexType(ctxt, node);
5201 break;
5202 case XML_SCHEMA_TYPE_ELEMENT:{
5203 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5204
5205 /*
5206 * Handle element reference here
5207 */
5208 if (decl->ref != NULL) {
5209 if (decl->refDecl == NULL) {
5210 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5211 return (-1);
5212 }
5213 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5214 decl = decl->refDecl;
5215 }
5216 xmlSchemaValidateElementType(ctxt, node);
5217 ctxt->type = type;
5218 break;
5219 }
5220 case XML_SCHEMA_TYPE_BASIC:
5221 xmlSchemaValidateBasicType(ctxt, node);
5222 break;
5223 case XML_SCHEMA_TYPE_FACET:
5224 TODO break;
5225 case XML_SCHEMA_TYPE_SIMPLE:
5226 xmlSchemaValidateSimpleType(ctxt, node);
5227 break;
5228 case XML_SCHEMA_TYPE_SEQUENCE:
5229 TODO break;
5230 case XML_SCHEMA_TYPE_CHOICE:
5231 TODO break;
5232 case XML_SCHEMA_TYPE_ALL:
5233 TODO break;
5234 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5235 TODO break;
5236 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5237 TODO break;
5238 case XML_SCHEMA_TYPE_UR:
5239 TODO break;
5240 case XML_SCHEMA_TYPE_RESTRICTION:
5241 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5242 TODO break;
5243 case XML_SCHEMA_TYPE_EXTENSION:
5244 TODO break;
5245 case XML_SCHEMA_TYPE_ATTRIBUTE:
5246 TODO break;
5247 case XML_SCHEMA_TYPE_GROUP:
5248 TODO break;
5249 case XML_SCHEMA_TYPE_NOTATION:
5250 TODO break;
5251 case XML_SCHEMA_TYPE_LIST:
5252 TODO break;
5253 case XML_SCHEMA_TYPE_UNION:
5254 TODO break;
5255 case XML_SCHEMA_FACET_MININCLUSIVE:
5256 TODO break;
5257 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5258 TODO break;
5259 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5260 TODO break;
5261 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5262 TODO break;
5263 case XML_SCHEMA_FACET_TOTALDIGITS:
5264 TODO break;
5265 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5266 TODO break;
5267 case XML_SCHEMA_FACET_PATTERN:
5268 TODO break;
5269 case XML_SCHEMA_FACET_ENUMERATION:
5270 TODO break;
5271 case XML_SCHEMA_FACET_WHITESPACE:
5272 TODO break;
5273 case XML_SCHEMA_FACET_LENGTH:
5274 TODO break;
5275 case XML_SCHEMA_FACET_MAXLENGTH:
5276 TODO break;
5277 case XML_SCHEMA_FACET_MINLENGTH:
5278 TODO break;
5279 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5280 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005281 }
5282 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5283
5284 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005285 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 ctxt->node = ctxt->node->next;
5287 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005288 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005289}
5290
5291/**
5292 * xmlSchemaValidateType:
5293 * @ctxt: a schema validation context
5294 * @elem: an element
5295 * @type: the list of type declarations
5296 *
5297 * Validate the content of an element against the types.
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
5303xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005304 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5305{
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 xmlChar *nil;
5307
Daniel Veillard2db8c122003-07-08 12:16:59 +00005308 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005309 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005310
Daniel Veillard4255d502002-04-16 15:50:10 +00005311 /*
5312 * 3.3.4 : 2
5313 */
5314 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005315 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5316 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 }
5318 /*
5319 * 3.3.4: 3
5320 */
5321 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5322 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005323 /* 3.3.4: 3.2 */
5324 if (xmlStrEqual(nil, BAD_CAST "true")) {
5325 if (elem->children != NULL) {
5326 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5327 return (ctxt->err);
5328 }
5329 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5330 (elemDecl->value != NULL)) {
5331 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5332 return (ctxt->err);
5333 }
5334 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005335 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005336 /* 3.3.4: 3.1 */
5337 if (nil != NULL) {
5338 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5339 xmlFree(nil);
5340 return (ctxt->err);
5341 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005342 }
5343
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00005345
5346 ctxt->type = elemDecl->subtypes;
5347 ctxt->node = elem->children;
5348 xmlSchemaValidateContent(ctxt, elem);
5349 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350
5351 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005352}
5353
5354
5355/**
5356 * xmlSchemaValidateAttributes:
5357 * @ctxt: a schema validation context
5358 * @elem: an element
5359 * @attributes: the list of attribute declarations
5360 *
5361 * Validate the attributes of an element.
5362 *
5363 * Returns 0 if the element is schemas valid, a positive error code
5364 * number otherwise and -1 in case of internal or API error.
5365 */
5366static int
5367xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005368 xmlSchemaAttributePtr attributes)
5369{
Daniel Veillard4255d502002-04-16 15:50:10 +00005370 int i, ret;
5371 xmlAttrPtr attr;
5372 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005373 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005374
5375 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005377 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005378 /*
5379 * Handle attribute groups
5380 */
5381 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5382 group = (xmlSchemaAttributeGroupPtr) attributes;
5383 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5384 attributes = group->next;
5385 continue;
5386 }
5387 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5388 attr = ctxt->attr[i].attr;
5389 if (attr == NULL)
5390 continue;
5391 if (attributes->ref != NULL) {
5392 if (!xmlStrEqual(attr->name, attributes->ref))
5393 continue;
5394 if (attr->ns != NULL) {
5395 if ((attributes->refNs == NULL) ||
5396 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5397 continue;
5398 } else if (attributes->refNs != NULL) {
5399 continue;
5400 }
5401 } else {
5402 if (!xmlStrEqual(attr->name, attributes->name))
5403 continue;
5404 /*
5405 * TODO: handle the mess about namespaces here.
5406 */
5407 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */ ) {
5408 TODO}
5409 }
5410 ctxt->cur = (xmlNodePtr) attributes;
5411 if (attributes->subtypes == NULL) {
5412 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
5413 continue;
5414 }
5415 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5416 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5417 value);
5418 if (ret != 0) {
5419 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
5420 } else {
5421 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5422 }
5423 if (value != NULL) {
5424 xmlFree(value);
5425 }
5426 }
5427 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005428 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005429 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005430}
5431
5432/**
5433 * xmlSchemaValidateElement:
5434 * @ctxt: a schema validation context
5435 * @elem: an element
5436 *
5437 * Validate an element in a tree
5438 *
5439 * Returns 0 if the element is schemas valid, a positive error code
5440 * number otherwise and -1 in case of internal or API error.
5441 */
5442static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005443xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
5444{
Daniel Veillard4255d502002-04-16 15:50:10 +00005445 xmlSchemaElementPtr elemDecl;
5446 int ret, attrBase;
5447
5448 if (elem->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005449 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5450 elem->name, elem->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005451 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005452 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5453 elem->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005454 /*
5455 * 3.3.4 : 1
5456 */
5457 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005458 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
5459 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005460 }
5461 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005462 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
5463 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005464 }
5465 /*
5466 * Verify the attributes
5467 */
5468 attrBase = ctxt->attrBase;
5469 ctxt->attrBase = ctxt->attrNr;
5470 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5471 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5472 /*
5473 * Verify the element content recursively
5474 */
5475 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005476 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5477 (xmlRegExecCallbacks)
5478 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005479#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005480 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005481#endif
5482 }
5483 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005484 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005485 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005486#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005487 xmlGenericError(xmlGenericErrorContext,
5488 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005489#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005490 if (ret == 0) {
5491 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
5492 } else if (ret < 0) {
5493 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005494#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005495 } else {
5496 xmlGenericError(xmlGenericErrorContext,
5497 "Element %s content check succeeded\n",
5498 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005499
5500#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005501 }
5502 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005503 }
5504 /*
5505 * Verify that all attributes were Schemas-validated
5506 */
5507 xmlSchemaCheckAttributes(ctxt, elem);
5508 ctxt->attrNr = ctxt->attrBase;
5509 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005510
5511 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005512}
5513
5514/**
5515 * xmlSchemaValidateDocument:
5516 * @ctxt: a schema validation context
5517 * @doc: a parsed document tree
5518 *
5519 * Validate a document tree in memory.
5520 *
5521 * Returns 0 if the document is schemas valid, a positive error code
5522 * number otherwise and -1 in case of internal or API error.
5523 */
5524static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005525xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5526{
Daniel Veillard4255d502002-04-16 15:50:10 +00005527 xmlNodePtr root;
5528 xmlSchemaElementPtr elemDecl;
5529
5530 root = xmlDocGetRootElement(doc);
5531 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005532 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
5533 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005534 }
5535 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005536 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5537 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005538 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005539 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5540 root->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005541 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005542 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005543 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005544 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005545 }
5546 /*
5547 * Okay, start the recursive validation
5548 */
5549 xmlSchemaValidateElement(ctxt, root);
5550
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005551 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005552}
5553
5554/************************************************************************
5555 * *
5556 * SAX Validation code *
5557 * *
5558 ************************************************************************/
5559
5560/************************************************************************
5561 * *
5562 * Validation interfaces *
5563 * *
5564 ************************************************************************/
5565
5566/**
5567 * xmlSchemaNewValidCtxt:
5568 * @schema: a precompiled XML Schemas
5569 *
5570 * Create an XML Schemas validation context based on the given schema
5571 *
5572 * Returns the validation context or NULL in case of error
5573 */
5574xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005575xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
5576{
Daniel Veillard4255d502002-04-16 15:50:10 +00005577 xmlSchemaValidCtxtPtr ret;
5578
5579 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5580 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005581 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005582 return (NULL);
5583 }
5584 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5585 ret->schema = schema;
5586 ret->attrNr = 0;
5587 ret->attrMax = 10;
5588 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005589 sizeof
5590 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00005591 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005592 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
5593 free(ret);
5594 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005595 }
5596 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5597 return (ret);
5598}
5599
5600/**
5601 * xmlSchemaFreeValidCtxt:
5602 * @ctxt: the schema validation context
5603 *
5604 * Free the resources associated to the schema validation context
5605 */
5606void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005607xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
5608{
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005610 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005611 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005612 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005613 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005614 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005615 xmlFree(ctxt);
5616}
5617
5618/**
5619 * xmlSchemaSetValidErrors:
5620 * @ctxt: a schema validation context
5621 * @err: the error function
5622 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00005623 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 *
5625 * Set the error and warning callback informations
5626 */
5627void
5628xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005629 xmlSchemaValidityErrorFunc err,
5630 xmlSchemaValidityWarningFunc warn, void *ctx)
5631{
Daniel Veillard4255d502002-04-16 15:50:10 +00005632 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005634 ctxt->error = err;
5635 ctxt->warning = warn;
5636 ctxt->userData = ctx;
5637}
5638
5639/**
5640 * xmlSchemaValidateDoc:
5641 * @ctxt: a schema validation context
5642 * @doc: a parsed document tree
5643 *
5644 * Validate a document tree in memory.
5645 *
5646 * Returns 0 if the document is schemas valid, a positive error code
5647 * number otherwise and -1 in case of internal or API error.
5648 */
5649int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005650xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5651{
Daniel Veillard4255d502002-04-16 15:50:10 +00005652 int ret;
5653
5654 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005655 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005656
5657 ctxt->doc = doc;
5658 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005659 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005660}
5661
5662/**
5663 * xmlSchemaValidateStream:
5664 * @ctxt: a schema validation context
5665 * @input: the input to use for reading the data
5666 * @enc: an optional encoding information
5667 * @sax: a SAX handler for the resulting events
5668 * @user_data: the context to provide to the SAX handler.
5669 *
5670 * Validate a document tree in memory.
5671 *
5672 * Returns 0 if the document is schemas valid, a positive error code
5673 * number otherwise and -1 in case of internal or API error.
5674 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005675int
Daniel Veillard4255d502002-04-16 15:50:10 +00005676xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005677 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5678 xmlSAXHandlerPtr sax, void *user_data)
5679{
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005681 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005682 ctxt->input = input;
5683 ctxt->enc = enc;
5684 ctxt->sax = sax;
5685 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005686 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005687}
5688
5689#endif /* LIBXML_SCHEMAS_ENABLED */