blob: feafab9edc04509c50c20fce5e5dfddbfa3bb299 [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
Daniel Veillardf2a12832003-11-24 13:04:35 +0000936 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000937 *
938 * Lookup a an element in the schemas or the accessible schemas
939 *
940 * Returns the element definition or NULL if not found.
941 */
942static xmlSchemaElementPtr
943xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +0000944 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000945{
946 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +0000947 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000948
949 if ((name == NULL) || (schema == NULL))
950 return (NULL);
951
952 if (namespace == NULL) {
953 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +0000954 if ((ret != NULL) &&
955 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000956 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +0000957 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000958 } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
959 if (xmlStrEqual(namespace, schema->targetNamespace))
960 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
961 else
962 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +0000963 if ((ret != NULL) &&
964 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000965 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +0000966 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000967 } else {
968 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +0000969 if ((ret != NULL) &&
970 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000971 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +0000972 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000973 }
Daniel Veillardf2a12832003-11-24 13:04:35 +0000974 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000975 import = xmlHashLookup(schema->schemasImports, namespace);
976 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +0000977 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000978#ifdef DEBUG
979 if (ret == NULL) {
980 if (namespace == NULL)
981 fprintf(stderr, "Unable to lookup type %s", name);
982 else
983 fprintf(stderr, "Unable to lookup type %s:%s", name,
984 namespace);
985 }
986#endif
987 return (ret);
988}
989
990/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000991 * xmlSchemaGetType:
992 * @schema: the schemas context
993 * @name: the type name
994 * @ns: the type namespace
995 *
996 * Lookup a type in the schemas or the predefined types
997 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000998 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +0000999 */
1000static xmlSchemaTypePtr
1001xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001002 const xmlChar * namespace)
1003{
Daniel Veillard4255d502002-04-16 15:50:10 +00001004 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001005 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001006
1007 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001008 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001009 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001010 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1011 if (ret != NULL)
1012 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001013 }
1014 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001015 if (ret != NULL)
1016 return (ret);
1017 import = xmlHashLookup(schema->schemasImports, namespace);
1018 if (import != NULL)
1019 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001020#ifdef DEBUG
1021 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001022 if (namespace == NULL)
1023 fprintf(stderr, "Unable to lookup type %s", name);
1024 else
1025 fprintf(stderr, "Unable to lookup type %s:%s", name,
1026 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001027 }
1028#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001029 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001030}
1031
1032/************************************************************************
1033 * *
1034 * Parsing functions *
1035 * *
1036 ************************************************************************/
1037
1038#define IS_BLANK_NODE(n) \
1039 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1040
1041/**
1042 * xmlSchemaIsBlank:
1043 * @str: a string
1044 *
1045 * Check if a string is ignorable
1046 *
1047 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1048 */
1049static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001050xmlSchemaIsBlank(xmlChar * str)
1051{
Daniel Veillard4255d502002-04-16 15:50:10 +00001052 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001053 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001054 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001055 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001056 return (0);
1057 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001058 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001059 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001060}
1061
1062/**
1063 * xmlSchemaAddNotation:
1064 * @ctxt: a schema validation context
1065 * @schema: the schema being built
1066 * @name: the item name
1067 *
1068 * Add an XML schema Attrribute declaration
1069 * *WARNING* this interface is highly subject to change
1070 *
1071 * Returns the new struture or NULL in case of error
1072 */
1073static xmlSchemaNotationPtr
1074xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001075 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001076{
1077 xmlSchemaNotationPtr ret = NULL;
1078 int val;
1079
1080 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1081 return (NULL);
1082
1083 if (schema->notaDecl == NULL)
1084 schema->notaDecl = xmlHashCreate(10);
1085 if (schema->notaDecl == NULL)
1086 return (NULL);
1087
1088 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1089 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001090 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001091 return (NULL);
1092 }
1093 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001094 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001095 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1096 ret);
1097 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001098 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1099 XML_SCHEMAP_REDEFINED_NOTATION,
1100 "Notation %s already defined\n",
1101 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001102 xmlFree(ret);
1103 return (NULL);
1104 }
1105 return (ret);
1106}
1107
1108
1109/**
1110 * xmlSchemaAddAttribute:
1111 * @ctxt: a schema validation context
1112 * @schema: the schema being built
1113 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001114 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001115 *
1116 * Add an XML schema Attrribute declaration
1117 * *WARNING* this interface is highly subject to change
1118 *
1119 * Returns the new struture or NULL in case of error
1120 */
1121static xmlSchemaAttributePtr
1122xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001123 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001124{
1125 xmlSchemaAttributePtr ret = NULL;
1126 int val;
1127
1128 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1129 return (NULL);
1130
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001131#ifdef DEBUG
1132 fprintf(stderr, "Adding attribute %s\n", name);
1133 if (namespace != NULL)
1134 fprintf(stderr, " target namespace %s\n", namespace);
1135#endif
1136
Daniel Veillard4255d502002-04-16 15:50:10 +00001137 if (schema->attrDecl == NULL)
1138 schema->attrDecl = xmlHashCreate(10);
1139 if (schema->attrDecl == NULL)
1140 return (NULL);
1141
1142 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1143 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001144 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001145 return (NULL);
1146 }
1147 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001148 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1149 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001150 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001151 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001152 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001153 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1154 XML_SCHEMAP_REDEFINED_ATTR,
1155 "Attribute %s already defined\n",
1156 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001157 xmlFree(ret);
1158 return (NULL);
1159 }
1160 return (ret);
1161}
1162
1163/**
1164 * xmlSchemaAddAttributeGroup:
1165 * @ctxt: a schema validation context
1166 * @schema: the schema being built
1167 * @name: the item name
1168 *
1169 * Add an XML schema Attrribute Group declaration
1170 *
1171 * Returns the new struture or NULL in case of error
1172 */
1173static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001174xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1175 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001176{
1177 xmlSchemaAttributeGroupPtr ret = NULL;
1178 int val;
1179
1180 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1181 return (NULL);
1182
1183 if (schema->attrgrpDecl == NULL)
1184 schema->attrgrpDecl = xmlHashCreate(10);
1185 if (schema->attrgrpDecl == NULL)
1186 return (NULL);
1187
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001188 ret =
1189 (xmlSchemaAttributeGroupPtr)
1190 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001191 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001192 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001193 return (NULL);
1194 }
1195 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001196 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001197 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001198 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001199 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001200 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1201 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1202 "Attribute group %s already defined\n",
1203 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001204 xmlFree(ret);
1205 return (NULL);
1206 }
1207 return (ret);
1208}
1209
1210/**
1211 * xmlSchemaAddElement:
1212 * @ctxt: a schema validation context
1213 * @schema: the schema being built
1214 * @name: the type name
1215 * @namespace: the type namespace
1216 *
1217 * Add an XML schema Element declaration
1218 * *WARNING* this interface is highly subject to change
1219 *
1220 * Returns the new struture or NULL in case of error
1221 */
1222static xmlSchemaElementPtr
1223xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1224 const xmlChar * name, const xmlChar * namespace)
1225{
1226 xmlSchemaElementPtr ret = NULL;
1227 int val;
1228
1229 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1230 return (NULL);
1231
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001232#ifdef DEBUG
1233 fprintf(stderr, "Adding element %s\n", name);
1234 if (namespace != NULL)
1235 fprintf(stderr, " target namespace %s\n", namespace);
1236#endif
1237
Daniel Veillard4255d502002-04-16 15:50:10 +00001238 if (schema->elemDecl == NULL)
1239 schema->elemDecl = xmlHashCreate(10);
1240 if (schema->elemDecl == NULL)
1241 return (NULL);
1242
1243 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1244 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001245 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001246 return (NULL);
1247 }
1248 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001249 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1250 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001251 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001252 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001253 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001254 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001255
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001256 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001257 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1258 namespace, ret);
1259 if (val != 0) {
1260 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1261 XML_SCHEMAP_REDEFINED_ELEMENT,
1262 "Element %s already defined\n",
1263 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001264 xmlFree(ret);
1265 return (NULL);
1266 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001267 }
1268 return (ret);
1269}
1270
1271/**
1272 * xmlSchemaAddType:
1273 * @ctxt: a schema validation context
1274 * @schema: the schema being built
1275 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001276 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001277 *
1278 * Add an XML schema Simple Type definition
1279 * *WARNING* this interface is highly subject to change
1280 *
1281 * Returns the new struture or NULL in case of error
1282 */
1283static xmlSchemaTypePtr
1284xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001285 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001286{
1287 xmlSchemaTypePtr ret = NULL;
1288 int val;
1289
1290 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1291 return (NULL);
1292
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001293#ifdef DEBUG
1294 fprintf(stderr, "Adding type %s\n", name);
1295 if (namespace != NULL)
1296 fprintf(stderr, " target namespace %s\n", namespace);
1297#endif
1298
Daniel Veillard4255d502002-04-16 15:50:10 +00001299 if (schema->typeDecl == NULL)
1300 schema->typeDecl = xmlHashCreate(10);
1301 if (schema->typeDecl == NULL)
1302 return (NULL);
1303
1304 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1305 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001306 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001307 return (NULL);
1308 }
1309 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001310 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1311 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001312 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001313 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1314 XML_SCHEMAP_REDEFINED_TYPE,
1315 "Type %s already defined\n",
1316 name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001317 xmlFree(ret);
1318 return (NULL);
1319 }
1320 ret->minOccurs = 1;
1321 ret->maxOccurs = 1;
1322
1323 return (ret);
1324}
1325
1326/**
1327 * xmlSchemaAddGroup:
1328 * @ctxt: a schema validation context
1329 * @schema: the schema being built
1330 * @name: the group name
1331 *
1332 * Add an XML schema Group definition
1333 *
1334 * Returns the new struture or NULL in case of error
1335 */
1336static xmlSchemaTypePtr
1337xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001338 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001339{
1340 xmlSchemaTypePtr ret = NULL;
1341 int val;
1342
1343 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1344 return (NULL);
1345
1346 if (schema->groupDecl == NULL)
1347 schema->groupDecl = xmlHashCreate(10);
1348 if (schema->groupDecl == NULL)
1349 return (NULL);
1350
1351 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1352 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001353 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001354 return (NULL);
1355 }
1356 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001357 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001358 val =
1359 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1360 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001361 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001362 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1363 XML_SCHEMAP_REDEFINED_GROUP,
1364 "Group %s already defined\n",
1365 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001366 xmlFree(ret);
1367 return (NULL);
1368 }
1369 ret->minOccurs = 1;
1370 ret->maxOccurs = 1;
1371
1372 return (ret);
1373}
1374
1375/************************************************************************
1376 * *
1377 * Utilities for parsing *
1378 * *
1379 ************************************************************************/
1380
1381/**
1382 * xmlGetQNameProp:
1383 * @ctxt: a schema validation context
1384 * @node: a subtree containing XML Schema informations
1385 * @name: the attribute name
1386 * @namespace: the result namespace if any
1387 *
1388 * Extract a QName Attribute value
1389 *
1390 * Returns the NCName or NULL if not found, and also update @namespace
1391 * with the namespace URI
1392 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001393static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001394xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001395 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001396{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001397 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001398 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001399 const xmlChar *ret, *prefix;
1400 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001401
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001402 *namespace = NULL;
1403 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001404 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001405 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001406
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001407 ret = xmlSplitQName3(val, &len);
1408 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001409 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001410 }
1411 ret = xmlDictLookup(ctxt->dict, ret, -1);
1412 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001413
1414 ns = xmlSearchNs(node->doc, node, prefix);
1415 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001416 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1417 "Attribute %s: the QName prefix %s is undefined\n",
1418 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001419 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001420 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001421 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001422 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001423}
1424
1425/**
1426 * xmlGetMaxOccurs:
1427 * @ctxt: a schema validation context
1428 * @node: a subtree containing XML Schema informations
1429 *
1430 * Get the maxOccurs property
1431 *
1432 * Returns the default if not found, or the value
1433 */
1434static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001435xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1436{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001437 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001438 int ret = 0;
1439
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001440 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001441 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001442 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001443
1444 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001445 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001446 }
1447
1448 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001449 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001450 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001451 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 ret = ret * 10 + (*cur - '0');
1453 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001454 }
William M. Brack76e95df2003-10-18 16:20:14 +00001455 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001456 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001457 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001458 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1459 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001460 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001461 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001462 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001463}
1464
1465/**
1466 * xmlGetMinOccurs:
1467 * @ctxt: a schema validation context
1468 * @node: a subtree containing XML Schema informations
1469 *
1470 * Get the minOccurs property
1471 *
1472 * Returns the default if not found, or the value
1473 */
1474static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001475xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1476{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001477 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001478 int ret = 0;
1479
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001480 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001481 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001482 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001483
1484 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001485 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001486 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001487 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001488 ret = ret * 10 + (*cur - '0');
1489 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001490 }
William M. Brack76e95df2003-10-18 16:20:14 +00001491 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001492 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001493 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001494 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1495 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001496 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001497 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001498 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001499}
1500
1501/**
1502 * xmlGetBooleanProp:
1503 * @ctxt: a schema validation context
1504 * @node: a subtree containing XML Schema informations
1505 * @name: the attribute name
1506 * @def: the default value
1507 *
1508 * Get is a bolean property is set
1509 *
1510 * Returns the default if not found, 0 if found to be false,
1511 * 1 if found to be true
1512 */
1513static int
1514xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001515 const char *name, int def)
1516{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001517 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001518
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001519 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001520 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001521 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001522
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523 if (xmlStrEqual(val, BAD_CAST "true"))
1524 def = 1;
1525 else if (xmlStrEqual(val, BAD_CAST "false"))
1526 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001527 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001528 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1529 "Attribute %s: the value %s is not boolean\n",
1530 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001531 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001533}
1534
1535/************************************************************************
1536 * *
1537 * Shema extraction from an Infoset *
1538 * *
1539 ************************************************************************/
1540static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1541 ctxt, xmlSchemaPtr schema,
1542 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001543static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1544 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001545 xmlSchemaPtr schema,
1546 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001547static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1548 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001549 xmlSchemaPtr schema,
1550 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001551 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001552static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1553 xmlSchemaPtr schema,
1554 xmlNodePtr node);
1555static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1556 xmlSchemaPtr schema,
1557 xmlNodePtr node);
1558static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1559 ctxt,
1560 xmlSchemaPtr schema,
1561 xmlNodePtr node);
1562static xmlSchemaAttributeGroupPtr
1563xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1564 xmlSchemaPtr schema, xmlNodePtr node);
1565static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1566 xmlSchemaPtr schema,
1567 xmlNodePtr node);
1568static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1569 xmlSchemaPtr schema,
1570 xmlNodePtr node);
1571static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001572xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1573 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001574
1575/**
1576 * xmlSchemaParseAttrDecls:
1577 * @ctxt: a schema validation context
1578 * @schema: the schema being built
1579 * @node: a subtree containing XML Schema informations
1580 * @type: the hosting type
1581 *
1582 * parse a XML schema attrDecls declaration corresponding to
1583 * <!ENTITY % attrDecls
1584 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1585 */
1586static xmlNodePtr
1587xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1588 xmlNodePtr child, xmlSchemaTypePtr type)
1589{
1590 xmlSchemaAttributePtr lastattr, attr;
1591
1592 lastattr = NULL;
1593 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001594 (IS_SCHEMA(child, "attributeGroup"))) {
1595 attr = NULL;
1596 if (IS_SCHEMA(child, "attribute")) {
1597 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1598 } else if (IS_SCHEMA(child, "attributeGroup")) {
1599 attr = (xmlSchemaAttributePtr)
1600 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1601 }
1602 if (attr != NULL) {
1603 if (lastattr == NULL) {
1604 type->attributes = attr;
1605 lastattr = attr;
1606 } else {
1607 lastattr->next = attr;
1608 lastattr = attr;
1609 }
1610 }
1611 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001612 }
1613 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001614 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1615 if (attr != NULL) {
1616 if (lastattr == NULL) {
1617 type->attributes = attr;
1618 lastattr = attr;
1619 } else {
1620 lastattr->next = attr;
1621 lastattr = attr;
1622 }
1623 }
1624 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001625 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001626 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001627}
1628
1629/**
1630 * xmlSchemaParseAnnotation:
1631 * @ctxt: a schema validation context
1632 * @schema: the schema being built
1633 * @node: a subtree containing XML Schema informations
1634 *
1635 * parse a XML schema Attrribute declaration
1636 * *WARNING* this interface is highly subject to change
1637 *
1638 * Returns -1 in case of error, 0 if the declaration is inproper and
1639 * 1 in case of success.
1640 */
1641static xmlSchemaAnnotPtr
1642xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1643 xmlNodePtr node)
1644{
1645 xmlSchemaAnnotPtr ret;
1646
1647 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1648 return (NULL);
1649 ret = xmlSchemaNewAnnot(ctxt, node);
1650
1651 return (ret);
1652}
1653
1654/**
1655 * xmlSchemaParseFacet:
1656 * @ctxt: a schema validation context
1657 * @schema: the schema being built
1658 * @node: a subtree containing XML Schema informations
1659 *
1660 * parse a XML schema Facet declaration
1661 * *WARNING* this interface is highly subject to change
1662 *
1663 * Returns the new type structure or NULL in case of error
1664 */
1665static xmlSchemaFacetPtr
1666xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001667 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001668{
1669 xmlSchemaFacetPtr facet;
1670 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001671 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001672
1673 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1674 return (NULL);
1675
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001676 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001677 if (facet == NULL) {
1678 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1679 return (NULL);
1680 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001681 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001682 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001683 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001684 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1685 "Facet %s has no value\n", node->name, NULL);
1686 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001687 return (NULL);
1688 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001689 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001690 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001691 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001692 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001693 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001694 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001695 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001696 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001697 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001698 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001699 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001700 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001701 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001702 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001703 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001704 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001705 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001706 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001707 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001708 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001709 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001710 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1711 } else if (IS_SCHEMA(node, "minLength")) {
1712 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1713 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001714 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1715 "Unknown facet type %s\n", node->name, NULL);
1716 xmlSchemaFreeFacet(facet);
1717 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001718 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001719 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001720 facet->value = value;
1721 child = node->children;
1722
1723 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001724 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1725 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001726 }
1727 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001728 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1729 "Facet %s has unexpected child content\n",
1730 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001731 }
1732 return (facet);
1733}
1734
1735/**
1736 * xmlSchemaParseAny:
1737 * @ctxt: a schema validation context
1738 * @schema: the schema being built
1739 * @node: a subtree containing XML Schema informations
1740 *
1741 * parse a XML schema Any declaration
1742 * *WARNING* this interface is highly subject to change
1743 *
1744 * Returns the new type structure or NULL in case of error
1745 */
1746static xmlSchemaTypePtr
1747xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1748 xmlNodePtr node)
1749{
1750 xmlSchemaTypePtr type;
1751 xmlNodePtr child = NULL;
1752 xmlChar name[30];
1753
1754 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1755 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001756 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001757 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001758 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001759 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001760 type->node = node;
1761 type->type = XML_SCHEMA_TYPE_ANY;
1762 child = node->children;
1763 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1764 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1765
1766 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001767 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1768 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001769 }
1770 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001771 xmlSchemaPErr2(ctxt, node, child,
1772 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1773 "Sequence %s has unexpected content\n", type->name,
1774 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001775 }
1776
1777 return (type);
1778}
1779
1780/**
1781 * xmlSchemaParseNotation:
1782 * @ctxt: a schema validation context
1783 * @schema: the schema being built
1784 * @node: a subtree containing XML Schema informations
1785 *
1786 * parse a XML schema Notation declaration
1787 *
1788 * Returns the new structure or NULL in case of error
1789 */
1790static xmlSchemaNotationPtr
1791xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001792 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001793{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001794 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001795 xmlSchemaNotationPtr ret;
1796 xmlNodePtr child = NULL;
1797
1798 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1799 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001800 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001801 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001802 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1803 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001804 return (NULL);
1805 }
1806 ret = xmlSchemaAddNotation(ctxt, schema, name);
1807 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001808 return (NULL);
1809 }
1810 child = node->children;
1811 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1813 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001814 }
1815 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 xmlSchemaPErr2(ctxt, node, child,
1817 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1818 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 }
1820
1821 return (ret);
1822}
1823
1824/**
1825 * xmlSchemaParseAnyAttribute:
1826 * @ctxt: a schema validation context
1827 * @schema: the schema being built
1828 * @node: a subtree containing XML Schema informations
1829 *
1830 * parse a XML schema AnyAttrribute declaration
1831 * *WARNING* this interface is highly subject to change
1832 *
1833 * Returns an attribute def structure or NULL
1834 */
1835static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001836xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1837 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001838{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001839 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001840 xmlSchemaAttributePtr ret;
1841 xmlNodePtr child = NULL;
1842 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001843 const xmlChar *local, *ns;
1844
Daniel Veillard4255d502002-04-16 15:50:10 +00001845
1846 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1847 return (NULL);
1848
1849 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001850 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1851 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001852 if (ret == NULL) {
1853 return (NULL);
1854 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001855 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1856 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001857 if ((processContents == NULL)
1858 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1859 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1860 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1861 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1862 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1863 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001864 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001865 xmlSchemaPErr2(ctxt, node, child,
1866 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1867 "anyAttribute has unexpected content for processContents: %s\n",
1868 processContents, NULL);
1869 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001871
1872 child = node->children;
1873 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001874 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1875 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001876 }
1877 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001878 xmlSchemaPErr2(ctxt, node, child,
1879 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1880 "anyAttribute %s has unexpected content\n",
1881 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001882 }
1883
1884 return (ret);
1885}
1886
1887
1888/**
1889 * xmlSchemaParseAttribute:
1890 * @ctxt: a schema validation context
1891 * @schema: the schema being built
1892 * @node: a subtree containing XML Schema informations
1893 *
1894 * parse a XML schema Attrribute declaration
1895 * *WARNING* this interface is highly subject to change
1896 *
1897 * Returns -1 in case of error, 0 if the declaration is inproper and
1898 * 1 in case of success.
1899 */
1900static xmlSchemaAttributePtr
1901xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1902 xmlNodePtr node)
1903{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001904 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001905 xmlSchemaAttributePtr ret;
1906 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001907 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001908
1909 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1910 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001911 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001912 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1915 if (ref == NULL) {
1916 xmlSchemaPErr2(ctxt, node, child,
1917 XML_SCHEMAP_ATTR_NONAME_NOREF,
1918 "Attribute has no name nor ref\n", NULL, NULL);
1919 return (NULL);
1920 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001921 if (refNs == NULL)
1922 refNs = schema->targetNamespace;
1923 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
1924 name = (const xmlChar *) buf;
1925 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
1926 } else {
1927 const xmlChar *local, *ns;
1928
1929 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
1930 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001931 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001932 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001933 return (NULL);
1934 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001935 ret->ref = ref;
1936 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001937 if ((ret->targetNamespace != NULL) &&
1938 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
1939 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
1940 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001941 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001942 if ((ret->typeName != NULL) && (ret->typeNs == NULL))
1943 ret->typeNs = schema->targetNamespace;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001944 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001945 child = node->children;
1946 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1948 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001949 }
1950 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001951 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1952 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001953 }
1954 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001955 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
1956 "attribute %s has unexpected content\n", name,
1957 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001958 }
1959
1960 return (ret);
1961}
1962
1963/**
1964 * xmlSchemaParseAttributeGroup:
1965 * @ctxt: a schema validation context
1966 * @schema: the schema being built
1967 * @node: a subtree containing XML Schema informations
1968 *
1969 * parse a XML schema Attribute Group declaration
1970 * *WARNING* this interface is highly subject to change
1971 *
1972 * Returns the attribute group or NULL in case of error.
1973 */
1974static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001975xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1976 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001977{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001978 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001979 xmlSchemaAttributeGroupPtr ret;
1980 xmlSchemaAttributePtr last = NULL, attr;
1981 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001982 const xmlChar *oldcontainer;
1983 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001984
1985 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1986 return (NULL);
1987 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001988 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001989 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001990
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001991 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1992 if (ref == NULL) {
1993 xmlSchemaPErr2(ctxt, node, child,
1994 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
1995 "AttributeGroup has no name nor ref\n", NULL,
1996 NULL);
1997 return (NULL);
1998 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001999 if (refNs == NULL)
2000 refNs = schema->targetNamespace;
2001 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2002 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002003 if (name == NULL) {
2004 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2005 return (NULL);
2006 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002007 }
2008 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2009 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002010 return (NULL);
2011 }
2012 ret->ref = ref;
2013 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002014 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002015 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002016 child = node->children;
2017 ctxt->container = name;
2018 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002019 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2020 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002021 }
2022 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002023 (IS_SCHEMA(child, "attributeGroup"))) {
2024 attr = NULL;
2025 if (IS_SCHEMA(child, "attribute")) {
2026 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2027 } else if (IS_SCHEMA(child, "attributeGroup")) {
2028 attr = (xmlSchemaAttributePtr)
2029 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2030 }
2031 if (attr != NULL) {
2032 if (last == NULL) {
2033 ret->attributes = attr;
2034 last = attr;
2035 } else {
2036 last->next = attr;
2037 last = attr;
2038 }
2039 }
2040 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002041 }
2042 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002043 TODO
2044 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002045 }
2046 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002047 xmlSchemaPErr2(ctxt, node, child,
2048 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2049 "attribute group %s has unexpected content\n", name,
2050 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002051 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002052 ctxt->container = oldcontainer;
2053 return (ret);
2054}
2055
2056/**
2057 * xmlSchemaParseElement:
2058 * @ctxt: a schema validation context
2059 * @schema: the schema being built
2060 * @node: a subtree containing XML Schema informations
2061 *
2062 * parse a XML schema Element declaration
2063 * *WARNING* this interface is highly subject to change
2064 *
2065 * Returns -1 in case of error, 0 if the declaration is inproper and
2066 * 1 in case of success.
2067 */
2068static xmlSchemaElementPtr
2069xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2070 xmlNodePtr node, int toplevel)
2071{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002072 const xmlChar *name, *fixed;
2073 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002074 xmlSchemaElementPtr ret;
2075 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002076 const xmlChar *oldcontainer;
2077 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002078
2079 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2080 return (NULL);
2081 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002082 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002083 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002084
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002085 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2086 if (ref == NULL) {
2087 xmlSchemaPErr2(ctxt, node, child,
2088 XML_SCHEMAP_ELEM_NONAME_NOREF,
2089 "Element has no name nor ref\n", NULL, NULL);
2090 return (NULL);
2091 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002092 if (refNs == NULL)
2093 refNs = schema->targetNamespace;
2094 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2095 name = (const xmlChar *) buf;
2096 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2097 } else {
2098 const xmlChar *local, *ns;
2099
2100 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2101 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002102 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002103 if (ret != NULL)
2104 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002105 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002106 return (NULL);
2107 }
2108 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2109 ret->ref = ref;
2110 ret->refNs = refNs;
2111 if (ref != NULL)
2112 ret->flags |= XML_SCHEMAS_ELEM_REF;
2113 if (toplevel)
2114 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2115 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2116 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2117 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2118 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2119 ctxt->container = name;
2120
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002121 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002122 ret->namedType =
2123 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002124 if ((ret->namedType != NULL) && (ret->namedTypeNs == NULL))
2125 ret->namedTypeNs = schema->targetNamespace;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002126 ret->substGroup =
2127 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2128 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002129 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002130 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2131 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002132
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002133 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002134 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002135 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2136 "Element %s has both default and fixed\n",
2137 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002138 } else if (fixed != NULL) {
2139 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002140 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002141 }
2142
2143 child = node->children;
2144 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002145 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2146 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002147 }
2148 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002149 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002150 child = child->next;
2151 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002152 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002153 child = child->next;
2154 }
2155 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002156 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2157 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002158 }
2159 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002160 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2161 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002162 }
2163
2164 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002165 return (ret);
2166}
2167
2168/**
2169 * xmlSchemaParseUnion:
2170 * @ctxt: a schema validation context
2171 * @schema: the schema being built
2172 * @node: a subtree containing XML Schema informations
2173 *
2174 * parse a XML schema Union definition
2175 * *WARNING* this interface is highly subject to change
2176 *
2177 * Returns -1 in case of error, 0 if the declaration is inproper and
2178 * 1 in case of success.
2179 */
2180static xmlSchemaTypePtr
2181xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002182 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002183{
2184 xmlSchemaTypePtr type, subtype, last = NULL;
2185 xmlNodePtr child = NULL;
2186 xmlChar name[30];
2187
2188 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2189 return (NULL);
2190
2191
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002192 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002193 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002194 if (type == NULL)
2195 return (NULL);
2196 type->node = node;
2197 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002198 type->id = xmlSchemaGetProp(ctxt, node, "id");
2199 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002200
2201 child = node->children;
2202 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002203 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2204 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002205 }
2206 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002207 subtype = (xmlSchemaTypePtr)
2208 xmlSchemaParseSimpleType(ctxt, schema, child);
2209 if (subtype != NULL) {
2210 if (last == NULL) {
2211 type->subtypes = subtype;
2212 last = subtype;
2213 } else {
2214 last->next = subtype;
2215 last = subtype;
2216 }
2217 last->next = NULL;
2218 }
2219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002220 }
2221 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002222 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2223 "Union %s has unexpected content\n", type->name,
2224 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002225 }
2226 return (type);
2227}
2228
2229/**
2230 * xmlSchemaParseList:
2231 * @ctxt: a schema validation context
2232 * @schema: the schema being built
2233 * @node: a subtree containing XML Schema informations
2234 *
2235 * parse a XML schema List definition
2236 * *WARNING* this interface is highly subject to change
2237 *
2238 * Returns -1 in case of error, 0 if the declaration is inproper and
2239 * 1 in case of success.
2240 */
2241static xmlSchemaTypePtr
2242xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002244{
2245 xmlSchemaTypePtr type, subtype;
2246 xmlNodePtr child = NULL;
2247 xmlChar name[30];
2248
2249 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2250 return (NULL);
2251
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002252 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002253 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002254 if (type == NULL)
2255 return (NULL);
2256 type->node = node;
2257 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002258 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002259 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002260 if ((type->ref != NULL) && (type->refNs == NULL))
2261 type->refNs = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00002262
2263 child = node->children;
2264 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002265 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2266 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 }
2268 subtype = NULL;
2269 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002270 subtype = (xmlSchemaTypePtr)
2271 xmlSchemaParseSimpleType(ctxt, schema, child);
2272 child = child->next;
2273 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002274 }
2275 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002276 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2277 "List %s has unexpected content\n", type->name,
2278 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002279 }
2280 return (type);
2281}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002282
Daniel Veillard4255d502002-04-16 15:50:10 +00002283/**
2284 * xmlSchemaParseSimpleType:
2285 * @ctxt: a schema validation context
2286 * @schema: the schema being built
2287 * @node: a subtree containing XML Schema informations
2288 *
2289 * parse a XML schema Simple Type definition
2290 * *WARNING* this interface is highly subject to change
2291 *
2292 * Returns -1 in case of error, 0 if the declaration is inproper and
2293 * 1 in case of success.
2294 */
2295static xmlSchemaTypePtr
2296xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2297 xmlNodePtr node)
2298{
2299 xmlSchemaTypePtr type, subtype;
2300 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002301 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002302
2303 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2304 return (NULL);
2305
2306
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002307 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002308 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002309 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002310
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002311 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2312 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2313 } else {
2314 const xmlChar *local, *ns;
2315
2316 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2317 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002318 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002319 if (type == NULL)
2320 return (NULL);
2321 type->node = node;
2322 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002323 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002324
2325 child = node->children;
2326 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002327 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2328 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002329 }
2330 subtype = NULL;
2331 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002332 subtype = (xmlSchemaTypePtr)
2333 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2334 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002335 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002336 subtype = (xmlSchemaTypePtr)
2337 xmlSchemaParseList(ctxt, schema, child);
2338 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002339 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002340 subtype = (xmlSchemaTypePtr)
2341 xmlSchemaParseUnion(ctxt, schema, child);
2342 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002343 }
2344 type->subtypes = subtype;
2345 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002346 xmlSchemaPErr2(ctxt, node, child,
2347 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2348 "SimpleType %s has unexpected content\n",
2349 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002350 }
2351
2352 return (type);
2353}
2354
2355
2356/**
2357 * xmlSchemaParseGroup:
2358 * @ctxt: a schema validation context
2359 * @schema: the schema being built
2360 * @node: a subtree containing XML Schema informations
2361 *
2362 * parse a XML schema Group definition
2363 * *WARNING* this interface is highly subject to change
2364 *
2365 * Returns -1 in case of error, 0 if the declaration is inproper and
2366 * 1 in case of success.
2367 */
2368static xmlSchemaTypePtr
2369xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002370 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002371{
2372 xmlSchemaTypePtr type, subtype;
2373 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002374 const xmlChar *name;
2375 const xmlChar *ref = NULL, *refNs = NULL;
2376 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002377
2378 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2379 return (NULL);
2380
2381
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002382 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002383 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002384
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002385 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2386 if (ref == NULL) {
2387 xmlSchemaPErr2(ctxt, node, child,
2388 XML_SCHEMAP_GROUP_NONAME_NOREF,
2389 "Group has no name nor ref\n", NULL, NULL);
2390 return (NULL);
2391 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002392 if (refNs == NULL)
2393 refNs = schema->targetNamespace;
2394 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2395 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002396 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002397 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002398 if (type == NULL)
2399 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002400
Daniel Veillard4255d502002-04-16 15:50:10 +00002401 type->node = node;
2402 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002403 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002404 type->ref = ref;
2405 type->refNs = refNs;
2406 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2407 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2408
2409 child = node->children;
2410 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002411 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2412 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002413 }
2414 subtype = NULL;
2415 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002416 subtype = (xmlSchemaTypePtr)
2417 xmlSchemaParseAll(ctxt, schema, child);
2418 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002419 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2421 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002422 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002423 subtype = (xmlSchemaTypePtr)
2424 xmlSchemaParseSequence(ctxt, schema, child);
2425 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002426 }
2427 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002429 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002430 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2431 "Group %s has unexpected content\n", type->name,
2432 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002433 }
2434
2435 return (type);
2436}
2437
2438/**
2439 * xmlSchemaParseAll:
2440 * @ctxt: a schema validation context
2441 * @schema: the schema being built
2442 * @node: a subtree containing XML Schema informations
2443 *
2444 * parse a XML schema All definition
2445 * *WARNING* this interface is highly subject to change
2446 *
2447 * Returns -1 in case of error, 0 if the declaration is inproper and
2448 * 1 in case of success.
2449 */
2450static xmlSchemaTypePtr
2451xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002452 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002453{
2454 xmlSchemaTypePtr type, subtype, last = NULL;
2455 xmlNodePtr child = NULL;
2456 xmlChar name[30];
2457
2458 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2459 return (NULL);
2460
2461
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002462 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002463 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002464 if (type == NULL)
2465 return (NULL);
2466 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002467 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002468 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002469 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2470 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2471
2472 child = node->children;
2473 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002474 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2475 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002476 }
2477 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002478 subtype = (xmlSchemaTypePtr)
2479 xmlSchemaParseElement(ctxt, schema, child, 0);
2480 if (subtype != NULL) {
2481 if (last == NULL) {
2482 type->subtypes = subtype;
2483 last = subtype;
2484 } else {
2485 last->next = subtype;
2486 last = subtype;
2487 }
2488 last->next = NULL;
2489 }
2490 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002491 }
2492 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002493 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2494 "All %s has unexpected content\n", type->name,
2495 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002496 }
2497
2498 return (type);
2499}
2500
2501/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002502 * xmlSchemaImportSchema
2503 *
2504 * @ctxt: a schema validation context
2505 * @schemaLocation: an URI defining where to find the imported schema
2506 *
2507 * import a XML schema
2508 * *WARNING* this interface is highly subject to change
2509 *
2510 * Returns -1 in case of error and 1 in case of success.
2511 */
2512static xmlSchemaImportPtr
2513xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2514 const xmlChar *schemaLocation)
2515{
2516 xmlSchemaImportPtr import;
2517 xmlSchemaParserCtxtPtr newctxt;
2518
2519 newctxt = xmlSchemaNewParserCtxt((const char *) schemaLocation);
2520 if (newctxt == NULL) {
2521 xmlSchemaPErrMemory(NULL, "allocating parser context",
2522 NULL);
2523 return (NULL);
2524 }
2525 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2526 ctxt->userData);
2527
2528 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2529 if (import == NULL) {
2530 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2531 NULL);
2532 xmlSchemaFreeParserCtxt(newctxt);
2533 return (NULL);
2534 }
2535
2536 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002537 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002538 import->schema = xmlSchemaParse(newctxt);
2539
2540 if (import->schema == NULL) {
2541 /* FIXME use another error enum here ? */
2542 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2543 "failed to import schema at location %s\n",
2544 schemaLocation, NULL);
2545
2546 xmlSchemaFreeParserCtxt(newctxt);
2547 if (import->schemaLocation != NULL)
2548 xmlFree((xmlChar *)import->schemaLocation);
2549 xmlFree(import);
2550 return NULL;
2551 }
2552
2553 xmlSchemaFreeParserCtxt(newctxt);
2554 return import;
2555}
2556
2557
2558/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002559 * xmlSchemaParseImport:
2560 * @ctxt: a schema validation context
2561 * @schema: the schema being built
2562 * @node: a subtree containing XML Schema informations
2563 *
2564 * parse a XML schema Import definition
2565 * *WARNING* this interface is highly subject to change
2566 *
2567 * Returns -1 in case of error, 0 if the declaration is inproper and
2568 * 1 in case of success.
2569 */
2570static int
2571xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002572 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002573{
2574 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002575 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002576 const xmlChar *namespace;
2577 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002578 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002579 xmlURIPtr check;
2580
Daniel Veillard1d913862003-11-21 00:28:39 +00002581
Daniel Veillard5a872412002-05-22 06:40:27 +00002582 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2583 return (-1);
2584
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002585 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002586 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002587 check = xmlParseURI((const char *) namespace);
2588 if (check == NULL) {
2589 xmlSchemaPErr2(ctxt, node, child,
2590 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2591 "Import namespace attribute is not an URI: %s\n",
2592 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002593 return (-1);
2594 } else {
2595 xmlFreeURI(check);
2596 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002597 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002598 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002599 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002600 xmlChar *base = NULL;
2601 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002602 check = xmlParseURI((const char *) schemaLocation);
2603 if (check == NULL) {
2604 xmlSchemaPErr2(ctxt, node, child,
2605 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2606 "Import schemaLocation attribute is not an URI: %s\n",
2607 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002608 return (-1);
2609 } else {
2610 xmlFreeURI(check);
2611 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002612 base = xmlNodeGetBase(node->doc, node);
2613 if (base == NULL) {
2614 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2615 } else {
2616 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002617 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002618 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002619 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002620 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2621 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002622 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002623 }
2624 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002625 schema->schemasImports = xmlHashCreate(10);
2626 if (schema->schemasImports == NULL) {
2627 xmlSchemaPErr2(ctxt, node, child,
2628 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2629 "Internal: failed to build import table\n",
2630 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002631 return (-1);
2632 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002633 }
2634 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002635 import = xmlHashLookup(schema->schemasImports,
2636 XML_SCHEMAS_DEFAULT_NAMESPACE);
2637 if (import != NULL)
2638 previous = import->schemaLocation;
2639 else
2640 previous = NULL;
2641
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002642 if (schemaLocation != NULL) {
2643 if (previous != NULL) {
2644 if (!xmlStrEqual(schemaLocation, previous)) {
2645 xmlSchemaPErr2(ctxt, node, child,
2646 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2647 "Redefining import for default namespace with a different URI: %s\n",
2648 schemaLocation, NULL);
2649 }
2650 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002651 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2652 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002653 return (-1);
2654 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 xmlHashAddEntry(schema->schemasImports,
2656 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002657 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002658 }
2659 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002660 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002661 import = xmlHashLookup(schema->schemasImports, namespace);
2662 if (import != NULL)
2663 previous = import->schemaLocation;
2664 else
2665 previous = NULL;
2666
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002667 if (schemaLocation != NULL) {
2668 if (previous != NULL) {
2669 if (!xmlStrEqual(schemaLocation, previous)) {
2670 xmlSchemaPErr2(ctxt, node, child,
2671 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2672 "Redefining import for namespace %s with a different URI: %s\n",
2673 namespace, schemaLocation);
2674 }
2675 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002676 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2677 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002678 return (-1);
2679 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002680 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002681 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002682 }
2683 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002684 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002685
2686 child = node->children;
2687 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002688 /*
2689 * the annotations here are simply discarded ...
2690 */
2691 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002692 }
2693 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002694 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2695 "Import has unexpected content\n", NULL, NULL);
2696 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002697 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002698 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002699}
2700
2701/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002702 * xmlSchemaParseChoice:
2703 * @ctxt: a schema validation context
2704 * @schema: the schema being built
2705 * @node: a subtree containing XML Schema informations
2706 *
2707 * parse a XML schema Choice definition
2708 * *WARNING* this interface is highly subject to change
2709 *
2710 * Returns -1 in case of error, 0 if the declaration is inproper and
2711 * 1 in case of success.
2712 */
2713static xmlSchemaTypePtr
2714xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002715 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002716{
2717 xmlSchemaTypePtr type, subtype, last = NULL;
2718 xmlNodePtr child = NULL;
2719 xmlChar name[30];
2720
2721 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2722 return (NULL);
2723
2724
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002725 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002726 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002727 if (type == NULL)
2728 return (NULL);
2729 type->node = node;
2730 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002731 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2733 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2734
2735 child = node->children;
2736 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002737 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2738 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002739 }
2740 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002741 (IS_SCHEMA(child, "group")) ||
2742 (IS_SCHEMA(child, "any")) ||
2743 (IS_SCHEMA(child, "choice")) ||
2744 (IS_SCHEMA(child, "sequence"))) {
2745 subtype = NULL;
2746 if (IS_SCHEMA(child, "element")) {
2747 subtype = (xmlSchemaTypePtr)
2748 xmlSchemaParseElement(ctxt, schema, child, 0);
2749 } else if (IS_SCHEMA(child, "group")) {
2750 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2751 } else if (IS_SCHEMA(child, "any")) {
2752 subtype = xmlSchemaParseAny(ctxt, schema, child);
2753 } else if (IS_SCHEMA(child, "sequence")) {
2754 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2755 } else if (IS_SCHEMA(child, "choice")) {
2756 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2757 }
2758 if (subtype != NULL) {
2759 if (last == NULL) {
2760 type->subtypes = subtype;
2761 last = subtype;
2762 } else {
2763 last->next = subtype;
2764 last = subtype;
2765 }
2766 last->next = NULL;
2767 }
2768 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002769 }
2770 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002771 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
2772 "Choice %s has unexpected content\n", type->name,
2773 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002774 }
2775
2776 return (type);
2777}
2778
2779/**
2780 * xmlSchemaParseSequence:
2781 * @ctxt: a schema validation context
2782 * @schema: the schema being built
2783 * @node: a subtree containing XML Schema informations
2784 *
2785 * parse a XML schema Sequence definition
2786 * *WARNING* this interface is highly subject to change
2787 *
2788 * Returns -1 in case of error, 0 if the declaration is inproper and
2789 * 1 in case of success.
2790 */
2791static xmlSchemaTypePtr
2792xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002793 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002794{
2795 xmlSchemaTypePtr type, subtype, last = NULL;
2796 xmlNodePtr child = NULL;
2797 xmlChar name[30];
2798
2799 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2800 return (NULL);
2801
2802
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002803 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002804 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002805 if (type == NULL)
2806 return (NULL);
2807 type->node = node;
2808 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002809 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2811 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2812
2813 child = node->children;
2814 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002815 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2816 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002817 }
2818 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002819 (IS_SCHEMA(child, "group")) ||
2820 (IS_SCHEMA(child, "any")) ||
2821 (IS_SCHEMA(child, "choice")) ||
2822 (IS_SCHEMA(child, "sequence"))) {
2823 subtype = NULL;
2824 if (IS_SCHEMA(child, "element")) {
2825 subtype = (xmlSchemaTypePtr)
2826 xmlSchemaParseElement(ctxt, schema, child, 0);
2827 } else if (IS_SCHEMA(child, "group")) {
2828 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2829 } else if (IS_SCHEMA(child, "any")) {
2830 subtype = xmlSchemaParseAny(ctxt, schema, child);
2831 } else if (IS_SCHEMA(child, "choice")) {
2832 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2833 } else if (IS_SCHEMA(child, "sequence")) {
2834 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2835 }
2836 if (subtype != NULL) {
2837 if (last == NULL) {
2838 type->subtypes = subtype;
2839 last = subtype;
2840 } else {
2841 last->next = subtype;
2842 last = subtype;
2843 }
2844 last->next = NULL;
2845 }
2846 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002847 }
2848 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002849 xmlSchemaPErr2(ctxt, node, child,
2850 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2851 "Sequence %s has unexpected content\n", type->name,
2852 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002853 }
2854
2855 return (type);
2856}
2857
2858/**
2859 * xmlSchemaParseRestriction:
2860 * @ctxt: a schema validation context
2861 * @schema: the schema being built
2862 * @node: a subtree containing XML Schema informations
2863 * @simple: is that part of a simple type.
2864 *
2865 * parse a XML schema Restriction definition
2866 * *WARNING* this interface is highly subject to change
2867 *
2868 * Returns the type definition or NULL in case of error
2869 */
2870static xmlSchemaTypePtr
2871xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2872 xmlNodePtr node, int simple)
2873{
2874 xmlSchemaTypePtr type, subtype;
2875 xmlSchemaFacetPtr facet, lastfacet = NULL;
2876 xmlNodePtr child = NULL;
2877 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002878 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002879
2880 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2881 return (NULL);
2882
2883 oldcontainer = ctxt->container;
2884
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002885 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002886 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002887 if (type == NULL)
2888 return (NULL);
2889 type->node = node;
2890 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002891 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002892 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2893 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002894 xmlSchemaPErr2(ctxt, node, child,
2895 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
2896 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002897 }
2898 ctxt->container = name;
2899
2900 child = node->children;
2901 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002902 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2903 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002904 }
2905 subtype = NULL;
2906
2907 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002908 subtype = (xmlSchemaTypePtr)
2909 xmlSchemaParseAll(ctxt, schema, child);
2910 child = child->next;
2911 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002912 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002913 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2914 child = child->next;
2915 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002916 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002917 subtype = (xmlSchemaTypePtr)
2918 xmlSchemaParseSequence(ctxt, schema, child);
2919 child = child->next;
2920 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002921 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002922 subtype = (xmlSchemaTypePtr)
2923 xmlSchemaParseGroup(ctxt, schema, child);
2924 child = child->next;
2925 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002926 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002927 if (IS_SCHEMA(child, "simpleType")) {
2928 subtype = (xmlSchemaTypePtr)
2929 xmlSchemaParseSimpleType(ctxt, schema, child);
2930 child = child->next;
2931 type->baseType = subtype;
2932 }
2933 /*
2934 * Facets
2935 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002936 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002937 (IS_SCHEMA(child, "minExclusive")) ||
2938 (IS_SCHEMA(child, "maxInclusive")) ||
2939 (IS_SCHEMA(child, "maxExclusive")) ||
2940 (IS_SCHEMA(child, "totalDigits")) ||
2941 (IS_SCHEMA(child, "fractionDigits")) ||
2942 (IS_SCHEMA(child, "pattern")) ||
2943 (IS_SCHEMA(child, "enumeration")) ||
2944 (IS_SCHEMA(child, "whiteSpace")) ||
2945 (IS_SCHEMA(child, "length")) ||
2946 (IS_SCHEMA(child, "maxLength")) ||
2947 (IS_SCHEMA(child, "minLength"))) {
2948 facet = xmlSchemaParseFacet(ctxt, schema, child);
2949 if (facet != NULL) {
2950 if (lastfacet == NULL) {
2951 type->facets = facet;
2952 lastfacet = facet;
2953 } else {
2954 lastfacet->next = facet;
2955 lastfacet = facet;
2956 }
2957 lastfacet->next = NULL;
2958 }
2959 child = child->next;
2960 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002961 }
2962 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2963 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002964 xmlSchemaPErr2(ctxt, node, child,
2965 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
2966 "Restriction %s has unexpected content\n",
2967 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002968 }
2969 ctxt->container = oldcontainer;
2970 return (type);
2971}
2972
2973/**
2974 * xmlSchemaParseExtension:
2975 * @ctxt: a schema validation context
2976 * @schema: the schema being built
2977 * @node: a subtree containing XML Schema informations
2978 *
2979 * parse a XML schema Extension definition
2980 * *WARNING* this interface is highly subject to change
2981 *
2982 * Returns the type definition or NULL in case of error
2983 */
2984static xmlSchemaTypePtr
2985xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002986 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002987{
2988 xmlSchemaTypePtr type, subtype;
2989 xmlNodePtr child = NULL;
2990 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002991 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002992
2993 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2994 return (NULL);
2995
2996 oldcontainer = ctxt->container;
2997
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002998 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002999 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003000 if (type == NULL)
3001 return (NULL);
3002 type->node = node;
3003 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003004 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003005 ctxt->container = name;
3006
3007 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3008 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003009 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3010 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003011 }
3012 child = node->children;
3013 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003014 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3015 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 }
3017 subtype = NULL;
3018
3019 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003020 subtype = xmlSchemaParseAll(ctxt, schema, child);
3021 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003022 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003023 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3024 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003025 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003026 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3027 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003028 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003029 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3030 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003031 }
3032 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003033 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003034 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3035 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003036 xmlSchemaPErr2(ctxt, node, child,
3037 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3038 "Extension %s has unexpected content\n", type->name,
3039 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 }
3041 ctxt->container = oldcontainer;
3042 return (type);
3043}
3044
3045/**
3046 * xmlSchemaParseSimpleContent:
3047 * @ctxt: a schema validation context
3048 * @schema: the schema being built
3049 * @node: a subtree containing XML Schema informations
3050 *
3051 * parse a XML schema SimpleContent definition
3052 * *WARNING* this interface is highly subject to change
3053 *
3054 * Returns the type definition or NULL in case of error
3055 */
3056static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003057xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3058 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003059{
3060 xmlSchemaTypePtr type, subtype;
3061 xmlNodePtr child = NULL;
3062 xmlChar name[30];
3063
3064 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3065 return (NULL);
3066
3067
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003069 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003070 if (type == NULL)
3071 return (NULL);
3072 type->node = node;
3073 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003074 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003075
3076 child = node->children;
3077 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003078 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003080 }
3081 subtype = NULL;
3082 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003083 subtype = (xmlSchemaTypePtr)
3084 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3085 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003086 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003087 subtype = (xmlSchemaTypePtr)
3088 xmlSchemaParseExtension(ctxt, schema, child);
3089 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003090 }
3091 type->subtypes = subtype;
3092 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003093 xmlSchemaPErr2(ctxt, node, child,
3094 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3095 "SimpleContent %s has unexpected content\n",
3096 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003097 }
3098 return (type);
3099}
3100
3101/**
3102 * xmlSchemaParseComplexContent:
3103 * @ctxt: a schema validation context
3104 * @schema: the schema being built
3105 * @node: a subtree containing XML Schema informations
3106 *
3107 * parse a XML schema ComplexContent definition
3108 * *WARNING* this interface is highly subject to change
3109 *
3110 * Returns the type definition or NULL in case of error
3111 */
3112static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003113xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3114 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003115{
3116 xmlSchemaTypePtr type, subtype;
3117 xmlNodePtr child = NULL;
3118 xmlChar name[30];
3119
3120 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3121 return (NULL);
3122
3123
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003124 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003125 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003126 if (type == NULL)
3127 return (NULL);
3128 type->node = node;
3129 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003130 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003131
3132 child = node->children;
3133 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003134 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3135 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003136 }
3137 subtype = NULL;
3138 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003139 subtype = (xmlSchemaTypePtr)
3140 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3141 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003142 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003143 subtype = (xmlSchemaTypePtr)
3144 xmlSchemaParseExtension(ctxt, schema, child);
3145 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003146 }
3147 type->subtypes = subtype;
3148 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003149 xmlSchemaPErr2(ctxt, node, child,
3150 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3151 "ComplexContent %s has unexpected content\n",
3152 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 }
3154 return (type);
3155}
3156
3157/**
3158 * xmlSchemaParseComplexType:
3159 * @ctxt: a schema validation context
3160 * @schema: the schema being built
3161 * @node: a subtree containing XML Schema informations
3162 *
3163 * parse a XML schema Complex Type definition
3164 * *WARNING* this interface is highly subject to change
3165 *
3166 * Returns the type definition or NULL in case of error
3167 */
3168static xmlSchemaTypePtr
3169xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3170 xmlNodePtr node)
3171{
3172 xmlSchemaTypePtr type, subtype;
3173 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003174 const xmlChar *name;
3175 const xmlChar *oldcontainer;
3176 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003177
3178 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3179 return (NULL);
3180
3181 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003182 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003183 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003184
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003185 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3186 name = (const xmlChar *)buf;
3187 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3188 } else {
3189 const xmlChar *local, *ns;
3190
3191 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3192 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003193 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003195 return (NULL);
3196 }
3197 type->node = node;
3198 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003199 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 ctxt->container = name;
3201
3202 child = node->children;
3203 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003204 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3205 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003206 }
3207 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003208 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3209 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3212 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003214 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003215
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003216 if (IS_SCHEMA(child, "all")) {
3217 subtype = xmlSchemaParseAll(ctxt, schema, child);
3218 child = child->next;
3219 } else if (IS_SCHEMA(child, "choice")) {
3220 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3221 child = child->next;
3222 } else if (IS_SCHEMA(child, "sequence")) {
3223 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3224 child = child->next;
3225 } else if (IS_SCHEMA(child, "group")) {
3226 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3227 child = child->next;
3228 }
3229 if (subtype != NULL)
3230 type->subtypes = subtype;
3231 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003232 }
3233 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003234 xmlSchemaPErr2(ctxt, node, child,
3235 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3236 "ComplexType %s has unexpected content\n",
3237 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 }
3239 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003240 return (type);
3241}
3242
3243
3244/**
3245 * xmlSchemaParseSchema:
3246 * @ctxt: a schema validation context
3247 * @node: a subtree containing XML Schema informations
3248 *
3249 * parse a XML schema definition from a node set
3250 * *WARNING* this interface is highly subject to change
3251 *
3252 * Returns the internal XML Schema structure built from the resource or
3253 * NULL in case of error
3254 */
3255static xmlSchemaPtr
3256xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3257{
3258 xmlSchemaPtr schema = NULL;
3259 xmlSchemaAnnotPtr annot;
3260 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003261 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003262 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003263
3264 if ((ctxt == NULL) || (node == NULL))
3265 return (NULL);
3266
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003267 nberrors = ctxt->nberrors;
3268 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003269 if (IS_SCHEMA(node, "schema")) {
3270 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003271 if (schema == NULL)
3272 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003273 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3274 if (val != NULL) {
3275 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3276 } else {
3277 schema->targetNamespace = NULL;
3278 }
3279 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3280 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3281 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003282 if (val != NULL) {
3283 if (xmlStrEqual(val, BAD_CAST "qualified"))
3284 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3285 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3286 xmlSchemaPErr2(ctxt, node, child,
3287 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3288 "Invalid value %s for elementFormDefault\n",
3289 val, NULL);
3290 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003291 } else {
3292 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3293 }
3294 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003295 if (val != NULL) {
3296 if (xmlStrEqual(val, BAD_CAST "qualified"))
3297 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3298 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3299 xmlSchemaPErr2(ctxt, node, child,
3300 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3301 "Invalid value %s for attributeFormDefault\n",
3302 val, NULL);
3303 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003304 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003305
3306 child = node->children;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003307 while ((IS_SCHEMA(child, "include")) ||
3308 (IS_SCHEMA(child, "import")) ||
3309 (IS_SCHEMA(child, "redefine")) ||
3310 (IS_SCHEMA(child, "annotation"))) {
3311 if (IS_SCHEMA(child, "annotation")) {
3312 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3313 if (schema->annot == NULL)
3314 schema->annot = annot;
3315 else
3316 xmlSchemaFreeAnnot(annot);
3317 } else if (IS_SCHEMA(child, "include")) {
3318 TODO} else if (IS_SCHEMA(child, "import")) {
3319 xmlSchemaParseImport(ctxt, schema, child);
3320 } else if (IS_SCHEMA(child, "redefine")) {
3321 TODO}
3322 child = child->next;
3323 }
3324 while (child != NULL) {
3325 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003326 xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003327 child = child->next;
3328 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003329 xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003330 child = child->next;
3331 } else if (IS_SCHEMA(child, "element")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003332 xmlSchemaParseElement(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003333 child = child->next;
3334 } else if (IS_SCHEMA(child, "attribute")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003335 xmlSchemaParseAttribute(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003336 child = child->next;
3337 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003338 xmlSchemaParseAttributeGroup(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003339 child = child->next;
3340 } else if (IS_SCHEMA(child, "group")) {
3341 xmlSchemaParseGroup(ctxt, schema, child);
3342 child = child->next;
3343 } else if (IS_SCHEMA(child, "notation")) {
3344 xmlSchemaParseNotation(ctxt, schema, child);
3345 child = child->next;
3346 } else {
3347 xmlSchemaPErr2(ctxt, node, child,
3348 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3349 "Schemas: unexpected element %s here \n",
3350 child->name, NULL);
3351 child = child->next;
3352 }
3353 while (IS_SCHEMA(child, "annotation")) {
3354 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3355 if (schema->annot == NULL)
3356 schema->annot = annot;
3357 else
3358 xmlSchemaFreeAnnot(annot);
3359 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003360 }
3361 }
3362 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003363 if (ctxt->nberrors != 0) {
3364 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003365 xmlSchemaFree(schema);
3366 schema = NULL;
3367 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003368 }
3369 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003370#ifdef DEBUG
3371 if (schema == NULL)
3372 xmlGenericError(xmlGenericErrorContext,
3373 "xmlSchemaParse() failed\n");
3374#endif
3375
3376 return (schema);
3377}
3378
3379/************************************************************************
3380 * *
3381 * Validating using Schemas *
3382 * *
3383 ************************************************************************/
3384
3385/************************************************************************
3386 * *
3387 * Reading/Writing Schemas *
3388 * *
3389 ************************************************************************/
3390
3391/**
3392 * xmlSchemaNewParserCtxt:
3393 * @URL: the location of the schema
3394 *
3395 * Create an XML Schemas parse context for that file/resource expected
3396 * to contain an XML Schemas file.
3397 *
3398 * Returns the parser context or NULL in case of error
3399 */
3400xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401xmlSchemaNewParserCtxt(const char *URL)
3402{
Daniel Veillard4255d502002-04-16 15:50:10 +00003403 xmlSchemaParserCtxtPtr ret;
3404
3405 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003406 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003407
3408 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3409 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003410 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3411 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003412 return (NULL);
3413 }
3414 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003415 ret->dict = xmlDictCreate();
3416 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003417 return (ret);
3418}
3419
3420/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003421 * xmlSchemaNewMemParserCtxt:
3422 * @buffer: a pointer to a char array containing the schemas
3423 * @size: the size of the array
3424 *
3425 * Create an XML Schemas parse context for that memory buffer expected
3426 * to contain an XML Schemas file.
3427 *
3428 * Returns the parser context or NULL in case of error
3429 */
3430xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003431xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3432{
Daniel Veillard6045c902002-10-09 21:13:59 +00003433 xmlSchemaParserCtxtPtr ret;
3434
3435 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003436 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003437
3438 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3439 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003440 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3441 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003442 return (NULL);
3443 }
3444 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3445 ret->buffer = buffer;
3446 ret->size = size;
3447 return (ret);
3448}
3449
3450/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003451 * xmlSchemaNewDocParserCtxt:
3452 * @doc: a preparsed document tree
3453 *
3454 * Create an XML Schemas parse context for that document.
3455 * NB. The document may be modified during the parsing process.
3456 *
3457 * Returns the parser context or NULL in case of error
3458 */
3459xmlSchemaParserCtxtPtr
3460xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3461{
3462 xmlSchemaParserCtxtPtr ret;
3463
3464 if (doc == NULL)
3465 return (NULL);
3466
3467 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3468 if (ret == NULL) {
3469 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3470 NULL);
3471 return (NULL);
3472 }
3473 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3474 ret->doc = doc;
3475
3476 return (ret);
3477}
3478
3479/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003480 * xmlSchemaFreeParserCtxt:
3481 * @ctxt: the schema parser context
3482 *
3483 * Free the resources associated to the schema parser context
3484 */
3485void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003486xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3487{
Daniel Veillard4255d502002-04-16 15:50:10 +00003488 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003489 return;
Daniel Veillard6045c902002-10-09 21:13:59 +00003490 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003492 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003493 xmlFree(ctxt);
3494}
3495
3496/************************************************************************
3497 * *
3498 * Building the content models *
3499 * *
3500 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003501
Daniel Veillard4255d502002-04-16 15:50:10 +00003502/**
3503 * xmlSchemaBuildAContentModel:
3504 * @type: the schema type definition
3505 * @ctxt: the schema parser context
3506 * @name: the element name whose content is being built
3507 *
3508 * Generate the automata sequence needed for that type
3509 */
3510static void
3511xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003512 xmlSchemaParserCtxtPtr ctxt,
3513 const xmlChar * name)
3514{
Daniel Veillard4255d502002-04-16 15:50:10 +00003515 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003516 xmlGenericError(xmlGenericErrorContext,
3517 "Found unexpected type = NULL in %s content model\n",
3518 name);
3519 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003520 }
3521 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003522 case XML_SCHEMA_TYPE_ANY:
3523 /* TODO : handle the namespace too */
3524 /* TODO : make that a specific transition type */
3525 TODO ctxt->state =
3526 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3527 BAD_CAST "*", NULL);
3528 break;
3529 case XML_SCHEMA_TYPE_ELEMENT:{
3530 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003531
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003532 /* TODO : handle the namespace too */
3533 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003534
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003535 if (elem->maxOccurs >= UNBOUNDED) {
3536 if (elem->minOccurs > 1) {
3537 xmlAutomataStatePtr tmp;
3538 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003539
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003540 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3541 oldstate,
3542 NULL);
3543 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003544
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003545 counter = xmlAutomataNewCounter(ctxt->am,
3546 elem->minOccurs -
3547 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003548
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003549 if (elem->refDecl != NULL) {
3550 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3551 elem->refDecl,
3552 ctxt,
3553 elem->refDecl->
3554 name);
3555 } else {
3556 ctxt->state =
3557 xmlAutomataNewTransition(ctxt->am,
3558 ctxt->state, NULL,
3559 elem->name, type);
3560 }
3561 tmp = ctxt->state;
3562 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3563 counter);
3564 ctxt->state =
3565 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3566 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003567
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003568 } else {
3569 if (elem->refDecl != NULL) {
3570 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3571 elem->refDecl,
3572 ctxt,
3573 elem->refDecl->
3574 name);
3575 } else {
3576 ctxt->state =
3577 xmlAutomataNewTransition(ctxt->am,
3578 ctxt->state, NULL,
3579 elem->name, type);
3580 }
3581 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3582 oldstate);
3583 if (elem->minOccurs == 0) {
3584 /* basically an elem* */
3585 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3586 ctxt->state);
3587 }
3588 }
3589 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3590 xmlAutomataStatePtr tmp;
3591 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003592
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003593 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3594 oldstate, NULL);
3595 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003596
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003597 counter = xmlAutomataNewCounter(ctxt->am,
3598 elem->minOccurs - 1,
3599 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003600
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003601 if (elem->refDecl != NULL) {
3602 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3603 elem->refDecl, ctxt,
3604 elem->refDecl->name);
3605 } else {
3606 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3607 ctxt->state,
3608 NULL,
3609 elem->name,
3610 type);
3611 }
3612 tmp = ctxt->state;
3613 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3614 counter);
3615 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3616 NULL,
3617 counter);
3618 if (elem->minOccurs == 0) {
3619 /* basically an elem? */
3620 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3621 ctxt->state);
3622 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003623
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 } else {
3625 if (elem->refDecl != NULL) {
3626 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3627 elem->refDecl, ctxt,
3628 elem->refDecl->name);
3629 } else {
3630 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3631 ctxt->state,
3632 NULL,
3633 elem->name,
3634 type);
3635 }
3636 if (elem->minOccurs == 0) {
3637 /* basically an elem? */
3638 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3639 ctxt->state);
3640 }
3641 }
3642 break;
3643 }
3644 case XML_SCHEMA_TYPE_SEQUENCE:{
3645 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003646
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 /*
3648 * If max and min occurances are default (1) then
3649 * simply iterate over the subtypes
3650 */
3651 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
3652 subtypes = type->subtypes;
3653 while (subtypes != NULL) {
3654 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3655 subtypes = subtypes->next;
3656 }
3657 } else {
3658 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003659
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003660 if (type->maxOccurs >= UNBOUNDED) {
3661 if (type->minOccurs > 1) {
3662 xmlAutomataStatePtr tmp;
3663 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003664
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3666 oldstate,
3667 NULL);
3668 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003669
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003670 counter = xmlAutomataNewCounter(ctxt->am,
3671 type->
3672 minOccurs - 1,
3673 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003675 subtypes = type->subtypes;
3676 while (subtypes != NULL) {
3677 xmlSchemaBuildAContentModel(subtypes, ctxt,
3678 name);
3679 subtypes = subtypes->next;
3680 }
3681 tmp = ctxt->state;
3682 xmlAutomataNewCountedTrans(ctxt->am, tmp,
3683 oldstate, counter);
3684 ctxt->state =
3685 xmlAutomataNewCounterTrans(ctxt->am, tmp,
3686 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003687
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 } else {
3689 subtypes = type->subtypes;
3690 while (subtypes != NULL) {
3691 xmlSchemaBuildAContentModel(subtypes, ctxt,
3692 name);
3693 subtypes = subtypes->next;
3694 }
3695 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3696 oldstate);
3697 if (type->minOccurs == 0) {
3698 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3699 ctxt->state);
3700 }
3701 }
3702 } else if ((type->maxOccurs > 1)
3703 || (type->minOccurs > 1)) {
3704 xmlAutomataStatePtr tmp;
3705 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003707 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3708 oldstate,
3709 NULL);
3710 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00003711
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003712 counter = xmlAutomataNewCounter(ctxt->am,
3713 type->minOccurs -
3714 1,
3715 type->maxOccurs -
3716 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003717
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003718 subtypes = type->subtypes;
3719 while (subtypes != NULL) {
3720 xmlSchemaBuildAContentModel(subtypes, ctxt,
3721 name);
3722 subtypes = subtypes->next;
3723 }
3724 tmp = ctxt->state;
3725 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3726 counter);
3727 ctxt->state =
3728 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3729 counter);
3730 if (type->minOccurs == 0) {
3731 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3732 ctxt->state);
3733 }
Daniel Veillardb509f152002-04-17 16:28:10 +00003734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003735 } else {
3736 subtypes = type->subtypes;
3737 while (subtypes != NULL) {
3738 xmlSchemaBuildAContentModel(subtypes, ctxt,
3739 name);
3740 subtypes = subtypes->next;
3741 }
3742 if (type->minOccurs == 0) {
3743 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3744 ctxt->state);
3745 }
3746 }
3747 }
3748 break;
3749 }
3750 case XML_SCHEMA_TYPE_CHOICE:{
3751 xmlSchemaTypePtr subtypes;
3752 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00003753
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003754 start = ctxt->state;
3755 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00003756
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 /*
3758 * iterate over the subtypes and remerge the end with an
3759 * epsilon transition
3760 */
3761 if (type->maxOccurs == 1) {
3762 subtypes = type->subtypes;
3763 while (subtypes != NULL) {
3764 ctxt->state = start;
3765 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3766 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3767 subtypes = subtypes->next;
3768 }
3769 } else {
3770 int counter;
3771 xmlAutomataStatePtr hop;
3772 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3773 UNBOUNDED : type->maxOccurs - 1;
3774 int minOccurs =
3775 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00003776
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 /*
3778 * use a counter to keep track of the number of transtions
3779 * which went through the choice.
3780 */
3781 counter =
3782 xmlAutomataNewCounter(ctxt->am, minOccurs,
3783 maxOccurs);
3784 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00003785
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003786 subtypes = type->subtypes;
3787 while (subtypes != NULL) {
3788 ctxt->state = start;
3789 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3790 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3791 subtypes = subtypes->next;
3792 }
3793 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
3794 counter);
3795 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
3796 counter);
3797 }
3798 if (type->minOccurs == 0) {
3799 xmlAutomataNewEpsilon(ctxt->am, start, end);
3800 }
3801 ctxt->state = end;
3802 break;
3803 }
3804 case XML_SCHEMA_TYPE_ALL:{
3805 xmlAutomataStatePtr start;
3806 xmlSchemaTypePtr subtypes;
3807 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3808 int lax;
3809
3810 subtypes = type->subtypes;
3811 if (subtypes == NULL)
3812 break;
3813 start = ctxt->state;
3814 while (subtypes != NULL) {
3815 ctxt->state = start;
3816 elem = (xmlSchemaElementPtr) subtypes;
3817
3818 /* TODO : handle the namespace too */
3819 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3820 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
3821 ctxt->state, elem->name, 1,
3822 1, subtypes);
3823 } else {
3824 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
3825 ctxt->state, elem->name,
3826 elem->minOccurs,
3827 elem->maxOccurs,
3828 subtypes);
3829 }
3830 subtypes = subtypes->next;
3831 }
3832 lax = type->minOccurs == 0;
3833 ctxt->state =
3834 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3835 lax);
3836 break;
3837 }
3838 case XML_SCHEMA_TYPE_RESTRICTION:
3839 if (type->subtypes != NULL)
3840 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3841 break;
3842 case XML_SCHEMA_TYPE_EXTENSION:
3843 if (type->baseType != NULL) {
3844 xmlSchemaTypePtr subtypes;
3845
3846 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3847 subtypes = type->subtypes;
3848 while (subtypes != NULL) {
3849 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3850 subtypes = subtypes->next;
3851 }
3852 } else if (type->subtypes != NULL)
3853 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3854 break;
3855 case XML_SCHEMA_TYPE_GROUP:
3856 if (type->subtypes == NULL) {
3857 }
3858 case XML_SCHEMA_TYPE_COMPLEX:
3859 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3860 if (type->subtypes != NULL)
3861 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3862 break;
3863 default:
3864 xmlGenericError(xmlGenericErrorContext,
3865 "Found unexpected type %d in %s content model\n",
3866 type->type, name);
3867 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003868 }
3869}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003870
Daniel Veillard4255d502002-04-16 15:50:10 +00003871/**
3872 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003873 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003875 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00003876 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003877 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00003878 */
3879static void
3880xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003881 xmlSchemaParserCtxtPtr ctxt,
3882 const xmlChar * name)
3883{
Daniel Veillard4255d502002-04-16 15:50:10 +00003884 xmlAutomataStatePtr start;
3885
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003887 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003888 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3890 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003891 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003892 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003894 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
3895 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003896 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003897
3898#ifdef DEBUG_CONTENT
3899 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003900 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003901#endif
3902
Daniel Veillard4255d502002-04-16 15:50:10 +00003903 ctxt->am = xmlNewAutomata();
3904 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003905 xmlGenericError(xmlGenericErrorContext,
3906 "Cannot create automata for elem %s\n", name);
3907 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003908 }
3909 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3910 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3911 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00003912 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003913 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003914 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
3915 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003916 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
3918 "Content model of %s is not determinist:\n", name,
3919 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003920 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00003921#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003922 xmlGenericError(xmlGenericErrorContext,
3923 "Content model of %s:\n", name);
3924 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003925#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003926 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003927 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003928 xmlFreeAutomata(ctxt->am);
3929 ctxt->am = NULL;
3930}
3931
3932/**
3933 * xmlSchemaRefFixupCallback:
3934 * @elem: the schema element context
3935 * @ctxt: the schema parser context
3936 *
3937 * Free the resources associated to the schema parser context
3938 */
3939static void
3940xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003941 xmlSchemaParserCtxtPtr ctxt,
3942 const xmlChar * name,
3943 const xmlChar * context ATTRIBUTE_UNUSED,
3944 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003945{
3946 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003947 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003948 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003949 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003950
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003951 if (elem->subtypes != NULL) {
3952 xmlSchemaPErr(ctxt, elem->node,
3953 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
3954 "Schemas: element %s have both ref and subtype\n",
3955 name, NULL);
3956 return;
3957 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00003958 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00003959
3960 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003961 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
3962 "Schemas: element %s ref to %s not found\n",
3963 name, elem->ref);
3964 return;
3965 }
3966 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003967 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003968 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003969
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003970 if (elem->subtypes != NULL) {
3971 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
3972 "Schemas: element %s have both type and subtype\n",
3973 name, NULL);
3974 return;
3975 }
3976 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3977 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003978
3979 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003980 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
3981 "Schemas: element %s type %s not found\n", name,
3982 elem->namedType);
3983 return;
3984 }
3985 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003986 }
3987}
3988
3989/**
3990 * xmlSchemaTypeFixup:
3991 * @typeDecl: the schema type definition
3992 * @ctxt: the schema parser context
3993 *
3994 * Fixes the content model of the type.
3995 */
3996static void
3997xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003998 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003999{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004000 if (typeDecl == NULL)
4001 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004002 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004003 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004004 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004005 switch (typeDecl->type) {
4006 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4007 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4008 if (typeDecl->subtypes != NULL)
4009 typeDecl->contentType =
4010 typeDecl->subtypes->contentType;
4011 break;
4012 }
4013 case XML_SCHEMA_TYPE_RESTRICTION:{
4014 if (typeDecl->subtypes != NULL)
4015 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004016
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004017 if (typeDecl->base != NULL) {
4018 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004019
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004020 baseType =
4021 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4022 typeDecl->baseNs);
4023 if (baseType == NULL) {
4024 xmlSchemaPErr(ctxt, typeDecl->node,
4025 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004026 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004027 name, typeDecl->base);
4028 }
4029 typeDecl->baseType = baseType;
4030 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004031 if (typeDecl->subtypes == NULL)
4032 if (typeDecl->baseType != NULL)
4033 typeDecl->contentType =
4034 typeDecl->baseType->contentType;
4035 else
4036 /* 1.1.1 */
4037 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004038 else if ((typeDecl->subtypes->subtypes == NULL) &&
4039 ((typeDecl->subtypes->type ==
4040 XML_SCHEMA_TYPE_ALL)
4041 || (typeDecl->subtypes->type ==
4042 XML_SCHEMA_TYPE_SEQUENCE)))
4043 /* 1.1.2 */
4044 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4045 else if ((typeDecl->subtypes->type ==
4046 XML_SCHEMA_TYPE_CHOICE)
4047 && (typeDecl->subtypes->subtypes == NULL))
4048 /* 1.1.3 */
4049 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4050 else {
4051 /* 1.2 and 2.X are applied at the other layer */
4052 typeDecl->contentType =
4053 XML_SCHEMA_CONTENT_ELEMENTS;
4054 }
4055 break;
4056 }
4057 case XML_SCHEMA_TYPE_EXTENSION:{
4058 xmlSchemaContentType explicitContentType;
4059 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004060
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004061 if (typeDecl->base != NULL) {
4062 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004063
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004064 baseType =
4065 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4066 typeDecl->baseNs);
4067 if (baseType == NULL) {
4068 xmlSchemaPErr(ctxt, typeDecl->node,
4069 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004070 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004071 name, typeDecl->base);
4072 }
4073 typeDecl->baseType = baseType;
4074 }
4075 if (typeDecl->subtypes != NULL)
4076 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004077
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004078 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4079 if (typeDecl->subtypes == NULL)
4080 /* 1.1.1 */
4081 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4082 else if ((typeDecl->subtypes->subtypes == NULL) &&
4083 ((typeDecl->subtypes->type ==
4084 XML_SCHEMA_TYPE_ALL)
4085 || (typeDecl->subtypes->type ==
4086 XML_SCHEMA_TYPE_SEQUENCE)))
4087 /* 1.1.2 */
4088 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4089 else if ((typeDecl->subtypes->type ==
4090 XML_SCHEMA_TYPE_CHOICE)
4091 && (typeDecl->subtypes->subtypes == NULL))
4092 /* 1.1.3 */
4093 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004095 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4096 typeDecl->baseNs);
4097 if (base == NULL) {
4098 xmlSchemaPErr(ctxt, typeDecl->node,
4099 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4100 "Schemas: base type %s of type %s not found\n",
4101 typeDecl->base, name);
4102 return;
4103 }
4104 xmlSchemaTypeFixup(base, ctxt, NULL);
4105 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4106 /* 2.1 */
4107 typeDecl->contentType = base->contentType;
4108 } else if (base->contentType ==
4109 XML_SCHEMA_CONTENT_EMPTY) {
4110 /* 2.2 imbitable ! */
4111 typeDecl->contentType =
4112 XML_SCHEMA_CONTENT_ELEMENTS;
4113 } else {
4114 /* 2.3 imbitable pareil ! */
4115 typeDecl->contentType =
4116 XML_SCHEMA_CONTENT_ELEMENTS;
4117 }
4118 break;
4119 }
4120 case XML_SCHEMA_TYPE_COMPLEX:{
4121 if (typeDecl->subtypes == NULL) {
4122 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4123 } else {
4124 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4125 typeDecl->contentType =
4126 XML_SCHEMA_CONTENT_MIXED;
4127 else {
4128 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4129 NULL);
4130 if (typeDecl->subtypes != NULL)
4131 typeDecl->contentType =
4132 typeDecl->subtypes->contentType;
4133 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004134 if (typeDecl->attributes == NULL)
4135 typeDecl->attributes =
4136 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137 }
4138 break;
4139 }
4140 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4141 if (typeDecl->subtypes == NULL) {
4142 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4143 } else {
4144 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4145 typeDecl->contentType =
4146 XML_SCHEMA_CONTENT_MIXED;
4147 else {
4148 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4149 NULL);
4150 if (typeDecl->subtypes != NULL)
4151 typeDecl->contentType =
4152 typeDecl->subtypes->contentType;
4153 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004154 if (typeDecl->attributes == NULL)
4155 typeDecl->attributes =
4156 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004157 }
4158 break;
4159 }
4160 case XML_SCHEMA_TYPE_SEQUENCE:
4161 case XML_SCHEMA_TYPE_GROUP:
4162 case XML_SCHEMA_TYPE_ALL:
4163 case XML_SCHEMA_TYPE_CHOICE:
4164 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4165 break;
4166 case XML_SCHEMA_TYPE_BASIC:
4167 case XML_SCHEMA_TYPE_ANY:
4168 case XML_SCHEMA_TYPE_FACET:
4169 case XML_SCHEMA_TYPE_SIMPLE:
4170 case XML_SCHEMA_TYPE_UR:
4171 case XML_SCHEMA_TYPE_ELEMENT:
4172 case XML_SCHEMA_TYPE_ATTRIBUTE:
4173 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4174 case XML_SCHEMA_TYPE_NOTATION:
4175 case XML_SCHEMA_TYPE_LIST:
4176 case XML_SCHEMA_TYPE_UNION:
4177 case XML_SCHEMA_FACET_MININCLUSIVE:
4178 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4179 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4180 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4181 case XML_SCHEMA_FACET_TOTALDIGITS:
4182 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4183 case XML_SCHEMA_FACET_PATTERN:
4184 case XML_SCHEMA_FACET_ENUMERATION:
4185 case XML_SCHEMA_FACET_WHITESPACE:
4186 case XML_SCHEMA_FACET_LENGTH:
4187 case XML_SCHEMA_FACET_MAXLENGTH:
4188 case XML_SCHEMA_FACET_MINLENGTH:
4189 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004190 if (typeDecl->subtypes != NULL)
4191 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004192 break;
4193 }
4194 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004195#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004196 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004197 xmlGenericError(xmlGenericErrorContext,
4198 "Type of %s : %s:%d :", name,
4199 typeDecl->node->doc->URL,
4200 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004201 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004202 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004203 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004204 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004205 case XML_SCHEMA_CONTENT_SIMPLE:
4206 xmlGenericError(xmlGenericErrorContext, "simple\n");
4207 break;
4208 case XML_SCHEMA_CONTENT_ELEMENTS:
4209 xmlGenericError(xmlGenericErrorContext, "elements\n");
4210 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004211 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004212 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4213 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004214 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004215 xmlGenericError(xmlGenericErrorContext, "empty\n");
4216 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004217 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4219 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004220 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004221 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4222 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004223 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004224 xmlGenericError(xmlGenericErrorContext, "basic\n");
4225 break;
4226 default:
4227 xmlGenericError(xmlGenericErrorContext,
4228 "not registered !!!\n");
4229 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004230 }
4231#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004232}
4233
4234/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004235 * xmlSchemaCheckFacet:
4236 * @facet: the facet
4237 * @typeDecl: the schema type definition
4238 * @ctxt: the schema parser context or NULL
4239 * @name: name of the type
4240 *
4241 * Checks the default values types, especially for facets
4242 *
4243 * Returns 0 if okay or -1 in cae of error
4244 */
4245int
4246xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247 xmlSchemaTypePtr typeDecl,
4248 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004249{
4250 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4251 int ret = 0;
4252
4253 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004254 nonNegativeIntegerType =
4255 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4256 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004257 }
4258 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004259 case XML_SCHEMA_FACET_MININCLUSIVE:
4260 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4261 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4262 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4263 /*
4264 * Okay we need to validate the value
4265 * at that point.
4266 */
4267 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004268
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004269 vctxt = xmlSchemaNewValidCtxt(NULL);
4270 if (vctxt == NULL)
4271 break;
4272 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4273 facet->value);
4274 facet->val = vctxt->value;
4275 vctxt->value = NULL;
4276 if (facet->val == NULL) {
4277 /* error code */
4278 if (ctxt != NULL) {
4279 xmlSchemaPErr(ctxt, facet->node,
4280 XML_SCHEMAP_INVALID_FACET,
4281 "Schemas: type %s facet value %s invalid\n",
4282 name, facet->value);
4283 }
4284 ret = -1;
4285 }
4286 xmlSchemaFreeValidCtxt(vctxt);
4287 break;
4288 }
4289 case XML_SCHEMA_FACET_ENUMERATION:{
4290 /*
4291 * Okay we need to validate the value
4292 * at that point.
4293 */
4294 xmlSchemaValidCtxtPtr vctxt;
4295 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004296
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004297 vctxt = xmlSchemaNewValidCtxt(NULL);
4298 if (vctxt == NULL)
4299 break;
4300 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4301 facet->value);
4302 if (tmp != 0) {
4303 if (ctxt != NULL) {
4304 xmlSchemaPErr(ctxt, facet->node,
4305 XML_SCHEMAP_INVALID_ENUM,
4306 "Schemas: type %s enumeration value %s invalid\n",
4307 name, facet->value);
4308 }
4309 ret = -1;
4310 }
4311 xmlSchemaFreeValidCtxt(vctxt);
4312 break;
4313 }
4314 case XML_SCHEMA_FACET_PATTERN:
4315 facet->regexp = xmlRegexpCompile(facet->value);
4316 if (facet->regexp == NULL) {
4317 xmlSchemaPErr(ctxt, typeDecl->node,
4318 XML_SCHEMAP_REGEXP_INVALID,
4319 "Schemas: type %s facet regexp %s invalid\n",
4320 name, facet->value);
4321 ret = -1;
4322 }
4323 break;
4324 case XML_SCHEMA_FACET_TOTALDIGITS:
4325 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4326 case XML_SCHEMA_FACET_LENGTH:
4327 case XML_SCHEMA_FACET_MAXLENGTH:
4328 case XML_SCHEMA_FACET_MINLENGTH:{
4329 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004330
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004331 tmp =
4332 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4333 facet->value,
4334 &facet->val);
4335 if (tmp != 0) {
4336 /* error code */
4337 if (ctxt != NULL) {
4338 xmlSchemaPErr(ctxt, facet->node,
4339 XML_SCHEMAP_INVALID_FACET_VALUE,
4340 "Schemas: type %s facet value %s invalid\n",
4341 name, facet->value);
4342 }
4343 ret = -1;
4344 }
4345 break;
4346 }
4347 case XML_SCHEMA_FACET_WHITESPACE:{
4348 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4349 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4350 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4351 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4352 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4353 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4354 } else {
4355 if (ctxt != NULL) {
4356 xmlSchemaPErr(ctxt, facet->node,
4357 XML_SCHEMAP_INVALID_WHITE_SPACE,
4358 "Schemas: type %s whiteSpace value %s invalid\n",
4359 name, facet->value);
4360 }
4361 ret = -1;
4362 }
4363 }
4364 default:
4365 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004366 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004367 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004368}
4369
4370/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 * xmlSchemaCheckDefaults:
4372 * @typeDecl: the schema type definition
4373 * @ctxt: the schema parser context
4374 *
4375 * Checks the default values types, especially for facets
4376 */
4377static void
4378xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004379 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004380{
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004382 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004383 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004384 if (typeDecl->facets != NULL) {
4385 xmlSchemaFacetPtr facet = typeDecl->facets;
4386
4387 while (facet != NULL) {
4388 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4389 facet = facet->next;
4390 }
4391 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004392 }
4393}
4394
4395/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004396 * xmlSchemaAttrGrpFixup:
4397 * @attrgrpDecl: the schema attribute definition
4398 * @ctxt: the schema parser context
4399 * @name: the attribute name
4400 *
4401 * Fixes finish doing the computations on the attributes definitions
4402 */
4403static void
4404xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004405 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004406{
4407 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004409 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004410 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004411 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004412 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004413
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4415 attrgrpDecl->refNs);
4416 if (ref == NULL) {
4417 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4418 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4419 "Schemas: attribute group %s reference %s not found\n",
4420 name, attrgrpDecl->ref);
4421 return;
4422 }
4423 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4424 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004425 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004426 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4427 "Schemas: attribute %s has no attributes nor reference\n",
4428 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004429 }
4430}
4431
4432/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004433 * xmlSchemaAttrFixup:
4434 * @attrDecl: the schema attribute definition
4435 * @ctxt: the schema parser context
4436 * @name: the attribute name
4437 *
4438 * Fixes finish doing the computations on the attributes definitions
4439 */
4440static void
4441xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004442 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004443{
4444 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004445 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004449 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004450
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004451 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4452 attrDecl->typeNs);
4453 if (type == NULL) {
4454 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4455 "Schemas: attribute %s type %s not found\n",
4456 name, attrDecl->typeName);
4457 }
4458 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004459 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004460 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004461
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004462 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4463 attrDecl->refNs);
4464 if (ref == NULL) {
4465 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4466 "Schemas: attribute %s reference %s not found\n",
4467 name, attrDecl->ref);
4468 return;
4469 }
4470 xmlSchemaAttrFixup(ref, ctxt, NULL);
4471 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004472 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4474 "Schemas: attribute %s has no type nor reference\n",
4475 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 }
4477}
4478
4479/**
4480 * xmlSchemaParse:
4481 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004482 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004483 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 * XML Shema struture which can be used to validate instances.
4485 * *WARNING* this interface is highly subject to change
4486 *
4487 * Returns the internal XML Schema structure built from the resource or
4488 * NULL in case of error
4489 */
4490xmlSchemaPtr
4491xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4492{
4493 xmlSchemaPtr ret = NULL;
4494 xmlDocPtr doc;
4495 xmlNodePtr root, cur, delete;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004496 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004497
4498 xmlSchemaInitTypes();
4499
Daniel Veillard6045c902002-10-09 21:13:59 +00004500 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004501 return (NULL);
4502
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004503 nberrors = ctxt->nberrors;
4504 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 ctxt->counter = 0;
4506 ctxt->container = NULL;
4507
4508 /*
4509 * First step is to parse the input document into an DOM/Infoset
4510 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004511 if (ctxt->URL != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004512 doc = xmlParseFile((const char *) ctxt->URL);
4513 if (doc == NULL) {
4514 xmlSchemaPErr(ctxt, NULL,
4515 XML_SCHEMAP_FAILED_LOAD,
4516 "xmlSchemaParse: could not load %s\n",
4517 ctxt->URL, NULL);
4518 return (NULL);
4519 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004520 } else if (ctxt->buffer != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004521 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4522 if (doc == NULL) {
4523 xmlSchemaPErr(ctxt, NULL,
4524 XML_SCHEMAP_FAILED_PARSE,
4525 "xmlSchemaParse: could not parse\n",
4526 NULL, NULL);
4527 return (NULL);
4528 }
4529 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4530 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard9d751502003-10-29 13:21:47 +00004531 } else if (ctxt->doc != NULL) {
4532 doc = ctxt->doc;
Daniel Veillard6045c902002-10-09 21:13:59 +00004533 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004534 xmlSchemaPErr(ctxt, NULL,
4535 XML_SCHEMAP_NOTHING_TO_PARSE,
4536 "xmlSchemaParse: could not parse\n",
4537 NULL, NULL);
4538 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 }
4540
4541 /*
4542 * Then extract the root and Schema parse it
4543 */
4544 root = xmlDocGetRootElement(doc);
4545 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004546 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4547 XML_SCHEMAP_NOROOT,
4548 "schemas has no root", NULL, NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004549 xmlFreeDoc(doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 return (NULL);
4551 }
4552
4553 /*
4554 * Remove all the blank text nodes
4555 */
4556 delete = NULL;
4557 cur = root;
4558 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004559 if (delete != NULL) {
4560 xmlUnlinkNode(delete);
4561 xmlFreeNode(delete);
4562 delete = NULL;
4563 }
4564 if (cur->type == XML_TEXT_NODE) {
4565 if (IS_BLANK_NODE(cur)) {
4566 if (xmlNodeGetSpacePreserve(cur) != 1) {
4567 delete = cur;
4568 }
4569 }
4570 } else if ((cur->type != XML_ELEMENT_NODE) &&
4571 (cur->type != XML_CDATA_SECTION_NODE)) {
4572 delete = cur;
4573 goto skip_children;
4574 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004575
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 /*
4577 * Skip to next node
4578 */
4579 if (cur->children != NULL) {
4580 if ((cur->children->type != XML_ENTITY_DECL) &&
4581 (cur->children->type != XML_ENTITY_REF_NODE) &&
4582 (cur->children->type != XML_ENTITY_NODE)) {
4583 cur = cur->children;
4584 continue;
4585 }
4586 }
4587 skip_children:
4588 if (cur->next != NULL) {
4589 cur = cur->next;
4590 continue;
4591 }
4592
4593 do {
4594 cur = cur->parent;
4595 if (cur == NULL)
4596 break;
4597 if (cur == root) {
4598 cur = NULL;
4599 break;
4600 }
4601 if (cur->next != NULL) {
4602 cur = cur->next;
4603 break;
4604 }
4605 } while (cur != NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004606 }
4607 if (delete != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004608 xmlUnlinkNode(delete);
4609 xmlFreeNode(delete);
4610 delete = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004611 }
4612
4613 /*
4614 * Then do the parsing for good
4615 */
4616 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004617 if (ret == NULL) {
4618 xmlFreeDoc(doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004619 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004620 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004621 ret->doc = doc;
4622
4623 /*
4624 * Then fix all the references.
4625 */
4626 ctxt->schema = ret;
4627 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004628 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004629
4630 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004631 * Then fixup all attributes declarations
4632 */
4633 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4634
4635 /*
4636 * Then fixup all attributes group declarations
4637 */
4638 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4639 ctxt);
4640
4641 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00004642 * Then fixup all types properties
4643 */
4644 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4645
4646 /*
4647 * Then build the content model for all elements
4648 */
4649 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004651
4652 /*
4653 * Then check the defaults part of the type like facets values
4654 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004655 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4656 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004657
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004658 if (ctxt->nberrors != 0) {
4659 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004660 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004661 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004662 return (ret);
4663}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004664
Daniel Veillard4255d502002-04-16 15:50:10 +00004665/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004666 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004667 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004668 * @err: the error callback
4669 * @warn: the warning callback
4670 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004671 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004672 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 */
4674void
4675xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004676 xmlSchemaValidityErrorFunc err,
4677 xmlSchemaValidityWarningFunc warn, void *ctx)
4678{
Daniel Veillard4255d502002-04-16 15:50:10 +00004679 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004680 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004681 ctxt->error = err;
4682 ctxt->warning = warn;
4683 ctxt->userData = ctx;
4684}
4685
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004686/**
4687 * xmlSchemaFacetTypeToString:
4688 * @type: the facet type
4689 *
4690 * Convert the xmlSchemaTypeType to a char string.
4691 *
4692 * Returns the char string representation of the facet type if the
4693 * type is a facet and an "Internal Error" string otherwise.
4694 */
4695static const char *
4696xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4697{
4698 switch (type) {
4699 case XML_SCHEMA_FACET_PATTERN:
4700 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004701 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004702 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004703 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004704 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004705 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004706 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004707 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004708 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004709 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004710 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004711 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004712 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004713 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004714 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004715 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004716 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004717 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004718 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004719 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004720 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004721 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004722 return ("fractionDigits");
4723 default:
4724 break;
4725 }
4726 return ("Internal Error");
4727}
4728
4729/**
4730 * xmlSchemaValidateFacets:
4731 * @ctxt: a schema validation context
4732 * @base: the base type
4733 * @facets: the list of facets to check
4734 * @value: the lexical repr of the value to validate
4735 * @val: the precomputed value
4736 *
4737 * Check a value against all facet conditions
4738 *
4739 * Returns 0 if the element is schemas valid, a positive error code
4740 * number otherwise and -1 in case of internal or API error.
4741 */
4742static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004743xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4744 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004745 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004746{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004747 int ret = 0;
4748 int tmp = 0;
4749 xmlSchemaTypeType type;
4750 xmlSchemaFacetPtr facet = facets;
4751
4752 while (facet != NULL) {
4753 type = facet->type;
4754 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004755 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004756
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004757 while (facet != NULL) {
4758 tmp =
4759 xmlSchemaValidateFacet(base, facet, value,
4760 ctxt->value);
4761 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004762 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004763 }
4764 facet = facet->next;
4765 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004766 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004767 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004768
4769 if (tmp != 0) {
4770 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004771 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 +00004772 }
4773 if (facet != NULL)
4774 facet = facet->next;
4775 }
4776 return (ret);
4777}
4778
Daniel Veillard4255d502002-04-16 15:50:10 +00004779/************************************************************************
4780 * *
4781 * Simple type validation *
4782 * *
4783 ************************************************************************/
4784
4785/**
4786 * xmlSchemaValidateSimpleValue:
4787 * @ctxt: a schema validation context
4788 * @type: the type declaration
4789 * @value: the value to validate
4790 *
4791 * Validate a value against a simple type
4792 *
4793 * Returns 0 if the value is valid, a positive error code
4794 * number otherwise and -1 in case of internal or API error.
4795 */
4796static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004797xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004798 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004799{
Daniel Veillard4255d502002-04-16 15:50:10 +00004800 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004801
Daniel Veillard4255d502002-04-16 15:50:10 +00004802 /*
4803 * First normalize the value accordingly to Schema Datatype
4804 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4805 */
4806 /*
4807 * Then check the normalized value against the lexical space of the
4808 * type.
4809 */
4810 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004811 if (ctxt->value != NULL) {
4812 xmlSchemaFreeValue(ctxt->value);
4813 ctxt->value = NULL;
4814 }
4815 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4816 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004817 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004818 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 +00004819 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004821 xmlSchemaTypePtr base;
4822 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004823
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 base = type->baseType;
4825 if (base != NULL) {
4826 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4827 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004828 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004829 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004830
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004832 * Do not validate facets or attributes when working on
4833 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004834 */
4835 if (ctxt->schema != NULL) {
4836 if (ret == 0) {
4837 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004838 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004839 }
4840 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004841 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004842 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004843
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004844 base = type->subtypes;
4845 if (base != NULL) {
4846 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4847 } else {
4848 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004849 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004850 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004851 const xmlChar *cur, *end;
4852 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004853 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00004854
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004855 base = type->subtypes;
4856 if (base == NULL) {
4857 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
4858 "Internal: List type %s has no base type\n",
4859 type->name, NULL);
4860 return (-1);
4861 }
4862 cur = value;
4863 do {
William M. Brack76e95df2003-10-18 16:20:14 +00004864 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004865 cur++;
4866 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00004867 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004868 end++;
4869 if (end == cur)
4870 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004871 tmp = xmlStrndup(cur, end - cur);
4872 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
4873 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004874 if (ret2 != 0)
4875 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004876 cur = end;
4877 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004878 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004879 TODO
4880 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004881 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004882}
4883
4884/************************************************************************
4885 * *
4886 * DOM Validation code *
4887 * *
4888 ************************************************************************/
4889
4890static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004891 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004892static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004893 xmlNodePtr elem,
4894 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004895static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 xmlNodePtr elem,
4897 xmlSchemaElementPtr elemDecl,
4898 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004899
4900/**
4901 * xmlSchemaRegisterAttributes:
4902 * @ctxt: a schema validation context
4903 * @attrs: a list of attributes
4904 *
4905 * Register the list of attributes as the set to be validated on that element
4906 *
4907 * Returns -1 in case of error, 0 otherwise
4908 */
4909static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004910xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
4911{
Daniel Veillard4255d502002-04-16 15:50:10 +00004912 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004913 if ((attrs->ns != NULL) &&
4914 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4915 attrs = attrs->next;
4916 continue;
4917 }
4918 if (ctxt->attrNr >= ctxt->attrMax) {
4919 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00004920
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004921 ctxt->attrMax *= 2;
4922 tmp = (xmlSchemaAttrStatePtr)
4923 xmlRealloc(ctxt->attr, ctxt->attrMax *
4924 sizeof(xmlSchemaAttrState));
4925 if (tmp == NULL) {
4926 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
4927 ctxt->attrMax /= 2;
4928 return (-1);
4929 }
4930 ctxt->attr = tmp;
4931 }
4932 ctxt->attr[ctxt->attrNr].attr = attrs;
4933 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4934 ctxt->attrNr++;
4935 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004936 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004937 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004938}
4939
4940/**
4941 * xmlSchemaCheckAttributes:
4942 * @ctxt: a schema validation context
4943 * @node: the node carrying it.
4944 *
4945 * Check that the registered set of attributes on the current node
4946 * has been properly validated.
4947 *
4948 * Returns 0 if validity constraints are met, 1 otherwise.
4949 */
4950static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004951xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4952{
Daniel Veillard4255d502002-04-16 15:50:10 +00004953 int ret = 0;
4954 int i;
4955
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004956 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
4957 if (ctxt->attr[i].attr == NULL)
4958 break;
4959 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4960 ret = 1;
4961 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
4962 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004963 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004964 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004965}
4966
4967/**
4968 * xmlSchemaValidateSimpleContent:
4969 * @ctxt: a schema validation context
4970 * @elem: an element
4971 * @type: the type declaration
4972 *
4973 * Validate the content of an element expected to be a simple type
4974 *
4975 * Returns 0 if the element is schemas valid, a positive error code
4976 * number otherwise and -1 in case of internal or API error.
4977 */
4978static int
4979xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004980 xmlNodePtr node ATTRIBUTE_UNUSED)
4981{
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 xmlNodePtr child;
4983 xmlSchemaTypePtr type, base;
4984 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004985 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004986
4987 child = ctxt->node;
4988 type = ctxt->type;
4989
4990 /*
4991 * Validation Rule: Element Locally Valid (Type): 3.1.3
4992 */
4993 value = xmlNodeGetContent(child);
4994 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4995 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004996 case XML_SCHEMA_TYPE_RESTRICTION:{
4997 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004998
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004999 base = type->baseType;
5000 if (base != NULL) {
5001 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5002 } else {
5003 TODO}
5004 if (ret == 0) {
5005 facet = type->facets;
5006 ret =
5007 xmlSchemaValidateFacets(ctxt, base, facet, value);
5008 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005009 if ((ret == 0) && (type->attributes != NULL)) {
5010 ret = xmlSchemaValidateAttributes(ctxt, node,
5011 type->attributes);
5012 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005013 break;
5014 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005015 case XML_SCHEMA_TYPE_EXTENSION:{
5016 TODO
5017 break;
5018 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005019 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005020 TODO
5021 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005022 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005023 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005024
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005025 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005026}
5027
5028/**
5029 * xmlSchemaValidateCheckNodeList
5030 * @nodelist: the list of nodes
5031 *
5032 * Check the node list is only made of text nodes and entities pointing
5033 * to text nodes
5034 *
5035 * Returns 1 if true, 0 if false and -1 in case of error
5036 */
5037static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005038xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5039{
Daniel Veillard4255d502002-04-16 15:50:10 +00005040 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005041 if (nodelist->type == XML_ENTITY_REF_NODE) {
5042 TODO /* implement recursion in the entity content */
5043 }
5044 if ((nodelist->type != XML_TEXT_NODE) &&
5045 (nodelist->type != XML_COMMENT_NODE) &&
5046 (nodelist->type != XML_PI_NODE) &&
5047 (nodelist->type != XML_PI_NODE)) {
5048 return (0);
5049 }
5050 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005051 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005052 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005053}
5054
5055/**
5056 * xmlSchemaSkipIgnored:
5057 * @ctxt: a schema validation context
5058 * @type: the current type context
5059 * @node: the top node.
5060 *
5061 * Skip ignorable nodes in that context
5062 *
5063 * Returns the new sibling
5064 * number otherwise and -1 in case of internal or API error.
5065 */
5066static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005067xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068 xmlSchemaTypePtr type, xmlNodePtr node)
5069{
Daniel Veillard4255d502002-04-16 15:50:10 +00005070 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005071
Daniel Veillard4255d502002-04-16 15:50:10 +00005072 /*
5073 * TODO complete and handle entities
5074 */
5075 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005076 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005077 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005078 ((node->type == XML_COMMENT_NODE) ||
5079 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5080 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5081 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5082 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005083 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005085}
5086
5087/**
5088 * xmlSchemaValidateCallback:
5089 * @ctxt: a schema validation context
5090 * @name: the name of the element detected (might be NULL)
5091 * @type: the type
5092 *
5093 * A transition has been made in the automata associated to an element
5094 * content model
5095 */
5096static void
5097xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005098 const xmlChar * name ATTRIBUTE_UNUSED,
5099 xmlSchemaTypePtr type, xmlNodePtr node)
5100{
Daniel Veillard4255d502002-04-16 15:50:10 +00005101 xmlSchemaTypePtr oldtype = ctxt->type;
5102 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005103
Daniel Veillard4255d502002-04-16 15:50:10 +00005104#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005105 xmlGenericError(xmlGenericErrorContext,
5106 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005107 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005108#endif
5109 ctxt->type = type;
5110 ctxt->node = node;
5111 xmlSchemaValidateContent(ctxt, node);
5112 ctxt->type = oldtype;
5113 ctxt->node = oldnode;
5114}
5115
5116
5117#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005118
Daniel Veillard4255d502002-04-16 15:50:10 +00005119/**
5120 * xmlSchemaValidateSimpleRestrictionType:
5121 * @ctxt: a schema validation context
5122 * @node: the top node.
5123 *
5124 * Validate the content of a restriction type.
5125 *
5126 * Returns 0 if the element is schemas valid, a positive error code
5127 * number otherwise and -1 in case of internal or API error.
5128 */
5129static int
5130xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5131 xmlNodePtr node)
5132{
5133 xmlNodePtr child;
5134 xmlSchemaTypePtr type;
5135 int ret;
5136
5137 child = ctxt->node;
5138 type = ctxt->type;
5139
5140 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005141 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005142 return (-1);
5143 }
5144 /*
5145 * Only text and text based entities references shall be found there
5146 */
5147 ret = xmlSchemaValidateCheckNodeList(child);
5148 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005149 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005150 return (-1);
5151 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005152 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 +00005153 return (-1);
5154 }
5155 ctxt->type = type->subtypes;
5156 xmlSchemaValidateContent(ctxt, node);
5157 ctxt->type = type;
5158 return (ret);
5159}
5160#endif
5161
5162/**
5163 * xmlSchemaValidateSimpleType:
5164 * @ctxt: a schema validation context
5165 * @node: the top node.
5166 *
5167 * Validate the content of an simple type.
5168 *
5169 * Returns 0 if the element is schemas valid, a positive error code
5170 * number otherwise and -1 in case of internal or API error.
5171 */
5172static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005173xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5174{
Daniel Veillard4255d502002-04-16 15:50:10 +00005175 xmlNodePtr child;
5176 xmlSchemaTypePtr type;
5177 xmlAttrPtr attr;
5178 int ret;
5179
5180 child = ctxt->node;
5181 type = ctxt->type;
5182
5183 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005184 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5185 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005186 }
5187 /*
5188 * Only text and text based entities references shall be found there
5189 */
5190 ret = xmlSchemaValidateCheckNodeList(child);
5191 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005192 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5193 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005194 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005195 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5196 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005197 }
5198 /*
5199 * Validation Rule: Element Locally Valid (Type): 3.1.1
5200 */
5201 attr = node->properties;
5202 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005203 if ((attr->ns == NULL) ||
5204 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5205 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5206 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5207 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5208 (!xmlStrEqual
5209 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5210 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5211 return (ctxt->err);
5212 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005213 }
5214
5215 ctxt->type = type->subtypes;
5216 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5217 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005218 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005219}
5220
5221/**
5222 * xmlSchemaValidateElementType:
5223 * @ctxt: a schema validation context
5224 * @node: the top node.
5225 *
5226 * Validate the content of an element type.
5227 * Validation Rule: Element Locally Valid (Complex Type)
5228 *
5229 * Returns 0 if the element is schemas valid, a positive error code
5230 * number otherwise and -1 in case of internal or API error.
5231 */
5232static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005233xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5234{
Daniel Veillard4255d502002-04-16 15:50:10 +00005235 xmlNodePtr child;
5236 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005237 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005238 xmlSchemaElementPtr decl;
5239 int ret, attrBase;
5240
5241 oldregexp = ctxt->regexp;
5242
5243 child = ctxt->node;
5244 type = ctxt->type;
5245
5246 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005247 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5248 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 }
5250 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 if (type->minOccurs > 0) {
5252 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5253 }
5254 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005255 }
5256
5257 /*
5258 * Verify the element matches
5259 */
5260 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5262 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 }
5264 /*
5265 * Verify the attributes
5266 */
5267 attrBase = ctxt->attrBase;
5268 ctxt->attrBase = ctxt->attrNr;
5269 xmlSchemaRegisterAttributes(ctxt, child->properties);
5270 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5271 /*
5272 * Verify the element content recursively
5273 */
5274 decl = (xmlSchemaElementPtr) type;
5275 oldregexp = ctxt->regexp;
5276 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5278 (xmlRegExecCallbacks)
5279 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005280#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005281 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005282#endif
5283 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005284 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5285 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005286
5287 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005288 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005289#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005290 xmlGenericError(xmlGenericErrorContext,
5291 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005292#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005293 if (ret == 0) {
5294 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5295 } else if (ret < 0) {
5296 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005297#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005298 } else {
5299 xmlGenericError(xmlGenericErrorContext,
5300 "Element %s content check succeeded\n",
5301 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005302
5303#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005304 }
5305 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 }
5307 /*
5308 * Verify that all attributes were Schemas-validated
5309 */
5310 xmlSchemaCheckAttributes(ctxt, node);
5311 ctxt->attrNr = ctxt->attrBase;
5312 ctxt->attrBase = attrBase;
5313
5314 ctxt->regexp = oldregexp;
5315
5316 ctxt->node = child;
5317 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005318 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005319}
5320
5321/**
5322 * xmlSchemaValidateBasicType:
5323 * @ctxt: a schema validation context
5324 * @node: the top node.
5325 *
5326 * Validate the content of an element expected to be a basic type type
5327 *
5328 * Returns 0 if the element is schemas valid, a positive error code
5329 * number otherwise and -1 in case of internal or API error.
5330 */
5331static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005332xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5333{
Daniel Veillard4255d502002-04-16 15:50:10 +00005334 int ret;
5335 xmlNodePtr child, cur;
5336 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005337 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005338
5339 child = ctxt->node;
5340 type = ctxt->type;
5341
5342 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005343 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5344 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005345 }
5346 /*
5347 * First check the content model of the node.
5348 */
5349 cur = child;
5350 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005351 switch (cur->type) {
5352 case XML_TEXT_NODE:
5353 case XML_CDATA_SECTION_NODE:
5354 case XML_PI_NODE:
5355 case XML_COMMENT_NODE:
5356 case XML_XINCLUDE_START:
5357 case XML_XINCLUDE_END:
5358 break;
5359 case XML_ENTITY_REF_NODE:
5360 case XML_ENTITY_NODE:
5361 TODO break;
5362 case XML_ELEMENT_NODE:
5363 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5364 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005365 case XML_ATTRIBUTE_NODE:
5366 case XML_DOCUMENT_NODE:
5367 case XML_DOCUMENT_TYPE_NODE:
5368 case XML_DOCUMENT_FRAG_NODE:
5369 case XML_NOTATION_NODE:
5370 case XML_HTML_DOCUMENT_NODE:
5371 case XML_DTD_NODE:
5372 case XML_ELEMENT_DECL:
5373 case XML_ATTRIBUTE_DECL:
5374 case XML_ENTITY_DECL:
5375 case XML_NAMESPACE_DECL:
5376#ifdef LIBXML_DOCB_ENABLED
5377 case XML_DOCB_DOCUMENT_NODE:
5378#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005379 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5380 return (ctxt->err);
5381 }
5382 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005383 }
5384 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005385 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005386 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005387 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005388
5389 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005390 xmlSchemaFreeValue(ctxt->value);
5391 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005392 }
5393 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5394 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005395 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005396 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005397 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 +00005398 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005400}
5401
5402/**
5403 * xmlSchemaValidateComplexType:
5404 * @ctxt: a schema validation context
5405 * @node: the top node.
5406 *
5407 * Validate the content of an element expected to be a complex type type
5408 * xmlschema-1.html#cvc-complex-type
5409 * Validation Rule: Element Locally Valid (Complex Type)
5410 *
5411 * Returns 0 if the element is schemas valid, a positive error code
5412 * number otherwise and -1 in case of internal or API error.
5413 */
5414static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005415xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5416{
Daniel Veillard4255d502002-04-16 15:50:10 +00005417 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005418 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005419 int ret;
5420
5421 child = ctxt->node;
5422 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005423 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005424
Daniel Veillard4255d502002-04-16 15:50:10 +00005425 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005426 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005427 if (type->baseType != NULL) {
5428 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005429 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5430 }
5431 if (type->attributes != NULL) {
5432 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5433 }
5434 subtype = type->subtypes;
5435 while (subtype != NULL) {
5436 ctxt->type = subtype;
5437 xmlSchemaValidateComplexType(ctxt, node);
5438 subtype = subtype->next;
5439 }
5440 break;
5441 case XML_SCHEMA_CONTENT_ELEMENTS:
5442 case XML_SCHEMA_CONTENT_MIXED:
5443 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5444 /*
5445 * Skip ignorable nodes in that context
5446 */
5447 child = xmlSchemaSkipIgnored(ctxt, type, child);
5448 while (child != NULL) {
5449 if (child->type == XML_ELEMENT_NODE) {
5450 ret = xmlRegExecPushString(ctxt->regexp,
5451 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005452#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005453 if (ret < 0)
5454 xmlGenericError(xmlGenericErrorContext,
5455 " --> %s Error\n", child->name);
5456 else
5457 xmlGenericError(xmlGenericErrorContext,
5458 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005459#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005460 }
5461 child = child->next;
5462 /*
5463 * Skip ignorable nodes in that context
5464 */
5465 child = xmlSchemaSkipIgnored(ctxt, type, child);
5466 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005467 if (type->attributes != NULL) {
5468 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5469 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005470 break;
5471 case XML_SCHEMA_CONTENT_BASIC:{
5472 if (type->subtypes != NULL) {
5473 ctxt->type = type->subtypes;
5474 xmlSchemaValidateComplexType(ctxt, node);
5475 }
5476 if (type->baseType != NULL) {
5477 ctxt->type = type->baseType;
5478 xmlSchemaValidateBasicType(ctxt, node);
5479 }
5480 if (type->attributes != NULL) {
5481 xmlSchemaValidateAttributes(ctxt, node,
5482 type->attributes);
5483 }
5484 ctxt->type = type;
5485 break;
5486 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005487 case XML_SCHEMA_CONTENT_SIMPLE:{
5488 if (type->subtypes != NULL) {
5489 ctxt->type = type->subtypes;
5490 xmlSchemaValidateComplexType(ctxt, node);
5491 }
5492 if (type->baseType != NULL) {
5493 ctxt->type = type->baseType;
5494 xmlSchemaValidateComplexType(ctxt, node);
5495 }
5496 if (type->attributes != NULL) {
5497 xmlSchemaValidateAttributes(ctxt, node,
5498 type->attributes);
5499 }
5500 ctxt->type = type;
5501 break;
5502 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005503 default:
5504 TODO xmlGenericError(xmlGenericErrorContext,
5505 "unimplemented content type %d\n",
5506 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005507 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005508 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005509}
5510
5511/**
5512 * xmlSchemaValidateContent:
5513 * @ctxt: a schema validation context
5514 * @elem: an element
5515 * @type: the type declaration
5516 *
5517 * Validate the content of an element against the type.
5518 *
5519 * Returns 0 if the element is schemas valid, a positive error code
5520 * number otherwise and -1 in case of internal or API error.
5521 */
5522static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005523xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5524{
Daniel Veillard4255d502002-04-16 15:50:10 +00005525 xmlNodePtr child;
5526 xmlSchemaTypePtr type;
5527
5528 child = ctxt->node;
5529 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005530 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005531
Daniel Veillarde19fc232002-04-22 16:01:24 +00005532 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005533 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005534
Daniel Veillard4255d502002-04-16 15:50:10 +00005535 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005536 case XML_SCHEMA_TYPE_ANY:
5537 /* Any type will do it, fine */
5538 TODO /* handle recursivity */
5539 break;
5540 case XML_SCHEMA_TYPE_COMPLEX:
5541 xmlSchemaValidateComplexType(ctxt, node);
5542 break;
5543 case XML_SCHEMA_TYPE_ELEMENT:{
5544 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5545
5546 /*
5547 * Handle element reference here
5548 */
5549 if (decl->ref != NULL) {
5550 if (decl->refDecl == NULL) {
5551 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5552 return (-1);
5553 }
5554 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5555 decl = decl->refDecl;
5556 }
5557 xmlSchemaValidateElementType(ctxt, node);
5558 ctxt->type = type;
5559 break;
5560 }
5561 case XML_SCHEMA_TYPE_BASIC:
5562 xmlSchemaValidateBasicType(ctxt, node);
5563 break;
5564 case XML_SCHEMA_TYPE_FACET:
5565 TODO break;
5566 case XML_SCHEMA_TYPE_SIMPLE:
5567 xmlSchemaValidateSimpleType(ctxt, node);
5568 break;
5569 case XML_SCHEMA_TYPE_SEQUENCE:
5570 TODO break;
5571 case XML_SCHEMA_TYPE_CHOICE:
5572 TODO break;
5573 case XML_SCHEMA_TYPE_ALL:
5574 TODO break;
5575 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5576 TODO break;
5577 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5578 TODO break;
5579 case XML_SCHEMA_TYPE_UR:
5580 TODO break;
5581 case XML_SCHEMA_TYPE_RESTRICTION:
5582 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5583 TODO break;
5584 case XML_SCHEMA_TYPE_EXTENSION:
5585 TODO break;
5586 case XML_SCHEMA_TYPE_ATTRIBUTE:
5587 TODO break;
5588 case XML_SCHEMA_TYPE_GROUP:
5589 TODO break;
5590 case XML_SCHEMA_TYPE_NOTATION:
5591 TODO break;
5592 case XML_SCHEMA_TYPE_LIST:
5593 TODO break;
5594 case XML_SCHEMA_TYPE_UNION:
5595 TODO break;
5596 case XML_SCHEMA_FACET_MININCLUSIVE:
5597 TODO break;
5598 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5599 TODO break;
5600 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5601 TODO break;
5602 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5603 TODO break;
5604 case XML_SCHEMA_FACET_TOTALDIGITS:
5605 TODO break;
5606 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5607 TODO break;
5608 case XML_SCHEMA_FACET_PATTERN:
5609 TODO break;
5610 case XML_SCHEMA_FACET_ENUMERATION:
5611 TODO break;
5612 case XML_SCHEMA_FACET_WHITESPACE:
5613 TODO break;
5614 case XML_SCHEMA_FACET_LENGTH:
5615 TODO break;
5616 case XML_SCHEMA_FACET_MAXLENGTH:
5617 TODO break;
5618 case XML_SCHEMA_FACET_MINLENGTH:
5619 TODO break;
5620 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5621 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005622 }
5623 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5624
5625 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005627 ctxt->node = ctxt->node->next;
5628 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005629 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005630}
5631
5632/**
5633 * xmlSchemaValidateType:
5634 * @ctxt: a schema validation context
5635 * @elem: an element
5636 * @type: the list of type declarations
5637 *
5638 * Validate the content of an element against the types.
5639 *
5640 * Returns 0 if the element is schemas valid, a positive error code
5641 * number otherwise and -1 in case of internal or API error.
5642 */
5643static int
5644xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005645 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5646{
Daniel Veillard4255d502002-04-16 15:50:10 +00005647 xmlChar *nil;
5648
Daniel Veillard2db8c122003-07-08 12:16:59 +00005649 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005650 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005651
Daniel Veillard4255d502002-04-16 15:50:10 +00005652 /*
5653 * 3.3.4 : 2
5654 */
5655 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005656 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5657 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005658 }
5659 /*
5660 * 3.3.4: 3
5661 */
5662 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5663 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005664 /* 3.3.4: 3.2 */
5665 if (xmlStrEqual(nil, BAD_CAST "true")) {
5666 if (elem->children != NULL) {
5667 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5668 return (ctxt->err);
5669 }
5670 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5671 (elemDecl->value != NULL)) {
5672 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5673 return (ctxt->err);
5674 }
5675 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005676 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005677 /* 3.3.4: 3.1 */
5678 if (nil != NULL) {
5679 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5680 xmlFree(nil);
5681 return (ctxt->err);
5682 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005683 }
5684
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005685 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00005686
5687 ctxt->type = elemDecl->subtypes;
5688 ctxt->node = elem->children;
5689 xmlSchemaValidateContent(ctxt, elem);
5690 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005691
5692 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005693}
5694
5695
5696/**
5697 * xmlSchemaValidateAttributes:
5698 * @ctxt: a schema validation context
5699 * @elem: an element
5700 * @attributes: the list of attribute declarations
5701 *
5702 * Validate the attributes of an element.
5703 *
5704 * Returns 0 if the element is schemas valid, a positive error code
5705 * number otherwise and -1 in case of internal or API error.
5706 */
5707static int
5708xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005709 xmlSchemaAttributePtr attributes)
5710{
Daniel Veillard4255d502002-04-16 15:50:10 +00005711 int i, ret;
5712 xmlAttrPtr attr;
5713 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005714 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005715
5716 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005717 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005718 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005719 /*
5720 * Handle attribute groups
5721 */
5722 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5723 group = (xmlSchemaAttributeGroupPtr) attributes;
5724 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5725 attributes = group->next;
5726 continue;
5727 }
5728 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5729 attr = ctxt->attr[i].attr;
5730 if (attr == NULL)
5731 continue;
5732 if (attributes->ref != NULL) {
5733 if (!xmlStrEqual(attr->name, attributes->ref))
5734 continue;
5735 if (attr->ns != NULL) {
5736 if ((attributes->refNs == NULL) ||
5737 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5738 continue;
5739 } else if (attributes->refNs != NULL) {
5740 continue;
5741 }
5742 } else {
5743 if (!xmlStrEqual(attr->name, attributes->name))
5744 continue;
5745 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005746 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005747 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005748 if (attr->ns == NULL) {
5749 /*
5750 * accept an unqualified attribute only if the declaration
5751 * is unqualified or if the schemas allowed it.
5752 */
5753 if ((attributes->targetNamespace != NULL) &&
5754 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
5755 continue;
5756 } else {
5757 if (attributes->targetNamespace == NULL)
5758 continue;
5759 if (!xmlStrEqual(attributes->targetNamespace,
5760 attr->ns->href))
5761 continue;
5762 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005763 }
5764 ctxt->cur = (xmlNodePtr) attributes;
5765 if (attributes->subtypes == NULL) {
5766 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
5767 continue;
5768 }
5769 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5770 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5771 value);
5772 if (ret != 0) {
5773 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
5774 } else {
5775 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5776 }
5777 if (value != NULL) {
5778 xmlFree(value);
5779 }
5780 }
5781 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005782 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005783 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005784}
5785
5786/**
5787 * xmlSchemaValidateElement:
5788 * @ctxt: a schema validation context
5789 * @elem: an element
5790 *
5791 * Validate an element in a tree
5792 *
5793 * Returns 0 if the element is schemas valid, a positive error code
5794 * number otherwise and -1 in case of internal or API error.
5795 */
5796static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005797xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
5798{
Daniel Veillard4255d502002-04-16 15:50:10 +00005799 xmlSchemaElementPtr elemDecl;
5800 int ret, attrBase;
5801
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005802 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5804 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005805 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5807 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005808 }
5809 /*
5810 * special case whe elementFormDefault is unqualified for top-level elem.
5811 */
5812 if ((elemDecl == NULL) && (elem->ns != NULL) &&
5813 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
5814 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
5815 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
5816 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5817 elem->name, NULL, NULL);
5818 }
5819
Daniel Veillard4255d502002-04-16 15:50:10 +00005820 /*
5821 * 3.3.4 : 1
5822 */
5823 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
5825 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005826 }
5827 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
5829 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005830 }
5831 /*
5832 * Verify the attributes
5833 */
5834 attrBase = ctxt->attrBase;
5835 ctxt->attrBase = ctxt->attrNr;
5836 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5837 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5838 /*
5839 * Verify the element content recursively
5840 */
5841 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005842 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5843 (xmlRegExecCallbacks)
5844 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005845#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005847#endif
5848 }
5849 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005850 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005851 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005852#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005853 xmlGenericError(xmlGenericErrorContext,
5854 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005855#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005856 if (ret == 0) {
5857 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
5858 } else if (ret < 0) {
5859 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005860#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005861 } else {
5862 xmlGenericError(xmlGenericErrorContext,
5863 "Element %s content check succeeded\n",
5864 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005865
5866#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005867 }
5868 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005869 }
5870 /*
5871 * Verify that all attributes were Schemas-validated
5872 */
5873 xmlSchemaCheckAttributes(ctxt, elem);
5874 ctxt->attrNr = ctxt->attrBase;
5875 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876
5877 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005878}
5879
5880/**
5881 * xmlSchemaValidateDocument:
5882 * @ctxt: a schema validation context
5883 * @doc: a parsed document tree
5884 *
5885 * Validate a document tree in memory.
5886 *
5887 * Returns 0 if the document is schemas valid, a positive error code
5888 * number otherwise and -1 in case of internal or API error.
5889 */
5890static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005891xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5892{
Daniel Veillard4255d502002-04-16 15:50:10 +00005893 xmlNodePtr root;
5894 xmlSchemaElementPtr elemDecl;
5895
5896 root = xmlDocGetRootElement(doc);
5897 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005898 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
5899 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005900 }
5901 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005902 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5903 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005904 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005905 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5906 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005907 /*
5908 * special case whe elementFormDefault is unqualified for top-level elem.
5909 */
5910 if ((elemDecl == NULL) && (root->ns != NULL) &&
5911 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
5912 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
5913 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5914 root->name, NULL, NULL);
5915 }
5916
Daniel Veillard4255d502002-04-16 15:50:10 +00005917 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005918 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005919 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005920 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005921 }
5922 /*
5923 * Okay, start the recursive validation
5924 */
5925 xmlSchemaValidateElement(ctxt, root);
5926
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005927 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005928}
5929
5930/************************************************************************
5931 * *
5932 * SAX Validation code *
5933 * *
5934 ************************************************************************/
5935
5936/************************************************************************
5937 * *
5938 * Validation interfaces *
5939 * *
5940 ************************************************************************/
5941
5942/**
5943 * xmlSchemaNewValidCtxt:
5944 * @schema: a precompiled XML Schemas
5945 *
5946 * Create an XML Schemas validation context based on the given schema
5947 *
5948 * Returns the validation context or NULL in case of error
5949 */
5950xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005951xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
5952{
Daniel Veillard4255d502002-04-16 15:50:10 +00005953 xmlSchemaValidCtxtPtr ret;
5954
5955 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5956 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005957 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005958 return (NULL);
5959 }
5960 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5961 ret->schema = schema;
5962 ret->attrNr = 0;
5963 ret->attrMax = 10;
5964 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005965 sizeof
5966 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00005967 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005968 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
5969 free(ret);
5970 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005971 }
5972 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5973 return (ret);
5974}
5975
5976/**
5977 * xmlSchemaFreeValidCtxt:
5978 * @ctxt: the schema validation context
5979 *
5980 * Free the resources associated to the schema validation context
5981 */
5982void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005983xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
5984{
Daniel Veillard4255d502002-04-16 15:50:10 +00005985 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005986 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005987 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005988 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005989 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005990 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 xmlFree(ctxt);
5992}
5993
5994/**
5995 * xmlSchemaSetValidErrors:
5996 * @ctxt: a schema validation context
5997 * @err: the error function
5998 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00005999 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006000 *
6001 * Set the error and warning callback informations
6002 */
6003void
6004xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006005 xmlSchemaValidityErrorFunc err,
6006 xmlSchemaValidityWarningFunc warn, void *ctx)
6007{
Daniel Veillard4255d502002-04-16 15:50:10 +00006008 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006009 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006010 ctxt->error = err;
6011 ctxt->warning = warn;
6012 ctxt->userData = ctx;
6013}
6014
6015/**
6016 * xmlSchemaValidateDoc:
6017 * @ctxt: a schema validation context
6018 * @doc: a parsed document tree
6019 *
6020 * Validate a document tree in memory.
6021 *
6022 * Returns 0 if the document is schemas valid, a positive error code
6023 * number otherwise and -1 in case of internal or API error.
6024 */
6025int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006026xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6027{
Daniel Veillard4255d502002-04-16 15:50:10 +00006028 int ret;
6029
6030 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006031 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006032
6033 ctxt->doc = doc;
6034 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006035 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006036}
6037
6038/**
6039 * xmlSchemaValidateStream:
6040 * @ctxt: a schema validation context
6041 * @input: the input to use for reading the data
6042 * @enc: an optional encoding information
6043 * @sax: a SAX handler for the resulting events
6044 * @user_data: the context to provide to the SAX handler.
6045 *
6046 * Validate a document tree in memory.
6047 *
6048 * Returns 0 if the document is schemas valid, a positive error code
6049 * number otherwise and -1 in case of internal or API error.
6050 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006051int
Daniel Veillard4255d502002-04-16 15:50:10 +00006052xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006053 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6054 xmlSAXHandlerPtr sax, void *user_data)
6055{
Daniel Veillard4255d502002-04-16 15:50:10 +00006056 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006057 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006058 ctxt->input = input;
6059 ctxt->enc = enc;
6060 ctxt->sax = sax;
6061 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006062 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006063}
6064
6065#endif /* LIBXML_SCHEMAS_ENABLED */