blob: 58a460ebe6182cf37fc8fb8467f63d2034487d85 [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>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000027#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000028
Daniel Veillarda84c0b32003-06-02 16:58:46 +000029/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000030
Daniel Veillard82bbbd42003-05-11 20:16:09 +000031/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000032
Daniel Veillard82bbbd42003-05-11 20:16:09 +000033/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000034
Daniel Veillard118aed72002-09-24 14:13:13 +000035/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000036
Daniel Veillard4255d502002-04-16 15:50:10 +000037/* #define DEBUG_AUTOMATA 1 */
38
39#define UNBOUNDED (1 << 30)
40#define TODO \
41 xmlGenericError(xmlGenericErrorContext, \
42 "Unimplemented block at %s:%d\n", \
43 __FILE__, __LINE__);
44
Daniel Veillard5a872412002-05-22 06:40:27 +000045#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
46
Daniel Veillard4255d502002-04-16 15:50:10 +000047/*
48 * The XML Schemas namespaces
49 */
50static const xmlChar *xmlSchemaNs = (const xmlChar *)
51 "http://www.w3.org/2001/XMLSchema";
52
53static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
54 "http://www.w3.org/2001/XMLSchema-instance";
55
56#define IS_SCHEMA(node, type) \
57 ((node != NULL) && (node->ns != NULL) && \
58 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
59 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
60
61#define XML_SCHEMAS_PARSE_ERROR 1
62
63struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000064 void *userData; /* user specific data block */
65 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
66 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000067 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000068 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000069 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000070
Daniel Veillardbe9c6322003-11-22 20:37:51 +000071 xmlSchemaPtr topschema; /* The main schema */
72 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
73
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000075 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000076 int counter;
77
Daniel Veillardbe9c6322003-11-22 20:37:51 +000078 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000079 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +000080
Daniel Veillardd0c9c322003-10-10 00:49:42 +000081 const char *buffer;
82 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000083
Daniel Veillard4255d502002-04-16 15:50:10 +000084 /*
85 * Used to build complex element content models
86 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000087 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000088 xmlAutomataStatePtr start;
89 xmlAutomataStatePtr end;
90 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000091
92 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillard4255d502002-04-16 15:50:10 +000093};
94
95
96#define XML_SCHEMAS_ATTR_UNKNOWN 1
97#define XML_SCHEMAS_ATTR_CHECKED 2
98
99typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
100typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
101struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000102 xmlAttrPtr attr;
103 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +0000104};
105
106/**
107 * xmlSchemaValidCtxt:
108 *
109 * A Schemas validation context
110 */
111
112struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000113 void *userData; /* user specific data block */
114 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
115 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000116 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000117
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000118 xmlSchemaPtr schema; /* The schema in use */
119 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000120 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000121 xmlCharEncoding enc;
122 xmlSAXHandlerPtr sax;
123 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000124
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000125 xmlDocPtr myDoc;
126 int err;
127 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000128
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000129 xmlNodePtr node;
130 xmlNodePtr cur;
131 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000132
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000133 xmlRegExecCtxtPtr regexp;
134 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000135
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000136 int attrNr;
137 int attrBase;
138 int attrMax;
139 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000140};
141
Daniel Veillard1d913862003-11-21 00:28:39 +0000142/*
143 * These are the entries in the schemas importSchemas hash table
144 */
145typedef struct _xmlSchemaImport xmlSchemaImport;
146typedef xmlSchemaImport *xmlSchemaImportPtr;
147struct _xmlSchemaImport {
148 const xmlChar *schemaLocation;
149 xmlSchemaPtr schema;
150};
Daniel Veillard4255d502002-04-16 15:50:10 +0000151
152/************************************************************************
153 * *
154 * Some predeclarations *
155 * *
156 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000157static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
158 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000159 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000160
161/************************************************************************
162 * *
163 * Datatype error handlers *
164 * *
165 ************************************************************************/
166
167/**
168 * xmlSchemaPErrMemory:
169 * @node: a context node
170 * @extra: extra informations
171 *
172 * Handle an out of memory condition
173 */
174static void
175xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
176 const char *extra, xmlNodePtr node)
177{
178 if (ctxt != NULL)
179 ctxt->nberrors++;
180 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
181 extra);
182}
183
184/**
185 * xmlSchemaPErr:
186 * @ctxt: the parsing context
187 * @node: the context node
188 * @error: the error code
189 * @msg: the error message
190 * @str1: extra data
191 * @str2: extra data
192 *
193 * Handle a parser error
194 */
195static void
196xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
197 const char *msg, const xmlChar * str1, const xmlChar * str2)
198{
199 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000200 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000201 void *data = NULL;
202
203 if (ctxt != NULL) {
204 ctxt->nberrors++;
205 channel = ctxt->error;
206 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000207 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000208 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000209 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000210 error, XML_ERR_ERROR, NULL, 0,
211 (const char *) str1, (const char *) str2, NULL, 0, 0,
212 msg, str1, str2);
213}
214
215/**
216 * xmlSchemaPErr2:
217 * @ctxt: the parsing context
218 * @node: the context node
219 * @node: the current child
220 * @error: the error code
221 * @msg: the error message
222 * @str1: extra data
223 * @str2: extra data
224 *
225 * Handle a parser error
226 */
227static void
228xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
229 xmlNodePtr child, int error,
230 const char *msg, const xmlChar * str1, const xmlChar * str2)
231{
232 if (child != NULL)
233 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
234 else
235 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
236}
237
238/**
239 * xmlSchemaVTypeErrMemory:
240 * @node: a context node
241 * @extra: extra informations
242 *
243 * Handle an out of memory condition
244 */
245static void
246xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
247 const char *extra, xmlNodePtr node)
248{
249 if (ctxt != NULL) {
250 ctxt->nberrors++;
251 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
252 }
253 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
254 extra);
255}
256
257/**
258 * xmlSchemaVErr3:
259 * @ctxt: the validation context
260 * @node: the context node
261 * @error: the error code
262 * @msg: the error message
263 * @str1: extra data
264 * @str2: extra data
265 * @str3: extra data
266 *
267 * Handle a validation error
268 */
269static void
270xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
271 const char *msg, const xmlChar *str1, const xmlChar *str2,
272 const xmlChar *str3)
273{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000274 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000275 xmlGenericErrorFunc channel = NULL;
276 void *data = NULL;
277
278 if (ctxt != NULL) {
279 ctxt->nberrors++;
280 ctxt->err = error;
281 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000282 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000283 data = ctxt->userData;
284 }
285 /* reajust to global error numbers */
286 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000287 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000288 error, XML_ERR_ERROR, NULL, 0,
289 (const char *) str1, (const char *) str2,
290 (const char *) str3, 0, 0,
291 msg, str1, str2, str3);
292}
293/**
294 * xmlSchemaVErr:
295 * @ctxt: the validation context
296 * @node: the context node
297 * @error: the error code
298 * @msg: the error message
299 * @str1: extra data
300 * @str2: extra data
301 *
302 * Handle a validation error
303 */
304static void
305xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
306 const char *msg, const xmlChar * str1, const xmlChar * str2)
307{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000308 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000309 xmlGenericErrorFunc channel = NULL;
310 void *data = NULL;
311
312 if (ctxt != NULL) {
313 ctxt->nberrors++;
314 ctxt->err = error;
315 channel = ctxt->error;
316 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000317 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318 }
319 /* reajust to global error numbers */
320 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000321 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000322 error, XML_ERR_ERROR, NULL, 0,
323 (const char *) str1, (const char *) str2, NULL, 0, 0,
324 msg, str1, str2);
325}
Daniel Veillard4255d502002-04-16 15:50:10 +0000326
327/************************************************************************
328 * *
329 * Allocation functions *
330 * *
331 ************************************************************************/
332
333/**
334 * xmlSchemaNewSchema:
335 * @ctxt: a schema validation context (optional)
336 *
337 * Allocate a new Schema structure.
338 *
339 * Returns the newly allocated structure or NULL in case or error
340 */
341static xmlSchemaPtr
342xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
343{
344 xmlSchemaPtr ret;
345
346 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
347 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000348 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000349 return (NULL);
350 }
351 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000352 xmlDictReference(ctxt->dict);
353 ret->dict = ctxt->dict;
Daniel Veillard4255d502002-04-16 15:50:10 +0000354
355 return (ret);
356}
357
358/**
359 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000360 *
361 * Allocate a new Facet structure.
362 *
363 * Returns the newly allocated structure or NULL in case or error
364 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000365xmlSchemaFacetPtr
366xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000367{
368 xmlSchemaFacetPtr ret;
369
370 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
371 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000372 return (NULL);
373 }
374 memset(ret, 0, sizeof(xmlSchemaFacet));
375
376 return (ret);
377}
378
379/**
380 * xmlSchemaNewAnnot:
381 * @ctxt: a schema validation context (optional)
382 * @node: a node
383 *
384 * Allocate a new annotation structure.
385 *
386 * Returns the newly allocated structure or NULL in case or error
387 */
388static xmlSchemaAnnotPtr
389xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
390{
391 xmlSchemaAnnotPtr ret;
392
393 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
394 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000395 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000396 return (NULL);
397 }
398 memset(ret, 0, sizeof(xmlSchemaAnnot));
399 ret->content = node;
400 return (ret);
401}
402
403/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000404 * xmlSchemaFreeAnnot:
405 * @annot: a schema type structure
406 *
407 * Deallocate a annotation structure
408 */
409static void
410xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
411{
412 if (annot == NULL)
413 return;
414 xmlFree(annot);
415}
416
417/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000418 * xmlSchemaFreeImport:
419 * @import: a schema import structure
420 *
421 * Deallocate an import structure
422 */
423static void
424xmlSchemaFreeImport(xmlSchemaImportPtr import)
425{
426 if (import == NULL)
427 return;
428
429 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000430 xmlFree(import);
431}
432
433/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000434 * xmlSchemaFreeNotation:
435 * @schema: a schema notation structure
436 *
437 * Deallocate a Schema Notation structure.
438 */
439static void
440xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
441{
442 if (nota == NULL)
443 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000444 xmlFree(nota);
445}
446
447/**
448 * xmlSchemaFreeAttribute:
449 * @schema: a schema attribute structure
450 *
451 * Deallocate a Schema Attribute structure.
452 */
453static void
454xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
455{
456 if (attr == NULL)
457 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000458 xmlFree(attr);
459}
460
461/**
462 * xmlSchemaFreeAttributeGroup:
463 * @schema: a schema attribute group structure
464 *
465 * Deallocate a Schema Attribute Group structure.
466 */
467static void
468xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
469{
470 if (attr == NULL)
471 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000472 xmlFree(attr);
473}
474
475/**
476 * xmlSchemaFreeElement:
477 * @schema: a schema element structure
478 *
479 * Deallocate a Schema Element structure.
480 */
481static void
482xmlSchemaFreeElement(xmlSchemaElementPtr elem)
483{
484 if (elem == NULL)
485 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000486 if (elem->annot != NULL)
487 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000488 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000489 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000490 xmlFree(elem);
491}
492
493/**
494 * xmlSchemaFreeFacet:
495 * @facet: a schema facet structure
496 *
497 * Deallocate a Schema Facet structure.
498 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000499void
Daniel Veillard4255d502002-04-16 15:50:10 +0000500xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
501{
502 if (facet == NULL)
503 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000504 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000505 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000506 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000507 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000508 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000509 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000510 xmlFree(facet);
511}
512
513/**
514 * xmlSchemaFreeType:
515 * @type: a schema type structure
516 *
517 * Deallocate a Schema Type structure.
518 */
519void
520xmlSchemaFreeType(xmlSchemaTypePtr type)
521{
522 if (type == NULL)
523 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000524 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000525 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000526 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000527 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000528
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000529 facet = type->facets;
530 while (facet != NULL) {
531 next = facet->next;
532 xmlSchemaFreeFacet(facet);
533 facet = next;
534 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000535 }
536 xmlFree(type);
537}
538
539/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000540 * xmlSchemaFree:
541 * @schema: a schema structure
542 *
543 * Deallocate a Schema structure.
544 */
545void
546xmlSchemaFree(xmlSchemaPtr schema)
547{
548 if (schema == NULL)
549 return;
550
Daniel Veillard4255d502002-04-16 15:50:10 +0000551 if (schema->notaDecl != NULL)
552 xmlHashFree(schema->notaDecl,
553 (xmlHashDeallocator) xmlSchemaFreeNotation);
554 if (schema->attrDecl != NULL)
555 xmlHashFree(schema->attrDecl,
556 (xmlHashDeallocator) xmlSchemaFreeAttribute);
557 if (schema->attrgrpDecl != NULL)
558 xmlHashFree(schema->attrgrpDecl,
559 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
560 if (schema->elemDecl != NULL)
561 xmlHashFree(schema->elemDecl,
562 (xmlHashDeallocator) xmlSchemaFreeElement);
563 if (schema->typeDecl != NULL)
564 xmlHashFree(schema->typeDecl,
565 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000566 if (schema->groupDecl != NULL)
567 xmlHashFree(schema->groupDecl,
568 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000569 if (schema->schemasImports != NULL)
570 xmlHashFree(schema->schemasImports,
571 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillard4255d502002-04-16 15:50:10 +0000572 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000573 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000574 if (schema->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000575 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000576 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000577
578 xmlFree(schema);
579}
580
581/************************************************************************
582 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000583 * Debug functions *
584 * *
585 ************************************************************************/
586
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000587#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588
Daniel Veillard4255d502002-04-16 15:50:10 +0000589/**
590 * xmlSchemaElementDump:
591 * @elem: an element
592 * @output: the file output
593 *
594 * Dump the element
595 */
596static void
597xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000598 const xmlChar * name ATTRIBUTE_UNUSED,
599 const xmlChar * context ATTRIBUTE_UNUSED,
600 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000601{
602 if (elem == NULL)
603 return;
604
605 fprintf(output, "Element ");
606 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000607 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000608 fprintf(output, ": %s ", elem->name);
609 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000610 fprintf(output, "namespace '%s' ", namespace);
611
Daniel Veillard4255d502002-04-16 15:50:10 +0000612 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000613 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000614 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000615 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000616 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000618 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000619 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000620 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000621 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000622 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000623 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000626 fprintf(output, "\n");
627 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 fprintf(output, " ");
629 if (elem->minOccurs != 1)
630 fprintf(output, "min: %d ", elem->minOccurs);
631 if (elem->maxOccurs >= UNBOUNDED)
632 fprintf(output, "max: unbounded\n");
633 else if (elem->maxOccurs != 1)
634 fprintf(output, "max: %d\n", elem->maxOccurs);
635 else
636 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000637 }
638 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000639 fprintf(output, " type: %s", elem->namedType);
640 if (elem->namedTypeNs != NULL)
641 fprintf(output, " ns %s\n", elem->namedTypeNs);
642 else
643 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000644 }
645 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000646 fprintf(output, " substitutionGroup: %s", elem->substGroup);
647 if (elem->substGroupNs != NULL)
648 fprintf(output, " ns %s\n", elem->substGroupNs);
649 else
650 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000651 }
652 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000654}
655
656/**
657 * xmlSchemaAnnotDump:
658 * @output: the file output
659 * @annot: a annotation
660 *
661 * Dump the annotation
662 */
663static void
664xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
665{
666 xmlChar *content;
667
668 if (annot == NULL)
669 return;
670
671 content = xmlNodeGetContent(annot->content);
672 if (content != NULL) {
673 fprintf(output, " Annot: %s\n", content);
674 xmlFree(content);
675 } else
676 fprintf(output, " Annot: empty\n");
677}
678
679/**
680 * xmlSchemaTypeDump:
681 * @output: the file output
682 * @type: a type structure
683 *
684 * Dump a SchemaType structure
685 */
686static void
687xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
688{
689 if (type == NULL) {
690 fprintf(output, "Type: NULL\n");
691 return;
692 }
693 fprintf(output, "Type: ");
694 if (type->name != NULL)
695 fprintf(output, "%s, ", type->name);
696 else
697 fprintf(output, "no name");
698 switch (type->type) {
699 case XML_SCHEMA_TYPE_BASIC:
700 fprintf(output, "basic ");
701 break;
702 case XML_SCHEMA_TYPE_SIMPLE:
703 fprintf(output, "simple ");
704 break;
705 case XML_SCHEMA_TYPE_COMPLEX:
706 fprintf(output, "complex ");
707 break;
708 case XML_SCHEMA_TYPE_SEQUENCE:
709 fprintf(output, "sequence ");
710 break;
711 case XML_SCHEMA_TYPE_CHOICE:
712 fprintf(output, "choice ");
713 break;
714 case XML_SCHEMA_TYPE_ALL:
715 fprintf(output, "all ");
716 break;
717 case XML_SCHEMA_TYPE_UR:
718 fprintf(output, "ur ");
719 break;
720 case XML_SCHEMA_TYPE_RESTRICTION:
721 fprintf(output, "restriction ");
722 break;
723 case XML_SCHEMA_TYPE_EXTENSION:
724 fprintf(output, "extension ");
725 break;
726 default:
727 fprintf(output, "unknowntype%d ", type->type);
728 break;
729 }
730 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000731 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000732 }
733 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000734 case XML_SCHEMA_CONTENT_UNKNOWN:
735 fprintf(output, "unknown ");
736 break;
737 case XML_SCHEMA_CONTENT_EMPTY:
738 fprintf(output, "empty ");
739 break;
740 case XML_SCHEMA_CONTENT_ELEMENTS:
741 fprintf(output, "element ");
742 break;
743 case XML_SCHEMA_CONTENT_MIXED:
744 fprintf(output, "mixed ");
745 break;
746 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
747 fprintf(output, "mixed_or_elems ");
748 break;
749 case XML_SCHEMA_CONTENT_BASIC:
750 fprintf(output, "basic ");
751 break;
752 case XML_SCHEMA_CONTENT_SIMPLE:
753 fprintf(output, "simple ");
754 break;
755 case XML_SCHEMA_CONTENT_ANY:
756 fprintf(output, "any ");
757 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000758 }
759 fprintf(output, "\n");
760 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761 fprintf(output, " ");
762 if (type->minOccurs != 1)
763 fprintf(output, "min: %d ", type->minOccurs);
764 if (type->maxOccurs >= UNBOUNDED)
765 fprintf(output, "max: unbounded\n");
766 else if (type->maxOccurs != 1)
767 fprintf(output, "max: %d\n", type->maxOccurs);
768 else
769 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000770 }
771 if (type->annot != NULL)
772 xmlSchemaAnnotDump(output, type->annot);
773 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000774 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000775
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000776 fprintf(output, " subtypes: ");
777 while (sub != NULL) {
778 fprintf(output, "%s ", sub->name);
779 sub = sub->next;
780 }
781 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000782 }
783
784}
785
786/**
787 * xmlSchemaDump:
788 * @output: the file output
789 * @schema: a schema structure
790 *
791 * Dump a Schema structure.
792 */
793void
794xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
795{
796 if (schema == NULL) {
797 fprintf(output, "Schemas: NULL\n");
798 return;
799 }
800 fprintf(output, "Schemas: ");
801 if (schema->name != NULL)
802 fprintf(output, "%s, ", schema->name);
803 else
804 fprintf(output, "no name, ");
805 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000806 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000807 else
808 fprintf(output, "no target namespace");
809 fprintf(output, "\n");
810 if (schema->annot != NULL)
811 xmlSchemaAnnotDump(output, schema->annot);
812
813 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
814 output);
815 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000816 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000817}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000818#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000819
820/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000821 * *
822 * Utilities *
823 * *
824 ************************************************************************/
825/**
826 * numberedString:
827 * @prefix: the string prefix
828 * @number: the number
829 *
830 * Build a new numbered string
831 *
832 * Returns the new string
833 */
834
835/**
836 * xmlSchemaGetProp:
837 * @ctxt: the parser context
838 * @node: the node
839 * @name: the property name
840 *
841 * Read a attribute value and internalize the string
842 *
843 * Returns the string or NULL if not present.
844 */
845static const xmlChar *
846xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
847 const char *name)
848{
849 xmlChar *val;
850 const xmlChar *ret;
851
852 val = xmlGetProp(node, BAD_CAST name);
853 if (val == NULL)
854 return(NULL);
855 ret = xmlDictLookup(ctxt->dict, val, -1);
856 xmlFree(val);
857 return(ret);
858}
859
860/**
861 * xmlSchemaGetNamespace:
862 * @ctxt: the parser context
863 * @schema: the schemas containing the declaration
864 * @node: the node
865 * @qname: the QName to analyze
866 *
867 * Find the namespace name for the given declaration.
868 *
869 * Returns the local name for that declaration, as well as the namespace name
870 */
871static const xmlChar *
872xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
873 xmlNodePtr node, const xmlChar *qname,
874 const xmlChar **namespace) {
875 int len;
876 const xmlChar *name, *prefix, *def = NULL;
877 xmlNsPtr ns;
878
879 *namespace = NULL;
880
881 if (xmlStrEqual(node->name, BAD_CAST "element") ||
882 xmlStrEqual(node->name, BAD_CAST "attribute") ||
883 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
884 xmlStrEqual(node->name, BAD_CAST "complexType")) {
885 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
886 }
887
888 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
889 name = xmlSplitQName3(qname, &len);
890 if (name == NULL) {
891 if (def == NULL) {
892 if (xmlStrEqual(node->name, BAD_CAST "element")) {
893 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
894 *namespace = schema->targetNamespace;
895 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
896 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
897 *namespace = schema->targetNamespace;
898 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
899 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
900 *namespace = schema->targetNamespace;
901 }
902 } else {
903 *namespace = def;
904 }
905 return(qname);
906 }
907 name = xmlDictLookup(ctxt->dict, name, -1);
908 prefix = xmlDictLookup(ctxt->dict, qname, len);
909 if (def != NULL) {
910 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
911 "%s: presence of both prefix %s and targetNamespace\n",
912 node->name, prefix);
913 }
914 ns = xmlSearchNs(node->doc, node, prefix);
915 if (ns == NULL) {
916 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
917 "%s: the QName prefix %s is undefined\n",
918 node->name, prefix);
919 return(name);
920 }
921 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
922 return(name);
923}
924
925/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +0000926 * *
927 * Parsing functions *
928 * *
929 ************************************************************************/
930
931/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000932 * xmlSchemaGetElem:
933 * @schema: the schemas context
934 * @name: the element name
935 * @ns: the element namespace
936 *
937 * Lookup a an element in the schemas or the accessible schemas
938 *
939 * Returns the element definition or NULL if not found.
940 */
941static xmlSchemaElementPtr
942xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
943 const xmlChar * namespace)
944{
945 xmlSchemaElementPtr ret;
946 xmlSchemaImportPtr import;
947
948 if ((name == NULL) || (schema == NULL))
949 return (NULL);
950
951 if (namespace == NULL) {
952 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
953 if (ret != NULL)
954 return (ret);
955 } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
956 if (xmlStrEqual(namespace, schema->targetNamespace))
957 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
958 else
959 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
960 if (ret != NULL)
961 return (ret);
962 } else {
963 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
964 if (ret != NULL)
965 return (ret);
966 }
967 import = xmlHashLookup(schema->schemasImports, namespace);
968 if (import != NULL)
969 ret = xmlSchemaGetElem(import->schema, name, namespace);
970#ifdef DEBUG
971 if (ret == NULL) {
972 if (namespace == NULL)
973 fprintf(stderr, "Unable to lookup type %s", name);
974 else
975 fprintf(stderr, "Unable to lookup type %s:%s", name,
976 namespace);
977 }
978#endif
979 return (ret);
980}
981
982/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000983 * xmlSchemaGetType:
984 * @schema: the schemas context
985 * @name: the type name
986 * @ns: the type namespace
987 *
988 * Lookup a type in the schemas or the predefined types
989 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000990 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +0000991 */
992static xmlSchemaTypePtr
993xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000994 const xmlChar * namespace)
995{
Daniel Veillard4255d502002-04-16 15:50:10 +0000996 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +0000997 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +0000998
999 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001000 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001001 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001002 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1003 if (ret != NULL)
1004 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001005 }
1006 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001007 if (ret != NULL)
1008 return (ret);
1009 import = xmlHashLookup(schema->schemasImports, namespace);
1010 if (import != NULL)
1011 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001012#ifdef DEBUG
1013 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001014 if (namespace == NULL)
1015 fprintf(stderr, "Unable to lookup type %s", name);
1016 else
1017 fprintf(stderr, "Unable to lookup type %s:%s", name,
1018 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001019 }
1020#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001021 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001022}
1023
1024/************************************************************************
1025 * *
1026 * Parsing functions *
1027 * *
1028 ************************************************************************/
1029
1030#define IS_BLANK_NODE(n) \
1031 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1032
1033/**
1034 * xmlSchemaIsBlank:
1035 * @str: a string
1036 *
1037 * Check if a string is ignorable
1038 *
1039 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1040 */
1041static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001042xmlSchemaIsBlank(xmlChar * str)
1043{
Daniel Veillard4255d502002-04-16 15:50:10 +00001044 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001045 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001046 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001047 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001048 return (0);
1049 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001050 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001051 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001052}
1053
1054/**
1055 * xmlSchemaAddNotation:
1056 * @ctxt: a schema validation context
1057 * @schema: the schema being built
1058 * @name: the item name
1059 *
1060 * Add an XML schema Attrribute declaration
1061 * *WARNING* this interface is highly subject to change
1062 *
1063 * Returns the new struture or NULL in case of error
1064 */
1065static xmlSchemaNotationPtr
1066xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001067 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001068{
1069 xmlSchemaNotationPtr ret = NULL;
1070 int val;
1071
1072 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1073 return (NULL);
1074
1075 if (schema->notaDecl == NULL)
1076 schema->notaDecl = xmlHashCreate(10);
1077 if (schema->notaDecl == NULL)
1078 return (NULL);
1079
1080 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1081 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001082 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001083 return (NULL);
1084 }
1085 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001086 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001087 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1088 ret);
1089 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001090 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1091 XML_SCHEMAP_REDEFINED_NOTATION,
1092 "Notation %s already defined\n",
1093 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001094 xmlFree(ret);
1095 return (NULL);
1096 }
1097 return (ret);
1098}
1099
1100
1101/**
1102 * xmlSchemaAddAttribute:
1103 * @ctxt: a schema validation context
1104 * @schema: the schema being built
1105 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001106 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001107 *
1108 * Add an XML schema Attrribute declaration
1109 * *WARNING* this interface is highly subject to change
1110 *
1111 * Returns the new struture or NULL in case of error
1112 */
1113static xmlSchemaAttributePtr
1114xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001115 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001116{
1117 xmlSchemaAttributePtr ret = NULL;
1118 int val;
1119
1120 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1121 return (NULL);
1122
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001123#ifdef DEBUG
1124 fprintf(stderr, "Adding attribute %s\n", name);
1125 if (namespace != NULL)
1126 fprintf(stderr, " target namespace %s\n", namespace);
1127#endif
1128
Daniel Veillard4255d502002-04-16 15:50:10 +00001129 if (schema->attrDecl == NULL)
1130 schema->attrDecl = xmlHashCreate(10);
1131 if (schema->attrDecl == NULL)
1132 return (NULL);
1133
1134 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1135 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001136 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001137 return (NULL);
1138 }
1139 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001140 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1141 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001142 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001143 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001144 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001145 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1146 XML_SCHEMAP_REDEFINED_ATTR,
1147 "Attribute %s already defined\n",
1148 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001149 xmlFree(ret);
1150 return (NULL);
1151 }
1152 return (ret);
1153}
1154
1155/**
1156 * xmlSchemaAddAttributeGroup:
1157 * @ctxt: a schema validation context
1158 * @schema: the schema being built
1159 * @name: the item name
1160 *
1161 * Add an XML schema Attrribute Group declaration
1162 *
1163 * Returns the new struture or NULL in case of error
1164 */
1165static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001166xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1167 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001168{
1169 xmlSchemaAttributeGroupPtr ret = NULL;
1170 int val;
1171
1172 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1173 return (NULL);
1174
1175 if (schema->attrgrpDecl == NULL)
1176 schema->attrgrpDecl = xmlHashCreate(10);
1177 if (schema->attrgrpDecl == NULL)
1178 return (NULL);
1179
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001180 ret =
1181 (xmlSchemaAttributeGroupPtr)
1182 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001183 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001184 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001185 return (NULL);
1186 }
1187 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001188 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001189 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001190 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001191 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001192 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1193 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1194 "Attribute group %s already defined\n",
1195 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001196 xmlFree(ret);
1197 return (NULL);
1198 }
1199 return (ret);
1200}
1201
1202/**
1203 * xmlSchemaAddElement:
1204 * @ctxt: a schema validation context
1205 * @schema: the schema being built
1206 * @name: the type name
1207 * @namespace: the type namespace
1208 *
1209 * Add an XML schema Element declaration
1210 * *WARNING* this interface is highly subject to change
1211 *
1212 * Returns the new struture or NULL in case of error
1213 */
1214static xmlSchemaElementPtr
1215xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1216 const xmlChar * name, const xmlChar * namespace)
1217{
1218 xmlSchemaElementPtr ret = NULL;
1219 int val;
1220
1221 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1222 return (NULL);
1223
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001224#ifdef DEBUG
1225 fprintf(stderr, "Adding element %s\n", name);
1226 if (namespace != NULL)
1227 fprintf(stderr, " target namespace %s\n", namespace);
1228#endif
1229
Daniel Veillard4255d502002-04-16 15:50:10 +00001230 if (schema->elemDecl == NULL)
1231 schema->elemDecl = xmlHashCreate(10);
1232 if (schema->elemDecl == NULL)
1233 return (NULL);
1234
1235 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1236 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001237 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001238 return (NULL);
1239 }
1240 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001241 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1242 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001243 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001244 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001245 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001246 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001247
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001248 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001249 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1250 namespace, ret);
1251 if (val != 0) {
1252 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1253 XML_SCHEMAP_REDEFINED_ELEMENT,
1254 "Element %s already defined\n",
1255 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001256 xmlFree(ret);
1257 return (NULL);
1258 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001259 }
1260 return (ret);
1261}
1262
1263/**
1264 * xmlSchemaAddType:
1265 * @ctxt: a schema validation context
1266 * @schema: the schema being built
1267 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001268 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001269 *
1270 * Add an XML schema Simple Type definition
1271 * *WARNING* this interface is highly subject to change
1272 *
1273 * Returns the new struture or NULL in case of error
1274 */
1275static xmlSchemaTypePtr
1276xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001277 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001278{
1279 xmlSchemaTypePtr ret = NULL;
1280 int val;
1281
1282 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1283 return (NULL);
1284
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001285#ifdef DEBUG
1286 fprintf(stderr, "Adding type %s\n", name);
1287 if (namespace != NULL)
1288 fprintf(stderr, " target namespace %s\n", namespace);
1289#endif
1290
Daniel Veillard4255d502002-04-16 15:50:10 +00001291 if (schema->typeDecl == NULL)
1292 schema->typeDecl = xmlHashCreate(10);
1293 if (schema->typeDecl == NULL)
1294 return (NULL);
1295
1296 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1297 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001298 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001299 return (NULL);
1300 }
1301 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001302 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1303 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001304 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001305 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1306 XML_SCHEMAP_REDEFINED_TYPE,
1307 "Type %s already defined\n",
1308 name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001309 xmlFree(ret);
1310 return (NULL);
1311 }
1312 ret->minOccurs = 1;
1313 ret->maxOccurs = 1;
1314
1315 return (ret);
1316}
1317
1318/**
1319 * xmlSchemaAddGroup:
1320 * @ctxt: a schema validation context
1321 * @schema: the schema being built
1322 * @name: the group name
1323 *
1324 * Add an XML schema Group definition
1325 *
1326 * Returns the new struture or NULL in case of error
1327 */
1328static xmlSchemaTypePtr
1329xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001330 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001331{
1332 xmlSchemaTypePtr ret = NULL;
1333 int val;
1334
1335 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1336 return (NULL);
1337
1338 if (schema->groupDecl == NULL)
1339 schema->groupDecl = xmlHashCreate(10);
1340 if (schema->groupDecl == NULL)
1341 return (NULL);
1342
1343 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1344 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001345 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001346 return (NULL);
1347 }
1348 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001349 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 val =
1351 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1352 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001353 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001354 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1355 XML_SCHEMAP_REDEFINED_GROUP,
1356 "Group %s already defined\n",
1357 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001358 xmlFree(ret);
1359 return (NULL);
1360 }
1361 ret->minOccurs = 1;
1362 ret->maxOccurs = 1;
1363
1364 return (ret);
1365}
1366
1367/************************************************************************
1368 * *
1369 * Utilities for parsing *
1370 * *
1371 ************************************************************************/
1372
1373/**
1374 * xmlGetQNameProp:
1375 * @ctxt: a schema validation context
1376 * @node: a subtree containing XML Schema informations
1377 * @name: the attribute name
1378 * @namespace: the result namespace if any
1379 *
1380 * Extract a QName Attribute value
1381 *
1382 * Returns the NCName or NULL if not found, and also update @namespace
1383 * with the namespace URI
1384 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001385static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001386xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001387 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001388{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001389 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001390 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001391 const xmlChar *ret, *prefix;
1392 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001393
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001394 *namespace = NULL;
1395 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001396 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001397 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001398
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001399 ret = xmlSplitQName3(val, &len);
1400 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001401 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001402 }
1403 ret = xmlDictLookup(ctxt->dict, ret, -1);
1404 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001405
1406 ns = xmlSearchNs(node->doc, node, prefix);
1407 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001408 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1409 "Attribute %s: the QName prefix %s is undefined\n",
1410 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001411 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001412 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001413 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001414 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001415}
1416
1417/**
1418 * xmlGetMaxOccurs:
1419 * @ctxt: a schema validation context
1420 * @node: a subtree containing XML Schema informations
1421 *
1422 * Get the maxOccurs property
1423 *
1424 * Returns the default if not found, or the value
1425 */
1426static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001427xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1428{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001429 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001430 int ret = 0;
1431
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001432 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001433 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001434 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001435
1436 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001437 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001438 }
1439
1440 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001441 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001442 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001443 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001444 ret = ret * 10 + (*cur - '0');
1445 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001446 }
William M. Brack76e95df2003-10-18 16:20:14 +00001447 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001448 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001449 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001450 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1451 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001453 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001455}
1456
1457/**
1458 * xmlGetMinOccurs:
1459 * @ctxt: a schema validation context
1460 * @node: a subtree containing XML Schema informations
1461 *
1462 * Get the minOccurs property
1463 *
1464 * Returns the default if not found, or the value
1465 */
1466static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001467xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1468{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001469 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001470 int ret = 0;
1471
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001472 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001473 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001474 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001475
1476 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001477 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001478 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001479 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001480 ret = ret * 10 + (*cur - '0');
1481 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001482 }
William M. Brack76e95df2003-10-18 16:20:14 +00001483 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001484 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001485 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001486 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1487 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001488 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001489 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001490 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001491}
1492
1493/**
1494 * xmlGetBooleanProp:
1495 * @ctxt: a schema validation context
1496 * @node: a subtree containing XML Schema informations
1497 * @name: the attribute name
1498 * @def: the default value
1499 *
1500 * Get is a bolean property is set
1501 *
1502 * Returns the default if not found, 0 if found to be false,
1503 * 1 if found to be true
1504 */
1505static int
1506xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001507 const char *name, int def)
1508{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001509 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001510
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001511 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001512 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001513 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001514
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001515 if (xmlStrEqual(val, BAD_CAST "true"))
1516 def = 1;
1517 else if (xmlStrEqual(val, BAD_CAST "false"))
1518 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001519 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001520 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1521 "Attribute %s: the value %s is not boolean\n",
1522 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001523 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001524 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001525}
1526
1527/************************************************************************
1528 * *
1529 * Shema extraction from an Infoset *
1530 * *
1531 ************************************************************************/
1532static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1533 ctxt, xmlSchemaPtr schema,
1534 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001535static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1536 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001537 xmlSchemaPtr schema,
1538 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001539static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1540 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001541 xmlSchemaPtr schema,
1542 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001543 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001544static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1545 xmlSchemaPtr schema,
1546 xmlNodePtr node);
1547static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1548 xmlSchemaPtr schema,
1549 xmlNodePtr node);
1550static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1551 ctxt,
1552 xmlSchemaPtr schema,
1553 xmlNodePtr node);
1554static xmlSchemaAttributeGroupPtr
1555xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1556 xmlSchemaPtr schema, xmlNodePtr node);
1557static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1558 xmlSchemaPtr schema,
1559 xmlNodePtr node);
1560static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1561 xmlSchemaPtr schema,
1562 xmlNodePtr node);
1563static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001564xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1565 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001566
1567/**
1568 * xmlSchemaParseAttrDecls:
1569 * @ctxt: a schema validation context
1570 * @schema: the schema being built
1571 * @node: a subtree containing XML Schema informations
1572 * @type: the hosting type
1573 *
1574 * parse a XML schema attrDecls declaration corresponding to
1575 * <!ENTITY % attrDecls
1576 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1577 */
1578static xmlNodePtr
1579xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1580 xmlNodePtr child, xmlSchemaTypePtr type)
1581{
1582 xmlSchemaAttributePtr lastattr, attr;
1583
1584 lastattr = NULL;
1585 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001586 (IS_SCHEMA(child, "attributeGroup"))) {
1587 attr = NULL;
1588 if (IS_SCHEMA(child, "attribute")) {
1589 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1590 } else if (IS_SCHEMA(child, "attributeGroup")) {
1591 attr = (xmlSchemaAttributePtr)
1592 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1593 }
1594 if (attr != NULL) {
1595 if (lastattr == NULL) {
1596 type->attributes = attr;
1597 lastattr = attr;
1598 } else {
1599 lastattr->next = attr;
1600 lastattr = attr;
1601 }
1602 }
1603 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001604 }
1605 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001606 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1607 if (attr != NULL) {
1608 if (lastattr == NULL) {
1609 type->attributes = attr;
1610 lastattr = attr;
1611 } else {
1612 lastattr->next = attr;
1613 lastattr = attr;
1614 }
1615 }
1616 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001617 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001618 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001619}
1620
1621/**
1622 * xmlSchemaParseAnnotation:
1623 * @ctxt: a schema validation context
1624 * @schema: the schema being built
1625 * @node: a subtree containing XML Schema informations
1626 *
1627 * parse a XML schema Attrribute declaration
1628 * *WARNING* this interface is highly subject to change
1629 *
1630 * Returns -1 in case of error, 0 if the declaration is inproper and
1631 * 1 in case of success.
1632 */
1633static xmlSchemaAnnotPtr
1634xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1635 xmlNodePtr node)
1636{
1637 xmlSchemaAnnotPtr ret;
1638
1639 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1640 return (NULL);
1641 ret = xmlSchemaNewAnnot(ctxt, node);
1642
1643 return (ret);
1644}
1645
1646/**
1647 * xmlSchemaParseFacet:
1648 * @ctxt: a schema validation context
1649 * @schema: the schema being built
1650 * @node: a subtree containing XML Schema informations
1651 *
1652 * parse a XML schema Facet declaration
1653 * *WARNING* this interface is highly subject to change
1654 *
1655 * Returns the new type structure or NULL in case of error
1656 */
1657static xmlSchemaFacetPtr
1658xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001659 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001660{
1661 xmlSchemaFacetPtr facet;
1662 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001663 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001664
1665 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1666 return (NULL);
1667
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001668 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001669 if (facet == NULL) {
1670 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1671 return (NULL);
1672 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001673 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001674 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001675 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001676 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1677 "Facet %s has no value\n", node->name, NULL);
1678 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001679 return (NULL);
1680 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001681 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001682 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001683 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001684 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001685 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001686 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001687 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001688 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001689 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001690 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001691 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001692 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001693 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001694 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001695 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001696 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001697 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001698 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001699 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001700 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001701 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001702 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1703 } else if (IS_SCHEMA(node, "minLength")) {
1704 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1705 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001706 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1707 "Unknown facet type %s\n", node->name, NULL);
1708 xmlSchemaFreeFacet(facet);
1709 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001710 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001711 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001712 facet->value = value;
1713 child = node->children;
1714
1715 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001716 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1717 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001718 }
1719 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001720 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1721 "Facet %s has unexpected child content\n",
1722 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001723 }
1724 return (facet);
1725}
1726
1727/**
1728 * xmlSchemaParseAny:
1729 * @ctxt: a schema validation context
1730 * @schema: the schema being built
1731 * @node: a subtree containing XML Schema informations
1732 *
1733 * parse a XML schema Any declaration
1734 * *WARNING* this interface is highly subject to change
1735 *
1736 * Returns the new type structure or NULL in case of error
1737 */
1738static xmlSchemaTypePtr
1739xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1740 xmlNodePtr node)
1741{
1742 xmlSchemaTypePtr type;
1743 xmlNodePtr child = NULL;
1744 xmlChar name[30];
1745
1746 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1747 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001748 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001749 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001750 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001751 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001752 type->node = node;
1753 type->type = XML_SCHEMA_TYPE_ANY;
1754 child = node->children;
1755 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1756 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1757
1758 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001759 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001761 }
1762 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001763 xmlSchemaPErr2(ctxt, node, child,
1764 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1765 "Sequence %s has unexpected content\n", type->name,
1766 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001767 }
1768
1769 return (type);
1770}
1771
1772/**
1773 * xmlSchemaParseNotation:
1774 * @ctxt: a schema validation context
1775 * @schema: the schema being built
1776 * @node: a subtree containing XML Schema informations
1777 *
1778 * parse a XML schema Notation declaration
1779 *
1780 * Returns the new structure or NULL in case of error
1781 */
1782static xmlSchemaNotationPtr
1783xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001784 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001785{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001786 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001787 xmlSchemaNotationPtr ret;
1788 xmlNodePtr child = NULL;
1789
1790 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1791 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001792 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001793 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001794 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1795 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001796 return (NULL);
1797 }
1798 ret = xmlSchemaAddNotation(ctxt, schema, name);
1799 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001800 return (NULL);
1801 }
1802 child = node->children;
1803 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001804 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1805 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 }
1807 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001808 xmlSchemaPErr2(ctxt, node, child,
1809 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1810 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001811 }
1812
1813 return (ret);
1814}
1815
1816/**
1817 * xmlSchemaParseAnyAttribute:
1818 * @ctxt: a schema validation context
1819 * @schema: the schema being built
1820 * @node: a subtree containing XML Schema informations
1821 *
1822 * parse a XML schema AnyAttrribute declaration
1823 * *WARNING* this interface is highly subject to change
1824 *
1825 * Returns an attribute def structure or NULL
1826 */
1827static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001828xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1829 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001830{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001831 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001832 xmlSchemaAttributePtr ret;
1833 xmlNodePtr child = NULL;
1834 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001835 const xmlChar *local, *ns;
1836
Daniel Veillard4255d502002-04-16 15:50:10 +00001837
1838 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1839 return (NULL);
1840
1841 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001842 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1843 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001844 if (ret == NULL) {
1845 return (NULL);
1846 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001847 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1848 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001849 if ((processContents == NULL)
1850 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1851 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1852 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1853 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1854 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1855 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001856 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001857 xmlSchemaPErr2(ctxt, node, child,
1858 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1859 "anyAttribute has unexpected content for processContents: %s\n",
1860 processContents, NULL);
1861 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001862 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001863
1864 child = node->children;
1865 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001866 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1867 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001868 }
1869 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001870 xmlSchemaPErr2(ctxt, node, child,
1871 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1872 "anyAttribute %s has unexpected content\n",
1873 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001874 }
1875
1876 return (ret);
1877}
1878
1879
1880/**
1881 * xmlSchemaParseAttribute:
1882 * @ctxt: a schema validation context
1883 * @schema: the schema being built
1884 * @node: a subtree containing XML Schema informations
1885 *
1886 * parse a XML schema Attrribute declaration
1887 * *WARNING* this interface is highly subject to change
1888 *
1889 * Returns -1 in case of error, 0 if the declaration is inproper and
1890 * 1 in case of success.
1891 */
1892static xmlSchemaAttributePtr
1893xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1894 xmlNodePtr node)
1895{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001896 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001897 xmlSchemaAttributePtr ret;
1898 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001899 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001900
1901 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1902 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001903 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001904 if (name == NULL) {
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_ATTR_NONAME_NOREF,
1910 "Attribute has no name nor ref\n", NULL, NULL);
1911 return (NULL);
1912 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001913 if (refNs == NULL)
1914 refNs = schema->targetNamespace;
1915 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
1916 name = (const xmlChar *) buf;
1917 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
1918 } else {
1919 const xmlChar *local, *ns;
1920
1921 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
1922 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001923 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001924 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001925 return (NULL);
1926 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001927 ret->ref = ref;
1928 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001929 if ((ret->targetNamespace != NULL) &&
1930 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
1931 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
1932 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001933 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001934 if ((ret->typeName != NULL) && (ret->typeNs == NULL))
1935 ret->typeNs = schema->targetNamespace;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001936 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001937 child = node->children;
1938 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001939 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1940 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001941 }
1942 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001943 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1944 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001945 }
1946 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
1948 "attribute %s has unexpected content\n", name,
1949 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001950 }
1951
1952 return (ret);
1953}
1954
1955/**
1956 * xmlSchemaParseAttributeGroup:
1957 * @ctxt: a schema validation context
1958 * @schema: the schema being built
1959 * @node: a subtree containing XML Schema informations
1960 *
1961 * parse a XML schema Attribute Group declaration
1962 * *WARNING* this interface is highly subject to change
1963 *
1964 * Returns the attribute group or NULL in case of error.
1965 */
1966static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001967xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1968 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001969{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001970 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001971 xmlSchemaAttributeGroupPtr ret;
1972 xmlSchemaAttributePtr last = NULL, attr;
1973 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001974 const xmlChar *oldcontainer;
1975 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001976
1977 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1978 return (NULL);
1979 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001980 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001981 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001982
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001983 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1984 if (ref == NULL) {
1985 xmlSchemaPErr2(ctxt, node, child,
1986 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
1987 "AttributeGroup has no name nor ref\n", NULL,
1988 NULL);
1989 return (NULL);
1990 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001991 if (refNs == NULL)
1992 refNs = schema->targetNamespace;
1993 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
1994 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001995 if (name == NULL) {
1996 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
1997 return (NULL);
1998 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001999 }
2000 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2001 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002002 return (NULL);
2003 }
2004 ret->ref = ref;
2005 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002006 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002007 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002008 child = node->children;
2009 ctxt->container = name;
2010 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002011 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2012 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002013 }
2014 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002015 (IS_SCHEMA(child, "attributeGroup"))) {
2016 attr = NULL;
2017 if (IS_SCHEMA(child, "attribute")) {
2018 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2019 } else if (IS_SCHEMA(child, "attributeGroup")) {
2020 attr = (xmlSchemaAttributePtr)
2021 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2022 }
2023 if (attr != NULL) {
2024 if (last == NULL) {
2025 ret->attributes = attr;
2026 last = attr;
2027 } else {
2028 last->next = attr;
2029 last = attr;
2030 }
2031 }
2032 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002033 }
2034 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002035 TODO
2036 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002037 }
2038 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002039 xmlSchemaPErr2(ctxt, node, child,
2040 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2041 "attribute group %s has unexpected content\n", name,
2042 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002043 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002044 ctxt->container = oldcontainer;
2045 return (ret);
2046}
2047
2048/**
2049 * xmlSchemaParseElement:
2050 * @ctxt: a schema validation context
2051 * @schema: the schema being built
2052 * @node: a subtree containing XML Schema informations
2053 *
2054 * parse a XML schema Element declaration
2055 * *WARNING* this interface is highly subject to change
2056 *
2057 * Returns -1 in case of error, 0 if the declaration is inproper and
2058 * 1 in case of success.
2059 */
2060static xmlSchemaElementPtr
2061xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2062 xmlNodePtr node, int toplevel)
2063{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002064 const xmlChar *name, *fixed;
2065 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002066 xmlSchemaElementPtr ret;
2067 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002068 const xmlChar *oldcontainer;
2069 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002070
2071 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2072 return (NULL);
2073 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002074 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002075 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002076
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002077 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2078 if (ref == NULL) {
2079 xmlSchemaPErr2(ctxt, node, child,
2080 XML_SCHEMAP_ELEM_NONAME_NOREF,
2081 "Element has no name nor ref\n", NULL, NULL);
2082 return (NULL);
2083 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002084 if (refNs == NULL)
2085 refNs = schema->targetNamespace;
2086 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2087 name = (const xmlChar *) buf;
2088 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2089 } else {
2090 const xmlChar *local, *ns;
2091
2092 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2093 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002094 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002095 if (ret != NULL)
2096 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002097 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002098 return (NULL);
2099 }
2100 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2101 ret->ref = ref;
2102 ret->refNs = refNs;
2103 if (ref != NULL)
2104 ret->flags |= XML_SCHEMAS_ELEM_REF;
2105 if (toplevel)
2106 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2107 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2108 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2109 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2110 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2111 ctxt->container = name;
2112
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002113 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002114 ret->namedType =
2115 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002116 if ((ret->namedType != NULL) && (ret->namedTypeNs == NULL))
2117 ret->namedTypeNs = schema->targetNamespace;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002118 ret->substGroup =
2119 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2120 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002121 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002122 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2123 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002124
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002125 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002126 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002127 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2128 "Element %s has both default and fixed\n",
2129 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002130 } else if (fixed != NULL) {
2131 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002132 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 }
2134
2135 child = node->children;
2136 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002137 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2138 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 }
2140 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002141 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002142 child = child->next;
2143 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002144 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002145 child = child->next;
2146 }
2147 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002148 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2149 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002150 }
2151 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002152 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2153 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002154 }
2155
2156 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002157 return (ret);
2158}
2159
2160/**
2161 * xmlSchemaParseUnion:
2162 * @ctxt: a schema validation context
2163 * @schema: the schema being built
2164 * @node: a subtree containing XML Schema informations
2165 *
2166 * parse a XML schema Union definition
2167 * *WARNING* this interface is highly subject to change
2168 *
2169 * Returns -1 in case of error, 0 if the declaration is inproper and
2170 * 1 in case of success.
2171 */
2172static xmlSchemaTypePtr
2173xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002174 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002175{
2176 xmlSchemaTypePtr type, subtype, last = NULL;
2177 xmlNodePtr child = NULL;
2178 xmlChar name[30];
2179
2180 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2181 return (NULL);
2182
2183
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002184 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002185 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002186 if (type == NULL)
2187 return (NULL);
2188 type->node = node;
2189 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002190 type->id = xmlSchemaGetProp(ctxt, node, "id");
2191 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002192
2193 child = node->children;
2194 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002195 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2196 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002197 }
2198 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002199 subtype = (xmlSchemaTypePtr)
2200 xmlSchemaParseSimpleType(ctxt, schema, child);
2201 if (subtype != NULL) {
2202 if (last == NULL) {
2203 type->subtypes = subtype;
2204 last = subtype;
2205 } else {
2206 last->next = subtype;
2207 last = subtype;
2208 }
2209 last->next = NULL;
2210 }
2211 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002212 }
2213 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002214 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2215 "Union %s has unexpected content\n", type->name,
2216 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 }
2218 return (type);
2219}
2220
2221/**
2222 * xmlSchemaParseList:
2223 * @ctxt: a schema validation context
2224 * @schema: the schema being built
2225 * @node: a subtree containing XML Schema informations
2226 *
2227 * parse a XML schema List definition
2228 * *WARNING* this interface is highly subject to change
2229 *
2230 * Returns -1 in case of error, 0 if the declaration is inproper and
2231 * 1 in case of success.
2232 */
2233static xmlSchemaTypePtr
2234xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002235 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002236{
2237 xmlSchemaTypePtr type, subtype;
2238 xmlNodePtr child = NULL;
2239 xmlChar name[30];
2240
2241 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2242 return (NULL);
2243
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002244 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002245 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 if (type == NULL)
2247 return (NULL);
2248 type->node = node;
2249 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002250 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002252 if ((type->ref != NULL) && (type->refNs == NULL))
2253 type->refNs = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00002254
2255 child = node->children;
2256 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002257 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2258 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002259 }
2260 subtype = NULL;
2261 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002262 subtype = (xmlSchemaTypePtr)
2263 xmlSchemaParseSimpleType(ctxt, schema, child);
2264 child = child->next;
2265 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002266 }
2267 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002268 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2269 "List %s has unexpected content\n", type->name,
2270 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002271 }
2272 return (type);
2273}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002274
Daniel Veillard4255d502002-04-16 15:50:10 +00002275/**
2276 * xmlSchemaParseSimpleType:
2277 * @ctxt: a schema validation context
2278 * @schema: the schema being built
2279 * @node: a subtree containing XML Schema informations
2280 *
2281 * parse a XML schema Simple Type definition
2282 * *WARNING* this interface is highly subject to change
2283 *
2284 * Returns -1 in case of error, 0 if the declaration is inproper and
2285 * 1 in case of success.
2286 */
2287static xmlSchemaTypePtr
2288xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2289 xmlNodePtr node)
2290{
2291 xmlSchemaTypePtr type, subtype;
2292 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002293 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002294
2295 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2296 return (NULL);
2297
2298
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002299 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002300 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002301 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002302
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002303 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2304 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2305 } else {
2306 const xmlChar *local, *ns;
2307
2308 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2309 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002310 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002311 if (type == NULL)
2312 return (NULL);
2313 type->node = node;
2314 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002315 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002316
2317 child = node->children;
2318 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002319 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2320 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002321 }
2322 subtype = NULL;
2323 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002324 subtype = (xmlSchemaTypePtr)
2325 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2326 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002328 subtype = (xmlSchemaTypePtr)
2329 xmlSchemaParseList(ctxt, schema, child);
2330 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002331 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002332 subtype = (xmlSchemaTypePtr)
2333 xmlSchemaParseUnion(ctxt, schema, child);
2334 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002335 }
2336 type->subtypes = subtype;
2337 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002338 xmlSchemaPErr2(ctxt, node, child,
2339 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2340 "SimpleType %s has unexpected content\n",
2341 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002342 }
2343
2344 return (type);
2345}
2346
2347
2348/**
2349 * xmlSchemaParseGroup:
2350 * @ctxt: a schema validation context
2351 * @schema: the schema being built
2352 * @node: a subtree containing XML Schema informations
2353 *
2354 * parse a XML schema Group definition
2355 * *WARNING* this interface is highly subject to change
2356 *
2357 * Returns -1 in case of error, 0 if the declaration is inproper and
2358 * 1 in case of success.
2359 */
2360static xmlSchemaTypePtr
2361xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002362 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002363{
2364 xmlSchemaTypePtr type, subtype;
2365 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002366 const xmlChar *name;
2367 const xmlChar *ref = NULL, *refNs = NULL;
2368 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002369
2370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2371 return (NULL);
2372
2373
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002374 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002375 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002376
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002377 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2378 if (ref == NULL) {
2379 xmlSchemaPErr2(ctxt, node, child,
2380 XML_SCHEMAP_GROUP_NONAME_NOREF,
2381 "Group has no name nor ref\n", NULL, NULL);
2382 return (NULL);
2383 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002384 if (refNs == NULL)
2385 refNs = schema->targetNamespace;
2386 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2387 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002388 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002389 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002390 if (type == NULL)
2391 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002392
Daniel Veillard4255d502002-04-16 15:50:10 +00002393 type->node = node;
2394 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002395 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002396 type->ref = ref;
2397 type->refNs = refNs;
2398 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2399 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2400
2401 child = node->children;
2402 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002403 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2404 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002405 }
2406 subtype = NULL;
2407 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002408 subtype = (xmlSchemaTypePtr)
2409 xmlSchemaParseAll(ctxt, schema, child);
2410 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002411 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002412 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2413 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002414 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 subtype = (xmlSchemaTypePtr)
2416 xmlSchemaParseSequence(ctxt, schema, child);
2417 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002418 }
2419 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002421 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002422 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2423 "Group %s has unexpected content\n", type->name,
2424 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002425 }
2426
2427 return (type);
2428}
2429
2430/**
2431 * xmlSchemaParseAll:
2432 * @ctxt: a schema validation context
2433 * @schema: the schema being built
2434 * @node: a subtree containing XML Schema informations
2435 *
2436 * parse a XML schema All definition
2437 * *WARNING* this interface is highly subject to change
2438 *
2439 * Returns -1 in case of error, 0 if the declaration is inproper and
2440 * 1 in case of success.
2441 */
2442static xmlSchemaTypePtr
2443xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002444 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002445{
2446 xmlSchemaTypePtr type, subtype, last = NULL;
2447 xmlNodePtr child = NULL;
2448 xmlChar name[30];
2449
2450 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2451 return (NULL);
2452
2453
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002454 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002455 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002456 if (type == NULL)
2457 return (NULL);
2458 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002459 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002460 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002461 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2462 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2463
2464 child = node->children;
2465 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002466 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2467 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002468 }
2469 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002470 subtype = (xmlSchemaTypePtr)
2471 xmlSchemaParseElement(ctxt, schema, child, 0);
2472 if (subtype != NULL) {
2473 if (last == NULL) {
2474 type->subtypes = subtype;
2475 last = subtype;
2476 } else {
2477 last->next = subtype;
2478 last = subtype;
2479 }
2480 last->next = NULL;
2481 }
2482 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002483 }
2484 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002485 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2486 "All %s has unexpected content\n", type->name,
2487 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002488 }
2489
2490 return (type);
2491}
2492
2493/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002494 * xmlSchemaImportSchema
2495 *
2496 * @ctxt: a schema validation context
2497 * @schemaLocation: an URI defining where to find the imported schema
2498 *
2499 * import a XML schema
2500 * *WARNING* this interface is highly subject to change
2501 *
2502 * Returns -1 in case of error and 1 in case of success.
2503 */
2504static xmlSchemaImportPtr
2505xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2506 const xmlChar *schemaLocation)
2507{
2508 xmlSchemaImportPtr import;
2509 xmlSchemaParserCtxtPtr newctxt;
2510
2511 newctxt = xmlSchemaNewParserCtxt((const char *) schemaLocation);
2512 if (newctxt == NULL) {
2513 xmlSchemaPErrMemory(NULL, "allocating parser context",
2514 NULL);
2515 return (NULL);
2516 }
2517 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2518 ctxt->userData);
2519
2520 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2521 if (import == NULL) {
2522 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2523 NULL);
2524 xmlSchemaFreeParserCtxt(newctxt);
2525 return (NULL);
2526 }
2527
2528 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002529 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002530 import->schema = xmlSchemaParse(newctxt);
2531
2532 if (import->schema == NULL) {
2533 /* FIXME use another error enum here ? */
2534 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2535 "failed to import schema at location %s\n",
2536 schemaLocation, NULL);
2537
2538 xmlSchemaFreeParserCtxt(newctxt);
2539 if (import->schemaLocation != NULL)
2540 xmlFree((xmlChar *)import->schemaLocation);
2541 xmlFree(import);
2542 return NULL;
2543 }
2544
2545 xmlSchemaFreeParserCtxt(newctxt);
2546 return import;
2547}
2548
2549
2550/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002551 * xmlSchemaParseImport:
2552 * @ctxt: a schema validation context
2553 * @schema: the schema being built
2554 * @node: a subtree containing XML Schema informations
2555 *
2556 * parse a XML schema Import definition
2557 * *WARNING* this interface is highly subject to change
2558 *
2559 * Returns -1 in case of error, 0 if the declaration is inproper and
2560 * 1 in case of success.
2561 */
2562static int
2563xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002564 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002565{
2566 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002567 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002568 const xmlChar *namespace;
2569 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002570 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002571 xmlURIPtr check;
2572
Daniel Veillard1d913862003-11-21 00:28:39 +00002573
Daniel Veillard5a872412002-05-22 06:40:27 +00002574 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2575 return (-1);
2576
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002577 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002578 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002579 check = xmlParseURI((const char *) namespace);
2580 if (check == NULL) {
2581 xmlSchemaPErr2(ctxt, node, child,
2582 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2583 "Import namespace attribute is not an URI: %s\n",
2584 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002585 return (-1);
2586 } else {
2587 xmlFreeURI(check);
2588 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002589 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002590 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002591 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002592 xmlChar *base = NULL;
2593 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002594 check = xmlParseURI((const char *) schemaLocation);
2595 if (check == NULL) {
2596 xmlSchemaPErr2(ctxt, node, child,
2597 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2598 "Import schemaLocation attribute is not an URI: %s\n",
2599 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002600 return (-1);
2601 } else {
2602 xmlFreeURI(check);
2603 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002604 base = xmlNodeGetBase(node->doc, node);
2605 if (base == NULL) {
2606 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2607 } else {
2608 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002609 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002610 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002611 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002612 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2613 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002614 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002615 }
2616 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002617 schema->schemasImports = xmlHashCreate(10);
2618 if (schema->schemasImports == NULL) {
2619 xmlSchemaPErr2(ctxt, node, child,
2620 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2621 "Internal: failed to build import table\n",
2622 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002623 return (-1);
2624 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002625 }
2626 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002627 import = xmlHashLookup(schema->schemasImports,
2628 XML_SCHEMAS_DEFAULT_NAMESPACE);
2629 if (import != NULL)
2630 previous = import->schemaLocation;
2631 else
2632 previous = NULL;
2633
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002634 if (schemaLocation != NULL) {
2635 if (previous != NULL) {
2636 if (!xmlStrEqual(schemaLocation, previous)) {
2637 xmlSchemaPErr2(ctxt, node, child,
2638 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2639 "Redefining import for default namespace with a different URI: %s\n",
2640 schemaLocation, NULL);
2641 }
2642 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002643 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2644 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002645 return (-1);
2646 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002647 xmlHashAddEntry(schema->schemasImports,
2648 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002649 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002650 }
2651 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002652 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002653 import = xmlHashLookup(schema->schemasImports, namespace);
2654 if (import != NULL)
2655 previous = import->schemaLocation;
2656 else
2657 previous = NULL;
2658
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002659 if (schemaLocation != NULL) {
2660 if (previous != NULL) {
2661 if (!xmlStrEqual(schemaLocation, previous)) {
2662 xmlSchemaPErr2(ctxt, node, child,
2663 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2664 "Redefining import for namespace %s with a different URI: %s\n",
2665 namespace, schemaLocation);
2666 }
2667 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002668 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2669 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002670 return (-1);
2671 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002672 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002673 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002674 }
2675 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002676 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002677
2678 child = node->children;
2679 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002680 /*
2681 * the annotations here are simply discarded ...
2682 */
2683 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002684 }
2685 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2687 "Import has unexpected content\n", NULL, NULL);
2688 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002689 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002690 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002691}
2692
2693/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002694 * xmlSchemaParseChoice:
2695 * @ctxt: a schema validation context
2696 * @schema: the schema being built
2697 * @node: a subtree containing XML Schema informations
2698 *
2699 * parse a XML schema Choice definition
2700 * *WARNING* this interface is highly subject to change
2701 *
2702 * Returns -1 in case of error, 0 if the declaration is inproper and
2703 * 1 in case of success.
2704 */
2705static xmlSchemaTypePtr
2706xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002707 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002708{
2709 xmlSchemaTypePtr type, subtype, last = NULL;
2710 xmlNodePtr child = NULL;
2711 xmlChar name[30];
2712
2713 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2714 return (NULL);
2715
2716
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002718 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002719 if (type == NULL)
2720 return (NULL);
2721 type->node = node;
2722 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002723 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002724 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2725 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2726
2727 child = node->children;
2728 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002729 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2730 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002731 }
2732 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002733 (IS_SCHEMA(child, "group")) ||
2734 (IS_SCHEMA(child, "any")) ||
2735 (IS_SCHEMA(child, "choice")) ||
2736 (IS_SCHEMA(child, "sequence"))) {
2737 subtype = NULL;
2738 if (IS_SCHEMA(child, "element")) {
2739 subtype = (xmlSchemaTypePtr)
2740 xmlSchemaParseElement(ctxt, schema, child, 0);
2741 } else if (IS_SCHEMA(child, "group")) {
2742 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2743 } else if (IS_SCHEMA(child, "any")) {
2744 subtype = xmlSchemaParseAny(ctxt, schema, child);
2745 } else if (IS_SCHEMA(child, "sequence")) {
2746 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2747 } else if (IS_SCHEMA(child, "choice")) {
2748 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2749 }
2750 if (subtype != NULL) {
2751 if (last == NULL) {
2752 type->subtypes = subtype;
2753 last = subtype;
2754 } else {
2755 last->next = subtype;
2756 last = subtype;
2757 }
2758 last->next = NULL;
2759 }
2760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 }
2762 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002763 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
2764 "Choice %s has unexpected content\n", type->name,
2765 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 }
2767
2768 return (type);
2769}
2770
2771/**
2772 * xmlSchemaParseSequence:
2773 * @ctxt: a schema validation context
2774 * @schema: the schema being built
2775 * @node: a subtree containing XML Schema informations
2776 *
2777 * parse a XML schema Sequence definition
2778 * *WARNING* this interface is highly subject to change
2779 *
2780 * Returns -1 in case of error, 0 if the declaration is inproper and
2781 * 1 in case of success.
2782 */
2783static xmlSchemaTypePtr
2784xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002785 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002786{
2787 xmlSchemaTypePtr type, subtype, last = NULL;
2788 xmlNodePtr child = NULL;
2789 xmlChar name[30];
2790
2791 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2792 return (NULL);
2793
2794
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002795 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002796 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002797 if (type == NULL)
2798 return (NULL);
2799 type->node = node;
2800 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002801 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002802 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2803 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2804
2805 child = node->children;
2806 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002807 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2808 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002809 }
2810 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002811 (IS_SCHEMA(child, "group")) ||
2812 (IS_SCHEMA(child, "any")) ||
2813 (IS_SCHEMA(child, "choice")) ||
2814 (IS_SCHEMA(child, "sequence"))) {
2815 subtype = NULL;
2816 if (IS_SCHEMA(child, "element")) {
2817 subtype = (xmlSchemaTypePtr)
2818 xmlSchemaParseElement(ctxt, schema, child, 0);
2819 } else if (IS_SCHEMA(child, "group")) {
2820 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2821 } else if (IS_SCHEMA(child, "any")) {
2822 subtype = xmlSchemaParseAny(ctxt, schema, child);
2823 } else if (IS_SCHEMA(child, "choice")) {
2824 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2825 } else if (IS_SCHEMA(child, "sequence")) {
2826 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2827 }
2828 if (subtype != NULL) {
2829 if (last == NULL) {
2830 type->subtypes = subtype;
2831 last = subtype;
2832 } else {
2833 last->next = subtype;
2834 last = subtype;
2835 }
2836 last->next = NULL;
2837 }
2838 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002839 }
2840 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002841 xmlSchemaPErr2(ctxt, node, child,
2842 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2843 "Sequence %s has unexpected content\n", type->name,
2844 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002845 }
2846
2847 return (type);
2848}
2849
2850/**
2851 * xmlSchemaParseRestriction:
2852 * @ctxt: a schema validation context
2853 * @schema: the schema being built
2854 * @node: a subtree containing XML Schema informations
2855 * @simple: is that part of a simple type.
2856 *
2857 * parse a XML schema Restriction definition
2858 * *WARNING* this interface is highly subject to change
2859 *
2860 * Returns the type definition or NULL in case of error
2861 */
2862static xmlSchemaTypePtr
2863xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2864 xmlNodePtr node, int simple)
2865{
2866 xmlSchemaTypePtr type, subtype;
2867 xmlSchemaFacetPtr facet, lastfacet = NULL;
2868 xmlNodePtr child = NULL;
2869 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002870 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002871
2872 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2873 return (NULL);
2874
2875 oldcontainer = ctxt->container;
2876
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002878 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002879 if (type == NULL)
2880 return (NULL);
2881 type->node = node;
2882 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002883 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002884 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2885 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002886 xmlSchemaPErr2(ctxt, node, child,
2887 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
2888 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002889 }
2890 ctxt->container = name;
2891
2892 child = node->children;
2893 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002894 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2895 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002896 }
2897 subtype = NULL;
2898
2899 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002900 subtype = (xmlSchemaTypePtr)
2901 xmlSchemaParseAll(ctxt, schema, child);
2902 child = child->next;
2903 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002904 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002905 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2906 child = child->next;
2907 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002908 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002909 subtype = (xmlSchemaTypePtr)
2910 xmlSchemaParseSequence(ctxt, schema, child);
2911 child = child->next;
2912 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002913 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002914 subtype = (xmlSchemaTypePtr)
2915 xmlSchemaParseGroup(ctxt, schema, child);
2916 child = child->next;
2917 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002918 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002919 if (IS_SCHEMA(child, "simpleType")) {
2920 subtype = (xmlSchemaTypePtr)
2921 xmlSchemaParseSimpleType(ctxt, schema, child);
2922 child = child->next;
2923 type->baseType = subtype;
2924 }
2925 /*
2926 * Facets
2927 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002928 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002929 (IS_SCHEMA(child, "minExclusive")) ||
2930 (IS_SCHEMA(child, "maxInclusive")) ||
2931 (IS_SCHEMA(child, "maxExclusive")) ||
2932 (IS_SCHEMA(child, "totalDigits")) ||
2933 (IS_SCHEMA(child, "fractionDigits")) ||
2934 (IS_SCHEMA(child, "pattern")) ||
2935 (IS_SCHEMA(child, "enumeration")) ||
2936 (IS_SCHEMA(child, "whiteSpace")) ||
2937 (IS_SCHEMA(child, "length")) ||
2938 (IS_SCHEMA(child, "maxLength")) ||
2939 (IS_SCHEMA(child, "minLength"))) {
2940 facet = xmlSchemaParseFacet(ctxt, schema, child);
2941 if (facet != NULL) {
2942 if (lastfacet == NULL) {
2943 type->facets = facet;
2944 lastfacet = facet;
2945 } else {
2946 lastfacet->next = facet;
2947 lastfacet = facet;
2948 }
2949 lastfacet->next = NULL;
2950 }
2951 child = child->next;
2952 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002953 }
2954 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2955 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002956 xmlSchemaPErr2(ctxt, node, child,
2957 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
2958 "Restriction %s has unexpected content\n",
2959 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002960 }
2961 ctxt->container = oldcontainer;
2962 return (type);
2963}
2964
2965/**
2966 * xmlSchemaParseExtension:
2967 * @ctxt: a schema validation context
2968 * @schema: the schema being built
2969 * @node: a subtree containing XML Schema informations
2970 *
2971 * parse a XML schema Extension definition
2972 * *WARNING* this interface is highly subject to change
2973 *
2974 * Returns the type definition or NULL in case of error
2975 */
2976static xmlSchemaTypePtr
2977xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002978 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002979{
2980 xmlSchemaTypePtr type, subtype;
2981 xmlNodePtr child = NULL;
2982 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002983 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002984
2985 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2986 return (NULL);
2987
2988 oldcontainer = ctxt->container;
2989
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002990 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002991 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002992 if (type == NULL)
2993 return (NULL);
2994 type->node = node;
2995 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002996 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002997 ctxt->container = name;
2998
2999 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3000 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003001 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3002 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003003 }
3004 child = node->children;
3005 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003006 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3007 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003008 }
3009 subtype = NULL;
3010
3011 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003012 subtype = xmlSchemaParseAll(ctxt, schema, child);
3013 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003014 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003015 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3016 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003017 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3019 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003020 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003021 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3022 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003023 }
3024 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003025 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003026 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3027 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003028 xmlSchemaPErr2(ctxt, node, child,
3029 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3030 "Extension %s has unexpected content\n", type->name,
3031 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003032 }
3033 ctxt->container = oldcontainer;
3034 return (type);
3035}
3036
3037/**
3038 * xmlSchemaParseSimpleContent:
3039 * @ctxt: a schema validation context
3040 * @schema: the schema being built
3041 * @node: a subtree containing XML Schema informations
3042 *
3043 * parse a XML schema SimpleContent definition
3044 * *WARNING* this interface is highly subject to change
3045 *
3046 * Returns the type definition or NULL in case of error
3047 */
3048static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003049xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3050 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003051{
3052 xmlSchemaTypePtr type, subtype;
3053 xmlNodePtr child = NULL;
3054 xmlChar name[30];
3055
3056 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3057 return (NULL);
3058
3059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003060 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003061 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003062 if (type == NULL)
3063 return (NULL);
3064 type->node = node;
3065 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003066 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003067
3068 child = node->children;
3069 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003070 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3071 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 }
3073 subtype = NULL;
3074 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003075 subtype = (xmlSchemaTypePtr)
3076 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3077 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003078 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003079 subtype = (xmlSchemaTypePtr)
3080 xmlSchemaParseExtension(ctxt, schema, child);
3081 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003082 }
3083 type->subtypes = subtype;
3084 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003085 xmlSchemaPErr2(ctxt, node, child,
3086 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3087 "SimpleContent %s has unexpected content\n",
3088 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003089 }
3090 return (type);
3091}
3092
3093/**
3094 * xmlSchemaParseComplexContent:
3095 * @ctxt: a schema validation context
3096 * @schema: the schema being built
3097 * @node: a subtree containing XML Schema informations
3098 *
3099 * parse a XML schema ComplexContent definition
3100 * *WARNING* this interface is highly subject to change
3101 *
3102 * Returns the type definition or NULL in case of error
3103 */
3104static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003105xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3106 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003107{
3108 xmlSchemaTypePtr type, subtype;
3109 xmlNodePtr child = NULL;
3110 xmlChar name[30];
3111
3112 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3113 return (NULL);
3114
3115
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003116 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003117 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003118 if (type == NULL)
3119 return (NULL);
3120 type->node = node;
3121 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003122 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003123
3124 child = node->children;
3125 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003126 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003128 }
3129 subtype = NULL;
3130 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003131 subtype = (xmlSchemaTypePtr)
3132 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003134 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003135 subtype = (xmlSchemaTypePtr)
3136 xmlSchemaParseExtension(ctxt, schema, child);
3137 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003138 }
3139 type->subtypes = subtype;
3140 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003141 xmlSchemaPErr2(ctxt, node, child,
3142 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3143 "ComplexContent %s has unexpected content\n",
3144 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003145 }
3146 return (type);
3147}
3148
3149/**
3150 * xmlSchemaParseComplexType:
3151 * @ctxt: a schema validation context
3152 * @schema: the schema being built
3153 * @node: a subtree containing XML Schema informations
3154 *
3155 * parse a XML schema Complex Type definition
3156 * *WARNING* this interface is highly subject to change
3157 *
3158 * Returns the type definition or NULL in case of error
3159 */
3160static xmlSchemaTypePtr
3161xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3162 xmlNodePtr node)
3163{
3164 xmlSchemaTypePtr type, subtype;
3165 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003166 const xmlChar *name;
3167 const xmlChar *oldcontainer;
3168 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003169
3170 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3171 return (NULL);
3172
3173 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003174 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003175 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003176
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003177 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3178 name = (const xmlChar *)buf;
3179 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3180 } else {
3181 const xmlChar *local, *ns;
3182
3183 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3184 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003186 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003187 return (NULL);
3188 }
3189 type->node = node;
3190 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003191 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003192 ctxt->container = name;
3193
3194 child = node->children;
3195 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003196 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3197 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 }
3199 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003200 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3201 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003202 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3204 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003205 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003206 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003207
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003208 if (IS_SCHEMA(child, "all")) {
3209 subtype = xmlSchemaParseAll(ctxt, schema, child);
3210 child = child->next;
3211 } else if (IS_SCHEMA(child, "choice")) {
3212 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3213 child = child->next;
3214 } else if (IS_SCHEMA(child, "sequence")) {
3215 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3216 child = child->next;
3217 } else if (IS_SCHEMA(child, "group")) {
3218 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3219 child = child->next;
3220 }
3221 if (subtype != NULL)
3222 type->subtypes = subtype;
3223 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003224 }
3225 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003226 xmlSchemaPErr2(ctxt, node, child,
3227 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3228 "ComplexType %s has unexpected content\n",
3229 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003230 }
3231 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003232 return (type);
3233}
3234
3235
3236/**
3237 * xmlSchemaParseSchema:
3238 * @ctxt: a schema validation context
3239 * @node: a subtree containing XML Schema informations
3240 *
3241 * parse a XML schema definition from a node set
3242 * *WARNING* this interface is highly subject to change
3243 *
3244 * Returns the internal XML Schema structure built from the resource or
3245 * NULL in case of error
3246 */
3247static xmlSchemaPtr
3248xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3249{
3250 xmlSchemaPtr schema = NULL;
3251 xmlSchemaAnnotPtr annot;
3252 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003253 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003254 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003255
3256 if ((ctxt == NULL) || (node == NULL))
3257 return (NULL);
3258
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003259 nberrors = ctxt->nberrors;
3260 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003261 if (IS_SCHEMA(node, "schema")) {
3262 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003263 if (schema == NULL)
3264 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003265 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3266 if (val != NULL) {
3267 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3268 } else {
3269 schema->targetNamespace = NULL;
3270 }
3271 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3272 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3273 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003274 if (val != NULL) {
3275 if (xmlStrEqual(val, BAD_CAST "qualified"))
3276 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3277 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3278 xmlSchemaPErr2(ctxt, node, child,
3279 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3280 "Invalid value %s for elementFormDefault\n",
3281 val, NULL);
3282 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003283 } else {
3284 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3285 }
3286 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003287 if (val != NULL) {
3288 if (xmlStrEqual(val, BAD_CAST "qualified"))
3289 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3290 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3291 xmlSchemaPErr2(ctxt, node, child,
3292 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3293 "Invalid value %s for attributeFormDefault\n",
3294 val, NULL);
3295 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003296 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003297
3298 child = node->children;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003299 while ((IS_SCHEMA(child, "include")) ||
3300 (IS_SCHEMA(child, "import")) ||
3301 (IS_SCHEMA(child, "redefine")) ||
3302 (IS_SCHEMA(child, "annotation"))) {
3303 if (IS_SCHEMA(child, "annotation")) {
3304 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3305 if (schema->annot == NULL)
3306 schema->annot = annot;
3307 else
3308 xmlSchemaFreeAnnot(annot);
3309 } else if (IS_SCHEMA(child, "include")) {
3310 TODO} else if (IS_SCHEMA(child, "import")) {
3311 xmlSchemaParseImport(ctxt, schema, child);
3312 } else if (IS_SCHEMA(child, "redefine")) {
3313 TODO}
3314 child = child->next;
3315 }
3316 while (child != NULL) {
3317 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003318 xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003319 child = child->next;
3320 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003321 xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003322 child = child->next;
3323 } else if (IS_SCHEMA(child, "element")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003324 xmlSchemaParseElement(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003325 child = child->next;
3326 } else if (IS_SCHEMA(child, "attribute")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003327 xmlSchemaParseAttribute(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003328 child = child->next;
3329 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003330 xmlSchemaParseAttributeGroup(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003331 child = child->next;
3332 } else if (IS_SCHEMA(child, "group")) {
3333 xmlSchemaParseGroup(ctxt, schema, child);
3334 child = child->next;
3335 } else if (IS_SCHEMA(child, "notation")) {
3336 xmlSchemaParseNotation(ctxt, schema, child);
3337 child = child->next;
3338 } else {
3339 xmlSchemaPErr2(ctxt, node, child,
3340 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3341 "Schemas: unexpected element %s here \n",
3342 child->name, NULL);
3343 child = child->next;
3344 }
3345 while (IS_SCHEMA(child, "annotation")) {
3346 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3347 if (schema->annot == NULL)
3348 schema->annot = annot;
3349 else
3350 xmlSchemaFreeAnnot(annot);
3351 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003352 }
3353 }
3354 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003355 if (ctxt->nberrors != 0) {
3356 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003357 xmlSchemaFree(schema);
3358 schema = NULL;
3359 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003360 }
3361 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003362#ifdef DEBUG
3363 if (schema == NULL)
3364 xmlGenericError(xmlGenericErrorContext,
3365 "xmlSchemaParse() failed\n");
3366#endif
3367
3368 return (schema);
3369}
3370
3371/************************************************************************
3372 * *
3373 * Validating using Schemas *
3374 * *
3375 ************************************************************************/
3376
3377/************************************************************************
3378 * *
3379 * Reading/Writing Schemas *
3380 * *
3381 ************************************************************************/
3382
3383/**
3384 * xmlSchemaNewParserCtxt:
3385 * @URL: the location of the schema
3386 *
3387 * Create an XML Schemas parse context for that file/resource expected
3388 * to contain an XML Schemas file.
3389 *
3390 * Returns the parser context or NULL in case of error
3391 */
3392xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003393xmlSchemaNewParserCtxt(const char *URL)
3394{
Daniel Veillard4255d502002-04-16 15:50:10 +00003395 xmlSchemaParserCtxtPtr ret;
3396
3397 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003398 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003399
3400 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3401 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3403 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003404 return (NULL);
3405 }
3406 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003407 ret->dict = xmlDictCreate();
3408 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003409 return (ret);
3410}
3411
3412/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003413 * xmlSchemaNewMemParserCtxt:
3414 * @buffer: a pointer to a char array containing the schemas
3415 * @size: the size of the array
3416 *
3417 * Create an XML Schemas parse context for that memory buffer expected
3418 * to contain an XML Schemas file.
3419 *
3420 * Returns the parser context or NULL in case of error
3421 */
3422xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3424{
Daniel Veillard6045c902002-10-09 21:13:59 +00003425 xmlSchemaParserCtxtPtr ret;
3426
3427 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003428 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003429
3430 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3431 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003432 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3433 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003434 return (NULL);
3435 }
3436 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3437 ret->buffer = buffer;
3438 ret->size = size;
3439 return (ret);
3440}
3441
3442/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003443 * xmlSchemaNewDocParserCtxt:
3444 * @doc: a preparsed document tree
3445 *
3446 * Create an XML Schemas parse context for that document.
3447 * NB. The document may be modified during the parsing process.
3448 *
3449 * Returns the parser context or NULL in case of error
3450 */
3451xmlSchemaParserCtxtPtr
3452xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3453{
3454 xmlSchemaParserCtxtPtr ret;
3455
3456 if (doc == NULL)
3457 return (NULL);
3458
3459 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3460 if (ret == NULL) {
3461 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3462 NULL);
3463 return (NULL);
3464 }
3465 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3466 ret->doc = doc;
3467
3468 return (ret);
3469}
3470
3471/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003472 * xmlSchemaFreeParserCtxt:
3473 * @ctxt: the schema parser context
3474 *
3475 * Free the resources associated to the schema parser context
3476 */
3477void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003478xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3479{
Daniel Veillard4255d502002-04-16 15:50:10 +00003480 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003481 return;
Daniel Veillard6045c902002-10-09 21:13:59 +00003482 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003483 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003484 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003485 xmlFree(ctxt);
3486}
3487
3488/************************************************************************
3489 * *
3490 * Building the content models *
3491 * *
3492 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003493
Daniel Veillard4255d502002-04-16 15:50:10 +00003494/**
3495 * xmlSchemaBuildAContentModel:
3496 * @type: the schema type definition
3497 * @ctxt: the schema parser context
3498 * @name: the element name whose content is being built
3499 *
3500 * Generate the automata sequence needed for that type
3501 */
3502static void
3503xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003504 xmlSchemaParserCtxtPtr ctxt,
3505 const xmlChar * name)
3506{
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003508 xmlGenericError(xmlGenericErrorContext,
3509 "Found unexpected type = NULL in %s content model\n",
3510 name);
3511 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003512 }
3513 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003514 case XML_SCHEMA_TYPE_ANY:
3515 /* TODO : handle the namespace too */
3516 /* TODO : make that a specific transition type */
3517 TODO ctxt->state =
3518 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3519 BAD_CAST "*", NULL);
3520 break;
3521 case XML_SCHEMA_TYPE_ELEMENT:{
3522 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003523
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003524 /* TODO : handle the namespace too */
3525 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003526
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003527 if (elem->maxOccurs >= UNBOUNDED) {
3528 if (elem->minOccurs > 1) {
3529 xmlAutomataStatePtr tmp;
3530 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003531
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003532 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3533 oldstate,
3534 NULL);
3535 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003536
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 counter = xmlAutomataNewCounter(ctxt->am,
3538 elem->minOccurs -
3539 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003540
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003541 if (elem->refDecl != NULL) {
3542 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3543 elem->refDecl,
3544 ctxt,
3545 elem->refDecl->
3546 name);
3547 } else {
3548 ctxt->state =
3549 xmlAutomataNewTransition(ctxt->am,
3550 ctxt->state, NULL,
3551 elem->name, type);
3552 }
3553 tmp = ctxt->state;
3554 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3555 counter);
3556 ctxt->state =
3557 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3558 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003559
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003560 } else {
3561 if (elem->refDecl != NULL) {
3562 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3563 elem->refDecl,
3564 ctxt,
3565 elem->refDecl->
3566 name);
3567 } else {
3568 ctxt->state =
3569 xmlAutomataNewTransition(ctxt->am,
3570 ctxt->state, NULL,
3571 elem->name, type);
3572 }
3573 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3574 oldstate);
3575 if (elem->minOccurs == 0) {
3576 /* basically an elem* */
3577 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3578 ctxt->state);
3579 }
3580 }
3581 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3582 xmlAutomataStatePtr tmp;
3583 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003584
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003585 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3586 oldstate, NULL);
3587 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003588
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003589 counter = xmlAutomataNewCounter(ctxt->am,
3590 elem->minOccurs - 1,
3591 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003592
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003593 if (elem->refDecl != NULL) {
3594 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3595 elem->refDecl, ctxt,
3596 elem->refDecl->name);
3597 } else {
3598 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3599 ctxt->state,
3600 NULL,
3601 elem->name,
3602 type);
3603 }
3604 tmp = ctxt->state;
3605 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3606 counter);
3607 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3608 NULL,
3609 counter);
3610 if (elem->minOccurs == 0) {
3611 /* basically an elem? */
3612 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3613 ctxt->state);
3614 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003615
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003616 } else {
3617 if (elem->refDecl != NULL) {
3618 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3619 elem->refDecl, ctxt,
3620 elem->refDecl->name);
3621 } else {
3622 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3623 ctxt->state,
3624 NULL,
3625 elem->name,
3626 type);
3627 }
3628 if (elem->minOccurs == 0) {
3629 /* basically an elem? */
3630 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3631 ctxt->state);
3632 }
3633 }
3634 break;
3635 }
3636 case XML_SCHEMA_TYPE_SEQUENCE:{
3637 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003638
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003639 /*
3640 * If max and min occurances are default (1) then
3641 * simply iterate over the subtypes
3642 */
3643 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
3644 subtypes = type->subtypes;
3645 while (subtypes != NULL) {
3646 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3647 subtypes = subtypes->next;
3648 }
3649 } else {
3650 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003651
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003652 if (type->maxOccurs >= UNBOUNDED) {
3653 if (type->minOccurs > 1) {
3654 xmlAutomataStatePtr tmp;
3655 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003656
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3658 oldstate,
3659 NULL);
3660 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003661
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 counter = xmlAutomataNewCounter(ctxt->am,
3663 type->
3664 minOccurs - 1,
3665 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003666
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003667 subtypes = type->subtypes;
3668 while (subtypes != NULL) {
3669 xmlSchemaBuildAContentModel(subtypes, ctxt,
3670 name);
3671 subtypes = subtypes->next;
3672 }
3673 tmp = ctxt->state;
3674 xmlAutomataNewCountedTrans(ctxt->am, tmp,
3675 oldstate, counter);
3676 ctxt->state =
3677 xmlAutomataNewCounterTrans(ctxt->am, tmp,
3678 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003679
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003680 } else {
3681 subtypes = type->subtypes;
3682 while (subtypes != NULL) {
3683 xmlSchemaBuildAContentModel(subtypes, ctxt,
3684 name);
3685 subtypes = subtypes->next;
3686 }
3687 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3688 oldstate);
3689 if (type->minOccurs == 0) {
3690 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3691 ctxt->state);
3692 }
3693 }
3694 } else if ((type->maxOccurs > 1)
3695 || (type->minOccurs > 1)) {
3696 xmlAutomataStatePtr tmp;
3697 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003698
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003699 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3700 oldstate,
3701 NULL);
3702 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00003703
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003704 counter = xmlAutomataNewCounter(ctxt->am,
3705 type->minOccurs -
3706 1,
3707 type->maxOccurs -
3708 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003709
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003710 subtypes = type->subtypes;
3711 while (subtypes != NULL) {
3712 xmlSchemaBuildAContentModel(subtypes, ctxt,
3713 name);
3714 subtypes = subtypes->next;
3715 }
3716 tmp = ctxt->state;
3717 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3718 counter);
3719 ctxt->state =
3720 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3721 counter);
3722 if (type->minOccurs == 0) {
3723 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3724 ctxt->state);
3725 }
Daniel Veillardb509f152002-04-17 16:28:10 +00003726
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003727 } else {
3728 subtypes = type->subtypes;
3729 while (subtypes != NULL) {
3730 xmlSchemaBuildAContentModel(subtypes, ctxt,
3731 name);
3732 subtypes = subtypes->next;
3733 }
3734 if (type->minOccurs == 0) {
3735 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3736 ctxt->state);
3737 }
3738 }
3739 }
3740 break;
3741 }
3742 case XML_SCHEMA_TYPE_CHOICE:{
3743 xmlSchemaTypePtr subtypes;
3744 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00003745
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003746 start = ctxt->state;
3747 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00003748
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003749 /*
3750 * iterate over the subtypes and remerge the end with an
3751 * epsilon transition
3752 */
3753 if (type->maxOccurs == 1) {
3754 subtypes = type->subtypes;
3755 while (subtypes != NULL) {
3756 ctxt->state = start;
3757 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3758 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3759 subtypes = subtypes->next;
3760 }
3761 } else {
3762 int counter;
3763 xmlAutomataStatePtr hop;
3764 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3765 UNBOUNDED : type->maxOccurs - 1;
3766 int minOccurs =
3767 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00003768
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003769 /*
3770 * use a counter to keep track of the number of transtions
3771 * which went through the choice.
3772 */
3773 counter =
3774 xmlAutomataNewCounter(ctxt->am, minOccurs,
3775 maxOccurs);
3776 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00003777
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003778 subtypes = type->subtypes;
3779 while (subtypes != NULL) {
3780 ctxt->state = start;
3781 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3782 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3783 subtypes = subtypes->next;
3784 }
3785 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
3786 counter);
3787 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
3788 counter);
3789 }
3790 if (type->minOccurs == 0) {
3791 xmlAutomataNewEpsilon(ctxt->am, start, end);
3792 }
3793 ctxt->state = end;
3794 break;
3795 }
3796 case XML_SCHEMA_TYPE_ALL:{
3797 xmlAutomataStatePtr start;
3798 xmlSchemaTypePtr subtypes;
3799 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3800 int lax;
3801
3802 subtypes = type->subtypes;
3803 if (subtypes == NULL)
3804 break;
3805 start = ctxt->state;
3806 while (subtypes != NULL) {
3807 ctxt->state = start;
3808 elem = (xmlSchemaElementPtr) subtypes;
3809
3810 /* TODO : handle the namespace too */
3811 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3812 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
3813 ctxt->state, elem->name, 1,
3814 1, subtypes);
3815 } else {
3816 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
3817 ctxt->state, elem->name,
3818 elem->minOccurs,
3819 elem->maxOccurs,
3820 subtypes);
3821 }
3822 subtypes = subtypes->next;
3823 }
3824 lax = type->minOccurs == 0;
3825 ctxt->state =
3826 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3827 lax);
3828 break;
3829 }
3830 case XML_SCHEMA_TYPE_RESTRICTION:
3831 if (type->subtypes != NULL)
3832 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3833 break;
3834 case XML_SCHEMA_TYPE_EXTENSION:
3835 if (type->baseType != NULL) {
3836 xmlSchemaTypePtr subtypes;
3837
3838 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3839 subtypes = type->subtypes;
3840 while (subtypes != NULL) {
3841 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3842 subtypes = subtypes->next;
3843 }
3844 } else if (type->subtypes != NULL)
3845 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3846 break;
3847 case XML_SCHEMA_TYPE_GROUP:
3848 if (type->subtypes == NULL) {
3849 }
3850 case XML_SCHEMA_TYPE_COMPLEX:
3851 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3852 if (type->subtypes != NULL)
3853 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3854 break;
3855 default:
3856 xmlGenericError(xmlGenericErrorContext,
3857 "Found unexpected type %d in %s content model\n",
3858 type->type, name);
3859 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003860 }
3861}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003862
Daniel Veillard4255d502002-04-16 15:50:10 +00003863/**
3864 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003865 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00003866 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003867 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00003868 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003869 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 */
3871static void
3872xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003873 xmlSchemaParserCtxtPtr ctxt,
3874 const xmlChar * name)
3875{
Daniel Veillard4255d502002-04-16 15:50:10 +00003876 xmlAutomataStatePtr start;
3877
Daniel Veillard4255d502002-04-16 15:50:10 +00003878 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003879 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003880 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003881 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3882 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003883 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003884 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003885 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
3887 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003888 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003889
3890#ifdef DEBUG_CONTENT
3891 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003892 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003893#endif
3894
Daniel Veillard4255d502002-04-16 15:50:10 +00003895 ctxt->am = xmlNewAutomata();
3896 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003897 xmlGenericError(xmlGenericErrorContext,
3898 "Cannot create automata for elem %s\n", name);
3899 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003900 }
3901 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3902 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3903 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00003904 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003905 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003906 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
3907 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003908 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003909 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
3910 "Content model of %s is not determinist:\n", name,
3911 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003912 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00003913#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003914 xmlGenericError(xmlGenericErrorContext,
3915 "Content model of %s:\n", name);
3916 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003917#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003918 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003919 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003920 xmlFreeAutomata(ctxt->am);
3921 ctxt->am = NULL;
3922}
3923
3924/**
3925 * xmlSchemaRefFixupCallback:
3926 * @elem: the schema element context
3927 * @ctxt: the schema parser context
3928 *
3929 * Free the resources associated to the schema parser context
3930 */
3931static void
3932xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003933 xmlSchemaParserCtxtPtr ctxt,
3934 const xmlChar * name,
3935 const xmlChar * context ATTRIBUTE_UNUSED,
3936 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003937{
3938 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003939 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003940 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003941 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003942
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003943 if (elem->subtypes != NULL) {
3944 xmlSchemaPErr(ctxt, elem->node,
3945 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
3946 "Schemas: element %s have both ref and subtype\n",
3947 name, NULL);
3948 return;
3949 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003950 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003951
3952 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003953 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
3954 "Schemas: element %s ref to %s not found\n",
3955 name, elem->ref);
3956 return;
3957 }
3958 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003959 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003960 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003961
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003962 if (elem->subtypes != NULL) {
3963 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
3964 "Schemas: element %s have both type and subtype\n",
3965 name, NULL);
3966 return;
3967 }
3968 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3969 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003970
3971 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003972 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
3973 "Schemas: element %s type %s not found\n", name,
3974 elem->namedType);
3975 return;
3976 }
3977 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003978 }
3979}
3980
3981/**
3982 * xmlSchemaTypeFixup:
3983 * @typeDecl: the schema type definition
3984 * @ctxt: the schema parser context
3985 *
3986 * Fixes the content model of the type.
3987 */
3988static void
3989xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003990 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003991{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00003992 if (typeDecl == NULL)
3993 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003994 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003995 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003996 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003997 switch (typeDecl->type) {
3998 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
3999 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4000 if (typeDecl->subtypes != NULL)
4001 typeDecl->contentType =
4002 typeDecl->subtypes->contentType;
4003 break;
4004 }
4005 case XML_SCHEMA_TYPE_RESTRICTION:{
4006 if (typeDecl->subtypes != NULL)
4007 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004008
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004009 if (typeDecl->base != NULL) {
4010 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004011
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004012 baseType =
4013 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4014 typeDecl->baseNs);
4015 if (baseType == NULL) {
4016 xmlSchemaPErr(ctxt, typeDecl->node,
4017 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004018 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 name, typeDecl->base);
4020 }
4021 typeDecl->baseType = baseType;
4022 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004023 if (typeDecl->subtypes == NULL)
4024 if (typeDecl->baseType != NULL)
4025 typeDecl->contentType =
4026 typeDecl->baseType->contentType;
4027 else
4028 /* 1.1.1 */
4029 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004030 else if ((typeDecl->subtypes->subtypes == NULL) &&
4031 ((typeDecl->subtypes->type ==
4032 XML_SCHEMA_TYPE_ALL)
4033 || (typeDecl->subtypes->type ==
4034 XML_SCHEMA_TYPE_SEQUENCE)))
4035 /* 1.1.2 */
4036 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4037 else if ((typeDecl->subtypes->type ==
4038 XML_SCHEMA_TYPE_CHOICE)
4039 && (typeDecl->subtypes->subtypes == NULL))
4040 /* 1.1.3 */
4041 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4042 else {
4043 /* 1.2 and 2.X are applied at the other layer */
4044 typeDecl->contentType =
4045 XML_SCHEMA_CONTENT_ELEMENTS;
4046 }
4047 break;
4048 }
4049 case XML_SCHEMA_TYPE_EXTENSION:{
4050 xmlSchemaContentType explicitContentType;
4051 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004052
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004053 if (typeDecl->base != NULL) {
4054 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004055
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056 baseType =
4057 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4058 typeDecl->baseNs);
4059 if (baseType == NULL) {
4060 xmlSchemaPErr(ctxt, typeDecl->node,
4061 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004062 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004063 name, typeDecl->base);
4064 }
4065 typeDecl->baseType = baseType;
4066 }
4067 if (typeDecl->subtypes != NULL)
4068 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004069
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4071 if (typeDecl->subtypes == NULL)
4072 /* 1.1.1 */
4073 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4074 else if ((typeDecl->subtypes->subtypes == NULL) &&
4075 ((typeDecl->subtypes->type ==
4076 XML_SCHEMA_TYPE_ALL)
4077 || (typeDecl->subtypes->type ==
4078 XML_SCHEMA_TYPE_SEQUENCE)))
4079 /* 1.1.2 */
4080 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4081 else if ((typeDecl->subtypes->type ==
4082 XML_SCHEMA_TYPE_CHOICE)
4083 && (typeDecl->subtypes->subtypes == NULL))
4084 /* 1.1.3 */
4085 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004086
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004087 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4088 typeDecl->baseNs);
4089 if (base == NULL) {
4090 xmlSchemaPErr(ctxt, typeDecl->node,
4091 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4092 "Schemas: base type %s of type %s not found\n",
4093 typeDecl->base, name);
4094 return;
4095 }
4096 xmlSchemaTypeFixup(base, ctxt, NULL);
4097 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4098 /* 2.1 */
4099 typeDecl->contentType = base->contentType;
4100 } else if (base->contentType ==
4101 XML_SCHEMA_CONTENT_EMPTY) {
4102 /* 2.2 imbitable ! */
4103 typeDecl->contentType =
4104 XML_SCHEMA_CONTENT_ELEMENTS;
4105 } else {
4106 /* 2.3 imbitable pareil ! */
4107 typeDecl->contentType =
4108 XML_SCHEMA_CONTENT_ELEMENTS;
4109 }
4110 break;
4111 }
4112 case XML_SCHEMA_TYPE_COMPLEX:{
4113 if (typeDecl->subtypes == NULL) {
4114 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4115 } else {
4116 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4117 typeDecl->contentType =
4118 XML_SCHEMA_CONTENT_MIXED;
4119 else {
4120 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4121 NULL);
4122 if (typeDecl->subtypes != NULL)
4123 typeDecl->contentType =
4124 typeDecl->subtypes->contentType;
4125 }
4126 }
4127 break;
4128 }
4129 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4130 if (typeDecl->subtypes == NULL) {
4131 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4132 } else {
4133 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4134 typeDecl->contentType =
4135 XML_SCHEMA_CONTENT_MIXED;
4136 else {
4137 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4138 NULL);
4139 if (typeDecl->subtypes != NULL)
4140 typeDecl->contentType =
4141 typeDecl->subtypes->contentType;
4142 }
4143 }
4144 break;
4145 }
4146 case XML_SCHEMA_TYPE_SEQUENCE:
4147 case XML_SCHEMA_TYPE_GROUP:
4148 case XML_SCHEMA_TYPE_ALL:
4149 case XML_SCHEMA_TYPE_CHOICE:
4150 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4151 break;
4152 case XML_SCHEMA_TYPE_BASIC:
4153 case XML_SCHEMA_TYPE_ANY:
4154 case XML_SCHEMA_TYPE_FACET:
4155 case XML_SCHEMA_TYPE_SIMPLE:
4156 case XML_SCHEMA_TYPE_UR:
4157 case XML_SCHEMA_TYPE_ELEMENT:
4158 case XML_SCHEMA_TYPE_ATTRIBUTE:
4159 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4160 case XML_SCHEMA_TYPE_NOTATION:
4161 case XML_SCHEMA_TYPE_LIST:
4162 case XML_SCHEMA_TYPE_UNION:
4163 case XML_SCHEMA_FACET_MININCLUSIVE:
4164 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4165 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4166 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4167 case XML_SCHEMA_FACET_TOTALDIGITS:
4168 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4169 case XML_SCHEMA_FACET_PATTERN:
4170 case XML_SCHEMA_FACET_ENUMERATION:
4171 case XML_SCHEMA_FACET_WHITESPACE:
4172 case XML_SCHEMA_FACET_LENGTH:
4173 case XML_SCHEMA_FACET_MAXLENGTH:
4174 case XML_SCHEMA_FACET_MINLENGTH:
4175 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004176 if (typeDecl->subtypes != NULL)
4177 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004178 break;
4179 }
4180 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004181#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004182 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004183 xmlGenericError(xmlGenericErrorContext,
4184 "Type of %s : %s:%d :", name,
4185 typeDecl->node->doc->URL,
4186 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004187 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004188 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004189 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004190 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004191 case XML_SCHEMA_CONTENT_SIMPLE:
4192 xmlGenericError(xmlGenericErrorContext, "simple\n");
4193 break;
4194 case XML_SCHEMA_CONTENT_ELEMENTS:
4195 xmlGenericError(xmlGenericErrorContext, "elements\n");
4196 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004197 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004198 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4199 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004200 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004201 xmlGenericError(xmlGenericErrorContext, "empty\n");
4202 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004203 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004204 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4205 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004206 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004207 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4208 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004209 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004210 xmlGenericError(xmlGenericErrorContext, "basic\n");
4211 break;
4212 default:
4213 xmlGenericError(xmlGenericErrorContext,
4214 "not registered !!!\n");
4215 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004216 }
4217#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004218}
4219
4220/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004221 * xmlSchemaCheckFacet:
4222 * @facet: the facet
4223 * @typeDecl: the schema type definition
4224 * @ctxt: the schema parser context or NULL
4225 * @name: name of the type
4226 *
4227 * Checks the default values types, especially for facets
4228 *
4229 * Returns 0 if okay or -1 in cae of error
4230 */
4231int
4232xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004233 xmlSchemaTypePtr typeDecl,
4234 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004235{
4236 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4237 int ret = 0;
4238
4239 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004240 nonNegativeIntegerType =
4241 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4242 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004243 }
4244 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004245 case XML_SCHEMA_FACET_MININCLUSIVE:
4246 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4247 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4248 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4249 /*
4250 * Okay we need to validate the value
4251 * at that point.
4252 */
4253 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004254
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004255 vctxt = xmlSchemaNewValidCtxt(NULL);
4256 if (vctxt == NULL)
4257 break;
4258 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4259 facet->value);
4260 facet->val = vctxt->value;
4261 vctxt->value = NULL;
4262 if (facet->val == NULL) {
4263 /* error code */
4264 if (ctxt != NULL) {
4265 xmlSchemaPErr(ctxt, facet->node,
4266 XML_SCHEMAP_INVALID_FACET,
4267 "Schemas: type %s facet value %s invalid\n",
4268 name, facet->value);
4269 }
4270 ret = -1;
4271 }
4272 xmlSchemaFreeValidCtxt(vctxt);
4273 break;
4274 }
4275 case XML_SCHEMA_FACET_ENUMERATION:{
4276 /*
4277 * Okay we need to validate the value
4278 * at that point.
4279 */
4280 xmlSchemaValidCtxtPtr vctxt;
4281 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004282
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004283 vctxt = xmlSchemaNewValidCtxt(NULL);
4284 if (vctxt == NULL)
4285 break;
4286 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4287 facet->value);
4288 if (tmp != 0) {
4289 if (ctxt != NULL) {
4290 xmlSchemaPErr(ctxt, facet->node,
4291 XML_SCHEMAP_INVALID_ENUM,
4292 "Schemas: type %s enumeration value %s invalid\n",
4293 name, facet->value);
4294 }
4295 ret = -1;
4296 }
4297 xmlSchemaFreeValidCtxt(vctxt);
4298 break;
4299 }
4300 case XML_SCHEMA_FACET_PATTERN:
4301 facet->regexp = xmlRegexpCompile(facet->value);
4302 if (facet->regexp == NULL) {
4303 xmlSchemaPErr(ctxt, typeDecl->node,
4304 XML_SCHEMAP_REGEXP_INVALID,
4305 "Schemas: type %s facet regexp %s invalid\n",
4306 name, facet->value);
4307 ret = -1;
4308 }
4309 break;
4310 case XML_SCHEMA_FACET_TOTALDIGITS:
4311 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4312 case XML_SCHEMA_FACET_LENGTH:
4313 case XML_SCHEMA_FACET_MAXLENGTH:
4314 case XML_SCHEMA_FACET_MINLENGTH:{
4315 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004316
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 tmp =
4318 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4319 facet->value,
4320 &facet->val);
4321 if (tmp != 0) {
4322 /* error code */
4323 if (ctxt != NULL) {
4324 xmlSchemaPErr(ctxt, facet->node,
4325 XML_SCHEMAP_INVALID_FACET_VALUE,
4326 "Schemas: type %s facet value %s invalid\n",
4327 name, facet->value);
4328 }
4329 ret = -1;
4330 }
4331 break;
4332 }
4333 case XML_SCHEMA_FACET_WHITESPACE:{
4334 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4335 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4336 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4337 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4338 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4339 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4340 } else {
4341 if (ctxt != NULL) {
4342 xmlSchemaPErr(ctxt, facet->node,
4343 XML_SCHEMAP_INVALID_WHITE_SPACE,
4344 "Schemas: type %s whiteSpace value %s invalid\n",
4345 name, facet->value);
4346 }
4347 ret = -1;
4348 }
4349 }
4350 default:
4351 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004352 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004353 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004354}
4355
4356/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004357 * xmlSchemaCheckDefaults:
4358 * @typeDecl: the schema type definition
4359 * @ctxt: the schema parser context
4360 *
4361 * Checks the default values types, especially for facets
4362 */
4363static void
4364xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004365 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004366{
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004368 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004370 if (typeDecl->facets != NULL) {
4371 xmlSchemaFacetPtr facet = typeDecl->facets;
4372
4373 while (facet != NULL) {
4374 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4375 facet = facet->next;
4376 }
4377 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 }
4379}
4380
4381/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004382 * xmlSchemaAttrGrpFixup:
4383 * @attrgrpDecl: the schema attribute definition
4384 * @ctxt: the schema parser context
4385 * @name: the attribute name
4386 *
4387 * Fixes finish doing the computations on the attributes definitions
4388 */
4389static void
4390xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004391 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004392{
4393 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004395 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004397 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004399
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004400 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4401 attrgrpDecl->refNs);
4402 if (ref == NULL) {
4403 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4404 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4405 "Schemas: attribute group %s reference %s not found\n",
4406 name, attrgrpDecl->ref);
4407 return;
4408 }
4409 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4410 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004411 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004412 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4413 "Schemas: attribute %s has no attributes nor reference\n",
4414 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004415 }
4416}
4417
4418/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004419 * xmlSchemaAttrFixup:
4420 * @attrDecl: the schema attribute definition
4421 * @ctxt: the schema parser context
4422 * @name: the attribute name
4423 *
4424 * Fixes finish doing the computations on the attributes definitions
4425 */
4426static void
4427xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004428 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004429{
4430 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004431 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004433 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4438 attrDecl->typeNs);
4439 if (type == NULL) {
4440 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4441 "Schemas: attribute %s type %s not found\n",
4442 name, attrDecl->typeName);
4443 }
4444 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004445 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004447
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4449 attrDecl->refNs);
4450 if (ref == NULL) {
4451 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4452 "Schemas: attribute %s reference %s not found\n",
4453 name, attrDecl->ref);
4454 return;
4455 }
4456 xmlSchemaAttrFixup(ref, ctxt, NULL);
4457 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004459 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4460 "Schemas: attribute %s has no type nor reference\n",
4461 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004462 }
4463}
4464
4465/**
4466 * xmlSchemaParse:
4467 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004469 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 * XML Shema struture which can be used to validate instances.
4471 * *WARNING* this interface is highly subject to change
4472 *
4473 * Returns the internal XML Schema structure built from the resource or
4474 * NULL in case of error
4475 */
4476xmlSchemaPtr
4477xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4478{
4479 xmlSchemaPtr ret = NULL;
4480 xmlDocPtr doc;
4481 xmlNodePtr root, cur, delete;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004482 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004483
4484 xmlSchemaInitTypes();
4485
Daniel Veillard6045c902002-10-09 21:13:59 +00004486 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004487 return (NULL);
4488
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004489 nberrors = ctxt->nberrors;
4490 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004491 ctxt->counter = 0;
4492 ctxt->container = NULL;
4493
4494 /*
4495 * First step is to parse the input document into an DOM/Infoset
4496 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004497 if (ctxt->URL != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004498 doc = xmlParseFile((const char *) ctxt->URL);
4499 if (doc == NULL) {
4500 xmlSchemaPErr(ctxt, NULL,
4501 XML_SCHEMAP_FAILED_LOAD,
4502 "xmlSchemaParse: could not load %s\n",
4503 ctxt->URL, NULL);
4504 return (NULL);
4505 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004506 } else if (ctxt->buffer != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004507 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4508 if (doc == NULL) {
4509 xmlSchemaPErr(ctxt, NULL,
4510 XML_SCHEMAP_FAILED_PARSE,
4511 "xmlSchemaParse: could not parse\n",
4512 NULL, NULL);
4513 return (NULL);
4514 }
4515 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4516 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard9d751502003-10-29 13:21:47 +00004517 } else if (ctxt->doc != NULL) {
4518 doc = ctxt->doc;
Daniel Veillard6045c902002-10-09 21:13:59 +00004519 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 xmlSchemaPErr(ctxt, NULL,
4521 XML_SCHEMAP_NOTHING_TO_PARSE,
4522 "xmlSchemaParse: could not parse\n",
4523 NULL, NULL);
4524 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004525 }
4526
4527 /*
4528 * Then extract the root and Schema parse it
4529 */
4530 root = xmlDocGetRootElement(doc);
4531 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004532 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4533 XML_SCHEMAP_NOROOT,
4534 "schemas has no root", NULL, NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004535 xmlFreeDoc(doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00004536 return (NULL);
4537 }
4538
4539 /*
4540 * Remove all the blank text nodes
4541 */
4542 delete = NULL;
4543 cur = root;
4544 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004545 if (delete != NULL) {
4546 xmlUnlinkNode(delete);
4547 xmlFreeNode(delete);
4548 delete = NULL;
4549 }
4550 if (cur->type == XML_TEXT_NODE) {
4551 if (IS_BLANK_NODE(cur)) {
4552 if (xmlNodeGetSpacePreserve(cur) != 1) {
4553 delete = cur;
4554 }
4555 }
4556 } else if ((cur->type != XML_ELEMENT_NODE) &&
4557 (cur->type != XML_CDATA_SECTION_NODE)) {
4558 delete = cur;
4559 goto skip_children;
4560 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004561
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004562 /*
4563 * Skip to next node
4564 */
4565 if (cur->children != NULL) {
4566 if ((cur->children->type != XML_ENTITY_DECL) &&
4567 (cur->children->type != XML_ENTITY_REF_NODE) &&
4568 (cur->children->type != XML_ENTITY_NODE)) {
4569 cur = cur->children;
4570 continue;
4571 }
4572 }
4573 skip_children:
4574 if (cur->next != NULL) {
4575 cur = cur->next;
4576 continue;
4577 }
4578
4579 do {
4580 cur = cur->parent;
4581 if (cur == NULL)
4582 break;
4583 if (cur == root) {
4584 cur = NULL;
4585 break;
4586 }
4587 if (cur->next != NULL) {
4588 cur = cur->next;
4589 break;
4590 }
4591 } while (cur != NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 }
4593 if (delete != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004594 xmlUnlinkNode(delete);
4595 xmlFreeNode(delete);
4596 delete = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004597 }
4598
4599 /*
4600 * Then do the parsing for good
4601 */
4602 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004603 if (ret == NULL) {
4604 xmlFreeDoc(doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004605 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004606 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004607 ret->doc = doc;
4608
4609 /*
4610 * Then fix all the references.
4611 */
4612 ctxt->schema = ret;
4613 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004614 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004615
4616 /*
4617 * Then fixup all types properties
4618 */
4619 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4620
4621 /*
4622 * Then build the content model for all elements
4623 */
4624 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004626
4627 /*
4628 * Then check the defaults part of the type like facets values
4629 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004630 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4631 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004632
4633 /*
4634 * Then fixup all attributes declarations
4635 */
4636 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4637
Daniel Veillard13e04c62002-04-23 17:51:29 +00004638 /*
4639 * Then fixup all attributes group declarations
4640 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004641 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4642 ctxt);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004643
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004644 if (ctxt->nberrors != 0) {
4645 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004646 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004647 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004648 return (ret);
4649}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650
Daniel Veillard4255d502002-04-16 15:50:10 +00004651/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004652 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004653 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004654 * @err: the error callback
4655 * @warn: the warning callback
4656 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004657 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004658 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004659 */
4660void
4661xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004662 xmlSchemaValidityErrorFunc err,
4663 xmlSchemaValidityWarningFunc warn, void *ctx)
4664{
Daniel Veillard4255d502002-04-16 15:50:10 +00004665 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004666 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004667 ctxt->error = err;
4668 ctxt->warning = warn;
4669 ctxt->userData = ctx;
4670}
4671
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004672/**
4673 * xmlSchemaFacetTypeToString:
4674 * @type: the facet type
4675 *
4676 * Convert the xmlSchemaTypeType to a char string.
4677 *
4678 * Returns the char string representation of the facet type if the
4679 * type is a facet and an "Internal Error" string otherwise.
4680 */
4681static const char *
4682xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4683{
4684 switch (type) {
4685 case XML_SCHEMA_FACET_PATTERN:
4686 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004687 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004688 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004689 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004690 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004691 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004692 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004693 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004694 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004695 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004696 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004697 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004698 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004699 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004700 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004701 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004702 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004703 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004704 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004705 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004706 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004707 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004708 return ("fractionDigits");
4709 default:
4710 break;
4711 }
4712 return ("Internal Error");
4713}
4714
4715/**
4716 * xmlSchemaValidateFacets:
4717 * @ctxt: a schema validation context
4718 * @base: the base type
4719 * @facets: the list of facets to check
4720 * @value: the lexical repr of the value to validate
4721 * @val: the precomputed value
4722 *
4723 * Check a value against all facet conditions
4724 *
4725 * Returns 0 if the element is schemas valid, a positive error code
4726 * number otherwise and -1 in case of internal or API error.
4727 */
4728static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004729xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4730 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004731 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004732{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004733 int ret = 0;
4734 int tmp = 0;
4735 xmlSchemaTypeType type;
4736 xmlSchemaFacetPtr facet = facets;
4737
4738 while (facet != NULL) {
4739 type = facet->type;
4740 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004741 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004742
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004743 while (facet != NULL) {
4744 tmp =
4745 xmlSchemaValidateFacet(base, facet, value,
4746 ctxt->value);
4747 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004748 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004749 }
4750 facet = facet->next;
4751 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004752 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004753 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004754
4755 if (tmp != 0) {
4756 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004757 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 +00004758 }
4759 if (facet != NULL)
4760 facet = facet->next;
4761 }
4762 return (ret);
4763}
4764
Daniel Veillard4255d502002-04-16 15:50:10 +00004765/************************************************************************
4766 * *
4767 * Simple type validation *
4768 * *
4769 ************************************************************************/
4770
4771/**
4772 * xmlSchemaValidateSimpleValue:
4773 * @ctxt: a schema validation context
4774 * @type: the type declaration
4775 * @value: the value to validate
4776 *
4777 * Validate a value against a simple type
4778 *
4779 * Returns 0 if the value is valid, a positive error code
4780 * number otherwise and -1 in case of internal or API error.
4781 */
4782static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004783xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004784 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004785{
Daniel Veillard4255d502002-04-16 15:50:10 +00004786 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004787
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 /*
4789 * First normalize the value accordingly to Schema Datatype
4790 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4791 */
4792 /*
4793 * Then check the normalized value against the lexical space of the
4794 * type.
4795 */
4796 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004797 if (ctxt->value != NULL) {
4798 xmlSchemaFreeValue(ctxt->value);
4799 ctxt->value = NULL;
4800 }
4801 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4802 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004803 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004804 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 +00004805 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004806 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004807 xmlSchemaTypePtr base;
4808 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004809
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004810 base = type->baseType;
4811 if (base != NULL) {
4812 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4813 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004814 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004815 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004816
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 /*
4818 * Do not validate facets when working on building the Schemas
4819 */
4820 if (ctxt->schema != NULL) {
4821 if (ret == 0) {
4822 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004823 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 }
4825 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004826 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004827 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004828
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004829 base = type->subtypes;
4830 if (base != NULL) {
4831 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4832 } else {
4833 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004834 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004835 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004836 const xmlChar *cur, *end;
4837 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004838 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00004839
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004840 base = type->subtypes;
4841 if (base == NULL) {
4842 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
4843 "Internal: List type %s has no base type\n",
4844 type->name, NULL);
4845 return (-1);
4846 }
4847 cur = value;
4848 do {
William M. Brack76e95df2003-10-18 16:20:14 +00004849 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004850 cur++;
4851 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00004852 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004853 end++;
4854 if (end == cur)
4855 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004856 tmp = xmlStrndup(cur, end - cur);
4857 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
4858 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004859 if (ret2 != 0)
4860 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004861 cur = end;
4862 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004863 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004864 TODO
4865 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004866 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004867}
4868
4869/************************************************************************
4870 * *
4871 * DOM Validation code *
4872 * *
4873 ************************************************************************/
4874
4875static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004876 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004877static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004878 xmlNodePtr elem,
4879 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004880static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004881 xmlNodePtr elem,
4882 xmlSchemaElementPtr elemDecl,
4883 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004884
4885/**
4886 * xmlSchemaRegisterAttributes:
4887 * @ctxt: a schema validation context
4888 * @attrs: a list of attributes
4889 *
4890 * Register the list of attributes as the set to be validated on that element
4891 *
4892 * Returns -1 in case of error, 0 otherwise
4893 */
4894static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004895xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
4896{
Daniel Veillard4255d502002-04-16 15:50:10 +00004897 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004898 if ((attrs->ns != NULL) &&
4899 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4900 attrs = attrs->next;
4901 continue;
4902 }
4903 if (ctxt->attrNr >= ctxt->attrMax) {
4904 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00004905
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004906 ctxt->attrMax *= 2;
4907 tmp = (xmlSchemaAttrStatePtr)
4908 xmlRealloc(ctxt->attr, ctxt->attrMax *
4909 sizeof(xmlSchemaAttrState));
4910 if (tmp == NULL) {
4911 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
4912 ctxt->attrMax /= 2;
4913 return (-1);
4914 }
4915 ctxt->attr = tmp;
4916 }
4917 ctxt->attr[ctxt->attrNr].attr = attrs;
4918 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4919 ctxt->attrNr++;
4920 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004921 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004923}
4924
4925/**
4926 * xmlSchemaCheckAttributes:
4927 * @ctxt: a schema validation context
4928 * @node: the node carrying it.
4929 *
4930 * Check that the registered set of attributes on the current node
4931 * has been properly validated.
4932 *
4933 * Returns 0 if validity constraints are met, 1 otherwise.
4934 */
4935static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004936xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4937{
Daniel Veillard4255d502002-04-16 15:50:10 +00004938 int ret = 0;
4939 int i;
4940
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004941 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
4942 if (ctxt->attr[i].attr == NULL)
4943 break;
4944 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4945 ret = 1;
4946 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
4947 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004948 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004949 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004950}
4951
4952/**
4953 * xmlSchemaValidateSimpleContent:
4954 * @ctxt: a schema validation context
4955 * @elem: an element
4956 * @type: the type declaration
4957 *
4958 * Validate the content of an element expected to be a simple type
4959 *
4960 * Returns 0 if the element is schemas valid, a positive error code
4961 * number otherwise and -1 in case of internal or API error.
4962 */
4963static int
4964xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004965 xmlNodePtr node ATTRIBUTE_UNUSED)
4966{
Daniel Veillard4255d502002-04-16 15:50:10 +00004967 xmlNodePtr child;
4968 xmlSchemaTypePtr type, base;
4969 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004970 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004971
4972 child = ctxt->node;
4973 type = ctxt->type;
4974
4975 /*
4976 * Validation Rule: Element Locally Valid (Type): 3.1.3
4977 */
4978 value = xmlNodeGetContent(child);
4979 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4980 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004981 case XML_SCHEMA_TYPE_RESTRICTION:{
4982 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004983
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004984 base = type->baseType;
4985 if (base != NULL) {
4986 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4987 } else {
4988 TODO}
4989 if (ret == 0) {
4990 facet = type->facets;
4991 ret =
4992 xmlSchemaValidateFacets(ctxt, base, facet, value);
4993 }
4994 break;
4995 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004996 case XML_SCHEMA_TYPE_EXTENSION:{
4997 TODO
4998 break;
4999 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005000 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005001 TODO
5002 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005003 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005004 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005005
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005006 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005007}
5008
5009/**
5010 * xmlSchemaValidateCheckNodeList
5011 * @nodelist: the list of nodes
5012 *
5013 * Check the node list is only made of text nodes and entities pointing
5014 * to text nodes
5015 *
5016 * Returns 1 if true, 0 if false and -1 in case of error
5017 */
5018static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005019xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5020{
Daniel Veillard4255d502002-04-16 15:50:10 +00005021 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005022 if (nodelist->type == XML_ENTITY_REF_NODE) {
5023 TODO /* implement recursion in the entity content */
5024 }
5025 if ((nodelist->type != XML_TEXT_NODE) &&
5026 (nodelist->type != XML_COMMENT_NODE) &&
5027 (nodelist->type != XML_PI_NODE) &&
5028 (nodelist->type != XML_PI_NODE)) {
5029 return (0);
5030 }
5031 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005032 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005033 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005034}
5035
5036/**
5037 * xmlSchemaSkipIgnored:
5038 * @ctxt: a schema validation context
5039 * @type: the current type context
5040 * @node: the top node.
5041 *
5042 * Skip ignorable nodes in that context
5043 *
5044 * Returns the new sibling
5045 * number otherwise and -1 in case of internal or API error.
5046 */
5047static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005048xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005049 xmlSchemaTypePtr type, xmlNodePtr node)
5050{
Daniel Veillard4255d502002-04-16 15:50:10 +00005051 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005052
Daniel Veillard4255d502002-04-16 15:50:10 +00005053 /*
5054 * TODO complete and handle entities
5055 */
5056 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005057 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005058 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005059 ((node->type == XML_COMMENT_NODE) ||
5060 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5061 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5062 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5063 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005064 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005065 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005066}
5067
5068/**
5069 * xmlSchemaValidateCallback:
5070 * @ctxt: a schema validation context
5071 * @name: the name of the element detected (might be NULL)
5072 * @type: the type
5073 *
5074 * A transition has been made in the automata associated to an element
5075 * content model
5076 */
5077static void
5078xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005079 const xmlChar * name ATTRIBUTE_UNUSED,
5080 xmlSchemaTypePtr type, xmlNodePtr node)
5081{
Daniel Veillard4255d502002-04-16 15:50:10 +00005082 xmlSchemaTypePtr oldtype = ctxt->type;
5083 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084
Daniel Veillard4255d502002-04-16 15:50:10 +00005085#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005086 xmlGenericError(xmlGenericErrorContext,
5087 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005088 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005089#endif
5090 ctxt->type = type;
5091 ctxt->node = node;
5092 xmlSchemaValidateContent(ctxt, node);
5093 ctxt->type = oldtype;
5094 ctxt->node = oldnode;
5095}
5096
5097
5098#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005099
Daniel Veillard4255d502002-04-16 15:50:10 +00005100/**
5101 * xmlSchemaValidateSimpleRestrictionType:
5102 * @ctxt: a schema validation context
5103 * @node: the top node.
5104 *
5105 * Validate the content of a restriction type.
5106 *
5107 * Returns 0 if the element is schemas valid, a positive error code
5108 * number otherwise and -1 in case of internal or API error.
5109 */
5110static int
5111xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5112 xmlNodePtr node)
5113{
5114 xmlNodePtr child;
5115 xmlSchemaTypePtr type;
5116 int ret;
5117
5118 child = ctxt->node;
5119 type = ctxt->type;
5120
5121 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005122 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005123 return (-1);
5124 }
5125 /*
5126 * Only text and text based entities references shall be found there
5127 */
5128 ret = xmlSchemaValidateCheckNodeList(child);
5129 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005130 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005131 return (-1);
5132 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 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 +00005134 return (-1);
5135 }
5136 ctxt->type = type->subtypes;
5137 xmlSchemaValidateContent(ctxt, node);
5138 ctxt->type = type;
5139 return (ret);
5140}
5141#endif
5142
5143/**
5144 * xmlSchemaValidateSimpleType:
5145 * @ctxt: a schema validation context
5146 * @node: the top node.
5147 *
5148 * Validate the content of an simple type.
5149 *
5150 * Returns 0 if the element is schemas valid, a positive error code
5151 * number otherwise and -1 in case of internal or API error.
5152 */
5153static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005154xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5155{
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 xmlNodePtr child;
5157 xmlSchemaTypePtr type;
5158 xmlAttrPtr attr;
5159 int ret;
5160
5161 child = ctxt->node;
5162 type = ctxt->type;
5163
5164 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005165 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5166 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005167 }
5168 /*
5169 * Only text and text based entities references shall be found there
5170 */
5171 ret = xmlSchemaValidateCheckNodeList(child);
5172 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005173 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5174 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005175 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005176 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5177 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005178 }
5179 /*
5180 * Validation Rule: Element Locally Valid (Type): 3.1.1
5181 */
5182 attr = node->properties;
5183 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005184 if ((attr->ns == NULL) ||
5185 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5186 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5187 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5188 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5189 (!xmlStrEqual
5190 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5191 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5192 return (ctxt->err);
5193 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005194 }
5195
5196 ctxt->type = type->subtypes;
5197 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5198 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005200}
5201
5202/**
5203 * xmlSchemaValidateElementType:
5204 * @ctxt: a schema validation context
5205 * @node: the top node.
5206 *
5207 * Validate the content of an element type.
5208 * Validation Rule: Element Locally Valid (Complex Type)
5209 *
5210 * Returns 0 if the element is schemas valid, a positive error code
5211 * number otherwise and -1 in case of internal or API error.
5212 */
5213static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005214xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5215{
Daniel Veillard4255d502002-04-16 15:50:10 +00005216 xmlNodePtr child;
5217 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005218 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005219 xmlSchemaElementPtr decl;
5220 int ret, attrBase;
5221
5222 oldregexp = ctxt->regexp;
5223
5224 child = ctxt->node;
5225 type = ctxt->type;
5226
5227 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005228 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5229 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005230 }
5231 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005232 if (type->minOccurs > 0) {
5233 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5234 }
5235 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 }
5237
5238 /*
5239 * Verify the element matches
5240 */
5241 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005242 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5243 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005244 }
5245 /*
5246 * Verify the attributes
5247 */
5248 attrBase = ctxt->attrBase;
5249 ctxt->attrBase = ctxt->attrNr;
5250 xmlSchemaRegisterAttributes(ctxt, child->properties);
5251 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5252 /*
5253 * Verify the element content recursively
5254 */
5255 decl = (xmlSchemaElementPtr) type;
5256 oldregexp = ctxt->regexp;
5257 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005258 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5259 (xmlRegExecCallbacks)
5260 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005261#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005262 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005263#endif
5264 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5266 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005267
5268 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005270#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005271 xmlGenericError(xmlGenericErrorContext,
5272 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005273#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005274 if (ret == 0) {
5275 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5276 } else if (ret < 0) {
5277 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005278#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005279 } else {
5280 xmlGenericError(xmlGenericErrorContext,
5281 "Element %s content check succeeded\n",
5282 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005283
5284#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005285 }
5286 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005287 }
5288 /*
5289 * Verify that all attributes were Schemas-validated
5290 */
5291 xmlSchemaCheckAttributes(ctxt, node);
5292 ctxt->attrNr = ctxt->attrBase;
5293 ctxt->attrBase = attrBase;
5294
5295 ctxt->regexp = oldregexp;
5296
5297 ctxt->node = child;
5298 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005299 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005300}
5301
5302/**
5303 * xmlSchemaValidateBasicType:
5304 * @ctxt: a schema validation context
5305 * @node: the top node.
5306 *
5307 * Validate the content of an element expected to be a basic type type
5308 *
5309 * Returns 0 if the element is schemas valid, a positive error code
5310 * number otherwise and -1 in case of internal or API error.
5311 */
5312static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005313xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5314{
Daniel Veillard4255d502002-04-16 15:50:10 +00005315 int ret;
5316 xmlNodePtr child, cur;
5317 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005318 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005319
5320 child = ctxt->node;
5321 type = ctxt->type;
5322
5323 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005324 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5325 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005326 }
5327 /*
5328 * First check the content model of the node.
5329 */
5330 cur = child;
5331 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005332 switch (cur->type) {
5333 case XML_TEXT_NODE:
5334 case XML_CDATA_SECTION_NODE:
5335 case XML_PI_NODE:
5336 case XML_COMMENT_NODE:
5337 case XML_XINCLUDE_START:
5338 case XML_XINCLUDE_END:
5339 break;
5340 case XML_ENTITY_REF_NODE:
5341 case XML_ENTITY_NODE:
5342 TODO break;
5343 case XML_ELEMENT_NODE:
5344 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5345 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005346 case XML_ATTRIBUTE_NODE:
5347 case XML_DOCUMENT_NODE:
5348 case XML_DOCUMENT_TYPE_NODE:
5349 case XML_DOCUMENT_FRAG_NODE:
5350 case XML_NOTATION_NODE:
5351 case XML_HTML_DOCUMENT_NODE:
5352 case XML_DTD_NODE:
5353 case XML_ELEMENT_DECL:
5354 case XML_ATTRIBUTE_DECL:
5355 case XML_ENTITY_DECL:
5356 case XML_NAMESPACE_DECL:
5357#ifdef LIBXML_DOCB_ENABLED
5358 case XML_DOCB_DOCUMENT_NODE:
5359#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5361 return (ctxt->err);
5362 }
5363 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005364 }
5365 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005366 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005367 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005368 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005369
5370 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005371 xmlSchemaFreeValue(ctxt->value);
5372 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005373 }
5374 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5375 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005377 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005378 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 +00005379 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005380 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005381}
5382
5383/**
5384 * xmlSchemaValidateComplexType:
5385 * @ctxt: a schema validation context
5386 * @node: the top node.
5387 *
5388 * Validate the content of an element expected to be a complex type type
5389 * xmlschema-1.html#cvc-complex-type
5390 * Validation Rule: Element Locally Valid (Complex Type)
5391 *
5392 * Returns 0 if the element is schemas valid, a positive error code
5393 * number otherwise and -1 in case of internal or API error.
5394 */
5395static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005396xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5397{
Daniel Veillard4255d502002-04-16 15:50:10 +00005398 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005399 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005400 int ret;
5401
5402 child = ctxt->node;
5403 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005404 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005405
Daniel Veillard4255d502002-04-16 15:50:10 +00005406 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005408 if (type->baseType != NULL) {
5409 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005410 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5411 }
5412 if (type->attributes != NULL) {
5413 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5414 }
5415 subtype = type->subtypes;
5416 while (subtype != NULL) {
5417 ctxt->type = subtype;
5418 xmlSchemaValidateComplexType(ctxt, node);
5419 subtype = subtype->next;
5420 }
5421 break;
5422 case XML_SCHEMA_CONTENT_ELEMENTS:
5423 case XML_SCHEMA_CONTENT_MIXED:
5424 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5425 /*
5426 * Skip ignorable nodes in that context
5427 */
5428 child = xmlSchemaSkipIgnored(ctxt, type, child);
5429 while (child != NULL) {
5430 if (child->type == XML_ELEMENT_NODE) {
5431 ret = xmlRegExecPushString(ctxt->regexp,
5432 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005433#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005434 if (ret < 0)
5435 xmlGenericError(xmlGenericErrorContext,
5436 " --> %s Error\n", child->name);
5437 else
5438 xmlGenericError(xmlGenericErrorContext,
5439 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005440#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005441 }
5442 child = child->next;
5443 /*
5444 * Skip ignorable nodes in that context
5445 */
5446 child = xmlSchemaSkipIgnored(ctxt, type, child);
5447 }
5448 break;
5449 case XML_SCHEMA_CONTENT_BASIC:{
5450 if (type->subtypes != NULL) {
5451 ctxt->type = type->subtypes;
5452 xmlSchemaValidateComplexType(ctxt, node);
5453 }
5454 if (type->baseType != NULL) {
5455 ctxt->type = type->baseType;
5456 xmlSchemaValidateBasicType(ctxt, node);
5457 }
5458 if (type->attributes != NULL) {
5459 xmlSchemaValidateAttributes(ctxt, node,
5460 type->attributes);
5461 }
5462 ctxt->type = type;
5463 break;
5464 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005465 case XML_SCHEMA_CONTENT_SIMPLE:{
5466 if (type->subtypes != NULL) {
5467 ctxt->type = type->subtypes;
5468 xmlSchemaValidateComplexType(ctxt, node);
5469 }
5470 if (type->baseType != NULL) {
5471 ctxt->type = type->baseType;
5472 xmlSchemaValidateComplexType(ctxt, node);
5473 }
5474 if (type->attributes != NULL) {
5475 xmlSchemaValidateAttributes(ctxt, node,
5476 type->attributes);
5477 }
5478 ctxt->type = type;
5479 break;
5480 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005481 default:
5482 TODO xmlGenericError(xmlGenericErrorContext,
5483 "unimplemented content type %d\n",
5484 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005485 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005486 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005487}
5488
5489/**
5490 * xmlSchemaValidateContent:
5491 * @ctxt: a schema validation context
5492 * @elem: an element
5493 * @type: the type declaration
5494 *
5495 * Validate the content of an element against the type.
5496 *
5497 * Returns 0 if the element is schemas valid, a positive error code
5498 * number otherwise and -1 in case of internal or API error.
5499 */
5500static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005501xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5502{
Daniel Veillard4255d502002-04-16 15:50:10 +00005503 xmlNodePtr child;
5504 xmlSchemaTypePtr type;
5505
5506 child = ctxt->node;
5507 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005508 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005509
Daniel Veillarde19fc232002-04-22 16:01:24 +00005510 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005511 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005512
Daniel Veillard4255d502002-04-16 15:50:10 +00005513 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005514 case XML_SCHEMA_TYPE_ANY:
5515 /* Any type will do it, fine */
5516 TODO /* handle recursivity */
5517 break;
5518 case XML_SCHEMA_TYPE_COMPLEX:
5519 xmlSchemaValidateComplexType(ctxt, node);
5520 break;
5521 case XML_SCHEMA_TYPE_ELEMENT:{
5522 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5523
5524 /*
5525 * Handle element reference here
5526 */
5527 if (decl->ref != NULL) {
5528 if (decl->refDecl == NULL) {
5529 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5530 return (-1);
5531 }
5532 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5533 decl = decl->refDecl;
5534 }
5535 xmlSchemaValidateElementType(ctxt, node);
5536 ctxt->type = type;
5537 break;
5538 }
5539 case XML_SCHEMA_TYPE_BASIC:
5540 xmlSchemaValidateBasicType(ctxt, node);
5541 break;
5542 case XML_SCHEMA_TYPE_FACET:
5543 TODO break;
5544 case XML_SCHEMA_TYPE_SIMPLE:
5545 xmlSchemaValidateSimpleType(ctxt, node);
5546 break;
5547 case XML_SCHEMA_TYPE_SEQUENCE:
5548 TODO break;
5549 case XML_SCHEMA_TYPE_CHOICE:
5550 TODO break;
5551 case XML_SCHEMA_TYPE_ALL:
5552 TODO break;
5553 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5554 TODO break;
5555 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5556 TODO break;
5557 case XML_SCHEMA_TYPE_UR:
5558 TODO break;
5559 case XML_SCHEMA_TYPE_RESTRICTION:
5560 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5561 TODO break;
5562 case XML_SCHEMA_TYPE_EXTENSION:
5563 TODO break;
5564 case XML_SCHEMA_TYPE_ATTRIBUTE:
5565 TODO break;
5566 case XML_SCHEMA_TYPE_GROUP:
5567 TODO break;
5568 case XML_SCHEMA_TYPE_NOTATION:
5569 TODO break;
5570 case XML_SCHEMA_TYPE_LIST:
5571 TODO break;
5572 case XML_SCHEMA_TYPE_UNION:
5573 TODO break;
5574 case XML_SCHEMA_FACET_MININCLUSIVE:
5575 TODO break;
5576 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5577 TODO break;
5578 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5579 TODO break;
5580 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5581 TODO break;
5582 case XML_SCHEMA_FACET_TOTALDIGITS:
5583 TODO break;
5584 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5585 TODO break;
5586 case XML_SCHEMA_FACET_PATTERN:
5587 TODO break;
5588 case XML_SCHEMA_FACET_ENUMERATION:
5589 TODO break;
5590 case XML_SCHEMA_FACET_WHITESPACE:
5591 TODO break;
5592 case XML_SCHEMA_FACET_LENGTH:
5593 TODO break;
5594 case XML_SCHEMA_FACET_MAXLENGTH:
5595 TODO break;
5596 case XML_SCHEMA_FACET_MINLENGTH:
5597 TODO break;
5598 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5599 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005600 }
5601 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5602
5603 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005604 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005605 ctxt->node = ctxt->node->next;
5606 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005607 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005608}
5609
5610/**
5611 * xmlSchemaValidateType:
5612 * @ctxt: a schema validation context
5613 * @elem: an element
5614 * @type: the list of type declarations
5615 *
5616 * Validate the content of an element against the types.
5617 *
5618 * Returns 0 if the element is schemas valid, a positive error code
5619 * number otherwise and -1 in case of internal or API error.
5620 */
5621static int
5622xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005623 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5624{
Daniel Veillard4255d502002-04-16 15:50:10 +00005625 xmlChar *nil;
5626
Daniel Veillard2db8c122003-07-08 12:16:59 +00005627 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005628 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005629
Daniel Veillard4255d502002-04-16 15:50:10 +00005630 /*
5631 * 3.3.4 : 2
5632 */
5633 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005634 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5635 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005636 }
5637 /*
5638 * 3.3.4: 3
5639 */
5640 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5641 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 /* 3.3.4: 3.2 */
5643 if (xmlStrEqual(nil, BAD_CAST "true")) {
5644 if (elem->children != NULL) {
5645 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5646 return (ctxt->err);
5647 }
5648 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5649 (elemDecl->value != NULL)) {
5650 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5651 return (ctxt->err);
5652 }
5653 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005654 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005655 /* 3.3.4: 3.1 */
5656 if (nil != NULL) {
5657 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5658 xmlFree(nil);
5659 return (ctxt->err);
5660 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 }
5662
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005663 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00005664
5665 ctxt->type = elemDecl->subtypes;
5666 ctxt->node = elem->children;
5667 xmlSchemaValidateContent(ctxt, elem);
5668 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005669
5670 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005671}
5672
5673
5674/**
5675 * xmlSchemaValidateAttributes:
5676 * @ctxt: a schema validation context
5677 * @elem: an element
5678 * @attributes: the list of attribute declarations
5679 *
5680 * Validate the attributes of an element.
5681 *
5682 * Returns 0 if the element is schemas valid, a positive error code
5683 * number otherwise and -1 in case of internal or API error.
5684 */
5685static int
5686xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005687 xmlSchemaAttributePtr attributes)
5688{
Daniel Veillard4255d502002-04-16 15:50:10 +00005689 int i, ret;
5690 xmlAttrPtr attr;
5691 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005692 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005693
5694 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005695 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005696 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005697 /*
5698 * Handle attribute groups
5699 */
5700 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5701 group = (xmlSchemaAttributeGroupPtr) attributes;
5702 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5703 attributes = group->next;
5704 continue;
5705 }
5706 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5707 attr = ctxt->attr[i].attr;
5708 if (attr == NULL)
5709 continue;
5710 if (attributes->ref != NULL) {
5711 if (!xmlStrEqual(attr->name, attributes->ref))
5712 continue;
5713 if (attr->ns != NULL) {
5714 if ((attributes->refNs == NULL) ||
5715 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5716 continue;
5717 } else if (attributes->refNs != NULL) {
5718 continue;
5719 }
5720 } else {
5721 if (!xmlStrEqual(attr->name, attributes->name))
5722 continue;
5723 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005724 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005725 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005726 if (attr->ns == NULL) {
5727 /*
5728 * accept an unqualified attribute only if the declaration
5729 * is unqualified or if the schemas allowed it.
5730 */
5731 if ((attributes->targetNamespace != NULL) &&
5732 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
5733 continue;
5734 } else {
5735 if (attributes->targetNamespace == NULL)
5736 continue;
5737 if (!xmlStrEqual(attributes->targetNamespace,
5738 attr->ns->href))
5739 continue;
5740 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741 }
5742 ctxt->cur = (xmlNodePtr) attributes;
5743 if (attributes->subtypes == NULL) {
5744 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
5745 continue;
5746 }
5747 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5748 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5749 value);
5750 if (ret != 0) {
5751 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
5752 } else {
5753 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5754 }
5755 if (value != NULL) {
5756 xmlFree(value);
5757 }
5758 }
5759 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005760 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005761 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005762}
5763
5764/**
5765 * xmlSchemaValidateElement:
5766 * @ctxt: a schema validation context
5767 * @elem: an element
5768 *
5769 * Validate an element in a tree
5770 *
5771 * Returns 0 if the element is schemas valid, a positive error code
5772 * number otherwise and -1 in case of internal or API error.
5773 */
5774static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005775xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
5776{
Daniel Veillard4255d502002-04-16 15:50:10 +00005777 xmlSchemaElementPtr elemDecl;
5778 int ret, attrBase;
5779
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005780 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005781 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5782 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005783 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5785 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005786 }
5787 /*
5788 * special case whe elementFormDefault is unqualified for top-level elem.
5789 */
5790 if ((elemDecl == NULL) && (elem->ns != NULL) &&
5791 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
5792 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
5793 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
5794 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5795 elem->name, NULL, NULL);
5796 }
5797
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 /*
5799 * 3.3.4 : 1
5800 */
5801 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005802 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
5803 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005804 }
5805 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
5807 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005808 }
5809 /*
5810 * Verify the attributes
5811 */
5812 attrBase = ctxt->attrBase;
5813 ctxt->attrBase = ctxt->attrNr;
5814 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5815 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5816 /*
5817 * Verify the element content recursively
5818 */
5819 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5821 (xmlRegExecCallbacks)
5822 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005823#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005825#endif
5826 }
5827 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005828 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005829 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005830#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005831 xmlGenericError(xmlGenericErrorContext,
5832 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005833#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005834 if (ret == 0) {
5835 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
5836 } else if (ret < 0) {
5837 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005838#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005839 } else {
5840 xmlGenericError(xmlGenericErrorContext,
5841 "Element %s content check succeeded\n",
5842 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005843
5844#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005845 }
5846 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 }
5848 /*
5849 * Verify that all attributes were Schemas-validated
5850 */
5851 xmlSchemaCheckAttributes(ctxt, elem);
5852 ctxt->attrNr = ctxt->attrBase;
5853 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005854
5855 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005856}
5857
5858/**
5859 * xmlSchemaValidateDocument:
5860 * @ctxt: a schema validation context
5861 * @doc: a parsed document tree
5862 *
5863 * Validate a document tree in memory.
5864 *
5865 * Returns 0 if the document is schemas valid, a positive error code
5866 * number otherwise and -1 in case of internal or API error.
5867 */
5868static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005869xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5870{
Daniel Veillard4255d502002-04-16 15:50:10 +00005871 xmlNodePtr root;
5872 xmlSchemaElementPtr elemDecl;
5873
5874 root = xmlDocGetRootElement(doc);
5875 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
5877 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005878 }
5879 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005880 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5881 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005882 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005883 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5884 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005885 /*
5886 * special case whe elementFormDefault is unqualified for top-level elem.
5887 */
5888 if ((elemDecl == NULL) && (root->ns != NULL) &&
5889 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
5890 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
5891 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5892 root->name, NULL, NULL);
5893 }
5894
Daniel Veillard4255d502002-04-16 15:50:10 +00005895 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005896 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005897 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005898 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005899 }
5900 /*
5901 * Okay, start the recursive validation
5902 */
5903 xmlSchemaValidateElement(ctxt, root);
5904
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005905 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005906}
5907
5908/************************************************************************
5909 * *
5910 * SAX Validation code *
5911 * *
5912 ************************************************************************/
5913
5914/************************************************************************
5915 * *
5916 * Validation interfaces *
5917 * *
5918 ************************************************************************/
5919
5920/**
5921 * xmlSchemaNewValidCtxt:
5922 * @schema: a precompiled XML Schemas
5923 *
5924 * Create an XML Schemas validation context based on the given schema
5925 *
5926 * Returns the validation context or NULL in case of error
5927 */
5928xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005929xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
5930{
Daniel Veillard4255d502002-04-16 15:50:10 +00005931 xmlSchemaValidCtxtPtr ret;
5932
5933 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5934 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005935 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005936 return (NULL);
5937 }
5938 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5939 ret->schema = schema;
5940 ret->attrNr = 0;
5941 ret->attrMax = 10;
5942 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005943 sizeof
5944 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00005945 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005946 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
5947 free(ret);
5948 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005949 }
5950 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5951 return (ret);
5952}
5953
5954/**
5955 * xmlSchemaFreeValidCtxt:
5956 * @ctxt: the schema validation context
5957 *
5958 * Free the resources associated to the schema validation context
5959 */
5960void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005961xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
5962{
Daniel Veillard4255d502002-04-16 15:50:10 +00005963 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005964 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005965 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005966 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005967 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005968 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005969 xmlFree(ctxt);
5970}
5971
5972/**
5973 * xmlSchemaSetValidErrors:
5974 * @ctxt: a schema validation context
5975 * @err: the error function
5976 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00005977 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00005978 *
5979 * Set the error and warning callback informations
5980 */
5981void
5982xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005983 xmlSchemaValidityErrorFunc err,
5984 xmlSchemaValidityWarningFunc warn, void *ctx)
5985{
Daniel Veillard4255d502002-04-16 15:50:10 +00005986 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005987 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 ctxt->error = err;
5989 ctxt->warning = warn;
5990 ctxt->userData = ctx;
5991}
5992
5993/**
5994 * xmlSchemaValidateDoc:
5995 * @ctxt: a schema validation context
5996 * @doc: a parsed document tree
5997 *
5998 * Validate a document tree in memory.
5999 *
6000 * Returns 0 if the document is schemas valid, a positive error code
6001 * number otherwise and -1 in case of internal or API error.
6002 */
6003int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006004xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6005{
Daniel Veillard4255d502002-04-16 15:50:10 +00006006 int ret;
6007
6008 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006009 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006010
6011 ctxt->doc = doc;
6012 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006013 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006014}
6015
6016/**
6017 * xmlSchemaValidateStream:
6018 * @ctxt: a schema validation context
6019 * @input: the input to use for reading the data
6020 * @enc: an optional encoding information
6021 * @sax: a SAX handler for the resulting events
6022 * @user_data: the context to provide to the SAX handler.
6023 *
6024 * Validate a document tree in memory.
6025 *
6026 * Returns 0 if the document is schemas valid, a positive error code
6027 * number otherwise and -1 in case of internal or API error.
6028 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006029int
Daniel Veillard4255d502002-04-16 15:50:10 +00006030xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006031 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6032 xmlSAXHandlerPtr sax, void *user_data)
6033{
Daniel Veillard4255d502002-04-16 15:50:10 +00006034 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006035 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006036 ctxt->input = input;
6037 ctxt->enc = enc;
6038 ctxt->sax = sax;
6039 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006040 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006041}
6042
6043#endif /* LIBXML_SCHEMAS_ENABLED */