blob: 6976cc7f11024bee70172f76e0631a9793420ed0 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
10#define IN_LIBXML
11#include "libxml.h"
12
13#ifdef LIBXML_SCHEMAS_ENABLED
14
15#include <string.h>
16#include <libxml/xmlmemory.h>
17#include <libxml/parser.h>
18#include <libxml/parserInternals.h>
19#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000020#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000021
22#include <libxml/xmlschemas.h>
23#include <libxml/schemasInternals.h>
24#include <libxml/xmlschemastypes.h>
25#include <libxml/xmlautomata.h>
26#include <libxml/xmlregexp.h>
27
Daniel Veillarda84c0b32003-06-02 16:58:46 +000028/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000029
Daniel Veillard82bbbd42003-05-11 20:16:09 +000030/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000031
Daniel Veillard82bbbd42003-05-11 20:16:09 +000032/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000033
Daniel Veillard118aed72002-09-24 14:13:13 +000034/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000035
Daniel Veillard4255d502002-04-16 15:50:10 +000036/* #define DEBUG_AUTOMATA 1 */
37
38#define UNBOUNDED (1 << 30)
39#define TODO \
40 xmlGenericError(xmlGenericErrorContext, \
41 "Unimplemented block at %s:%d\n", \
42 __FILE__, __LINE__);
43
Daniel Veillard5a872412002-05-22 06:40:27 +000044#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
45
Daniel Veillard4255d502002-04-16 15:50:10 +000046/*
47 * The XML Schemas namespaces
48 */
49static const xmlChar *xmlSchemaNs = (const xmlChar *)
50 "http://www.w3.org/2001/XMLSchema";
51
52static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
53 "http://www.w3.org/2001/XMLSchema-instance";
54
55#define IS_SCHEMA(node, type) \
56 ((node != NULL) && (node->ns != NULL) && \
57 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
58 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
59
60#define XML_SCHEMAS_PARSE_ERROR 1
61
62struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000063 void *userData; /* user specific data block */
64 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
65 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000066 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000067 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000068 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000069
Daniel Veillardd0c9c322003-10-10 00:49:42 +000070 xmlSchemaPtr schema; /* The schema in use */
71 xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000072 int counter;
73
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074 xmlChar *URL;
75 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +000076
Daniel Veillardd0c9c322003-10-10 00:49:42 +000077 const char *buffer;
78 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000079
Daniel Veillard4255d502002-04-16 15:50:10 +000080 /*
81 * Used to build complex element content models
82 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000083 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000084 xmlAutomataStatePtr start;
85 xmlAutomataStatePtr end;
86 xmlAutomataStatePtr state;
87};
88
89
90#define XML_SCHEMAS_ATTR_UNKNOWN 1
91#define XML_SCHEMAS_ATTR_CHECKED 2
92
93typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
94typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
95struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAttrPtr attr;
97 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +000098};
99
100/**
101 * xmlSchemaValidCtxt:
102 *
103 * A Schemas validation context
104 */
105
106struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000107 void *userData; /* user specific data block */
108 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
109 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000110 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000111
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlSchemaPtr schema; /* The schema in use */
113 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000115 xmlCharEncoding enc;
116 xmlSAXHandlerPtr sax;
117 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000118
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000119 xmlDocPtr myDoc;
120 int err;
121 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000122
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 xmlNodePtr node;
124 xmlNodePtr cur;
125 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000126
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000127 xmlRegExecCtxtPtr regexp;
128 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000129
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000130 int attrNr;
131 int attrBase;
132 int attrMax;
133 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134};
135
Daniel Veillard1d913862003-11-21 00:28:39 +0000136/*
137 * These are the entries in the schemas importSchemas hash table
138 */
139typedef struct _xmlSchemaImport xmlSchemaImport;
140typedef xmlSchemaImport *xmlSchemaImportPtr;
141struct _xmlSchemaImport {
142 const xmlChar *schemaLocation;
143 xmlSchemaPtr schema;
144};
Daniel Veillard4255d502002-04-16 15:50:10 +0000145
146/************************************************************************
147 * *
148 * Some predeclarations *
149 * *
150 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000151static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
152 xmlSchemaTypePtr type,
153 xmlChar * value);
154
155/************************************************************************
156 * *
157 * Datatype error handlers *
158 * *
159 ************************************************************************/
160
161/**
162 * xmlSchemaPErrMemory:
163 * @node: a context node
164 * @extra: extra informations
165 *
166 * Handle an out of memory condition
167 */
168static void
169xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
170 const char *extra, xmlNodePtr node)
171{
172 if (ctxt != NULL)
173 ctxt->nberrors++;
174 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
175 extra);
176}
177
178/**
179 * xmlSchemaPErr:
180 * @ctxt: the parsing context
181 * @node: the context node
182 * @error: the error code
183 * @msg: the error message
184 * @str1: extra data
185 * @str2: extra data
186 *
187 * Handle a parser error
188 */
189static void
190xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
191 const char *msg, const xmlChar * str1, const xmlChar * str2)
192{
193 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000194 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000195 void *data = NULL;
196
197 if (ctxt != NULL) {
198 ctxt->nberrors++;
199 channel = ctxt->error;
200 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000201 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000202 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000203 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000204 error, XML_ERR_ERROR, NULL, 0,
205 (const char *) str1, (const char *) str2, NULL, 0, 0,
206 msg, str1, str2);
207}
208
209/**
210 * xmlSchemaPErr2:
211 * @ctxt: the parsing context
212 * @node: the context node
213 * @node: the current child
214 * @error: the error code
215 * @msg: the error message
216 * @str1: extra data
217 * @str2: extra data
218 *
219 * Handle a parser error
220 */
221static void
222xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
223 xmlNodePtr child, int error,
224 const char *msg, const xmlChar * str1, const xmlChar * str2)
225{
226 if (child != NULL)
227 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
228 else
229 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
230}
231
232/**
233 * xmlSchemaVTypeErrMemory:
234 * @node: a context node
235 * @extra: extra informations
236 *
237 * Handle an out of memory condition
238 */
239static void
240xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
241 const char *extra, xmlNodePtr node)
242{
243 if (ctxt != NULL) {
244 ctxt->nberrors++;
245 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
246 }
247 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
248 extra);
249}
250
251/**
252 * xmlSchemaVErr3:
253 * @ctxt: the validation context
254 * @node: the context node
255 * @error: the error code
256 * @msg: the error message
257 * @str1: extra data
258 * @str2: extra data
259 * @str3: extra data
260 *
261 * Handle a validation error
262 */
263static void
264xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
265 const char *msg, const xmlChar *str1, const xmlChar *str2,
266 const xmlChar *str3)
267{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000268 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000269 xmlGenericErrorFunc channel = NULL;
270 void *data = NULL;
271
272 if (ctxt != NULL) {
273 ctxt->nberrors++;
274 ctxt->err = error;
275 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000276 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000277 data = ctxt->userData;
278 }
279 /* reajust to global error numbers */
280 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000281 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000282 error, XML_ERR_ERROR, NULL, 0,
283 (const char *) str1, (const char *) str2,
284 (const char *) str3, 0, 0,
285 msg, str1, str2, str3);
286}
287/**
288 * xmlSchemaVErr:
289 * @ctxt: the validation context
290 * @node: the context node
291 * @error: the error code
292 * @msg: the error message
293 * @str1: extra data
294 * @str2: extra data
295 *
296 * Handle a validation error
297 */
298static void
299xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
300 const char *msg, const xmlChar * str1, const xmlChar * str2)
301{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000302 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000303 xmlGenericErrorFunc channel = NULL;
304 void *data = NULL;
305
306 if (ctxt != NULL) {
307 ctxt->nberrors++;
308 ctxt->err = error;
309 channel = ctxt->error;
310 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000311 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000312 }
313 /* reajust to global error numbers */
314 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000315 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000316 error, XML_ERR_ERROR, NULL, 0,
317 (const char *) str1, (const char *) str2, NULL, 0, 0,
318 msg, str1, str2);
319}
Daniel Veillard4255d502002-04-16 15:50:10 +0000320
321/************************************************************************
322 * *
323 * Allocation functions *
324 * *
325 ************************************************************************/
326
327/**
328 * xmlSchemaNewSchema:
329 * @ctxt: a schema validation context (optional)
330 *
331 * Allocate a new Schema structure.
332 *
333 * Returns the newly allocated structure or NULL in case or error
334 */
335static xmlSchemaPtr
336xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
337{
338 xmlSchemaPtr ret;
339
340 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
341 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000342 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000343 return (NULL);
344 }
345 memset(ret, 0, sizeof(xmlSchema));
346
347 return (ret);
348}
349
350/**
351 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000352 *
353 * Allocate a new Facet structure.
354 *
355 * Returns the newly allocated structure or NULL in case or error
356 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000357xmlSchemaFacetPtr
358xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000359{
360 xmlSchemaFacetPtr ret;
361
362 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
363 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000364 return (NULL);
365 }
366 memset(ret, 0, sizeof(xmlSchemaFacet));
367
368 return (ret);
369}
370
371/**
372 * xmlSchemaNewAnnot:
373 * @ctxt: a schema validation context (optional)
374 * @node: a node
375 *
376 * Allocate a new annotation structure.
377 *
378 * Returns the newly allocated structure or NULL in case or error
379 */
380static xmlSchemaAnnotPtr
381xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
382{
383 xmlSchemaAnnotPtr ret;
384
385 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
386 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000387 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000388 return (NULL);
389 }
390 memset(ret, 0, sizeof(xmlSchemaAnnot));
391 ret->content = node;
392 return (ret);
393}
394
395/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000396 * xmlSchemaFreeAnnot:
397 * @annot: a schema type structure
398 *
399 * Deallocate a annotation structure
400 */
401static void
402xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
403{
404 if (annot == NULL)
405 return;
406 xmlFree(annot);
407}
408
409/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000410 * xmlSchemaFreeImport:
411 * @import: a schema import structure
412 *
413 * Deallocate an import structure
414 */
415static void
416xmlSchemaFreeImport(xmlSchemaImportPtr import)
417{
418 if (import == NULL)
419 return;
420
421 xmlSchemaFree(import->schema);
422 xmlFree((xmlChar *) import->schemaLocation);
423 xmlFree(import);
424}
425
426/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000427 * xmlSchemaFreeNotation:
428 * @schema: a schema notation structure
429 *
430 * Deallocate a Schema Notation structure.
431 */
432static void
433xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
434{
435 if (nota == NULL)
436 return;
437 if (nota->name != NULL)
438 xmlFree((xmlChar *) nota->name);
439 xmlFree(nota);
440}
441
442/**
443 * xmlSchemaFreeAttribute:
444 * @schema: a schema attribute structure
445 *
446 * Deallocate a Schema Attribute structure.
447 */
448static void
449xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
450{
451 if (attr == NULL)
452 return;
453 if (attr->name != NULL)
454 xmlFree((xmlChar *) attr->name);
455 if (attr->ref != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000456 xmlFree((xmlChar *) attr->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000457 if (attr->refNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000458 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000459 if (attr->typeName != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000460 xmlFree((xmlChar *) attr->typeName);
Daniel Veillard4255d502002-04-16 15:50:10 +0000461 if (attr->typeNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000462 xmlFree((xmlChar *) attr->typeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000463 xmlFree(attr);
464}
465
466/**
467 * xmlSchemaFreeAttributeGroup:
468 * @schema: a schema attribute group structure
469 *
470 * Deallocate a Schema Attribute Group structure.
471 */
472static void
473xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
474{
475 if (attr == NULL)
476 return;
477 if (attr->name != NULL)
478 xmlFree((xmlChar *) attr->name);
Daniel Veillard91a13252003-03-27 23:44:43 +0000479 if (attr->ref != NULL)
480 xmlFree((xmlChar *) attr->ref);
481 if (attr->refNs != NULL)
482 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000483 xmlFree(attr);
484}
485
486/**
487 * xmlSchemaFreeElement:
488 * @schema: a schema element structure
489 *
490 * Deallocate a Schema Element structure.
491 */
492static void
493xmlSchemaFreeElement(xmlSchemaElementPtr elem)
494{
495 if (elem == NULL)
496 return;
497 if (elem->name != NULL)
498 xmlFree((xmlChar *) elem->name);
499 if (elem->namedType != NULL)
500 xmlFree((xmlChar *) elem->namedType);
501 if (elem->namedTypeNs != NULL)
502 xmlFree((xmlChar *) elem->namedTypeNs);
503 if (elem->ref != NULL)
504 xmlFree((xmlChar *) elem->ref);
505 if (elem->refNs != NULL)
506 xmlFree((xmlChar *) elem->refNs);
Daniel Veillard32370232002-10-16 14:08:14 +0000507 if (elem->annot != NULL)
508 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000509 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000510 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000511 xmlFree(elem);
512}
513
514/**
515 * xmlSchemaFreeFacet:
516 * @facet: a schema facet structure
517 *
518 * Deallocate a Schema Facet structure.
519 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000520void
Daniel Veillard4255d502002-04-16 15:50:10 +0000521xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
522{
523 if (facet == NULL)
524 return;
525 if (facet->value != NULL)
526 xmlFree((xmlChar *) facet->value);
527 if (facet->id != NULL)
528 xmlFree((xmlChar *) facet->id);
529 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000530 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000531 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000532 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000533 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000534 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000535 xmlFree(facet);
536}
537
538/**
539 * xmlSchemaFreeType:
540 * @type: a schema type structure
541 *
542 * Deallocate a Schema Type structure.
543 */
544void
545xmlSchemaFreeType(xmlSchemaTypePtr type)
546{
547 if (type == NULL)
548 return;
549 if (type->name != NULL)
550 xmlFree((xmlChar *) type->name);
Daniel Veillard1d913862003-11-21 00:28:39 +0000551 if (type->ref != NULL)
552 xmlFree((xmlChar *) type->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000553 if (type->base != NULL)
554 xmlFree((xmlChar *) type->base);
555 if (type->baseNs != NULL)
556 xmlFree((xmlChar *) type->baseNs);
557 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000558 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000559 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000560 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000561
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000562 facet = type->facets;
563 while (facet != NULL) {
564 next = facet->next;
565 xmlSchemaFreeFacet(facet);
566 facet = next;
567 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000568 }
569 xmlFree(type);
570}
571
572/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000573 * xmlSchemaFree:
574 * @schema: a schema structure
575 *
576 * Deallocate a Schema structure.
577 */
578void
579xmlSchemaFree(xmlSchemaPtr schema)
580{
581 if (schema == NULL)
582 return;
583
Daniel Veillard91a13252003-03-27 23:44:43 +0000584 if (schema->id != NULL)
585 xmlFree((xmlChar *) schema->id);
586 if (schema->targetNamespace != NULL)
587 xmlFree((xmlChar *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000588 if (schema->name != NULL)
589 xmlFree((xmlChar *) schema->name);
590 if (schema->notaDecl != NULL)
591 xmlHashFree(schema->notaDecl,
592 (xmlHashDeallocator) xmlSchemaFreeNotation);
593 if (schema->attrDecl != NULL)
594 xmlHashFree(schema->attrDecl,
595 (xmlHashDeallocator) xmlSchemaFreeAttribute);
596 if (schema->attrgrpDecl != NULL)
597 xmlHashFree(schema->attrgrpDecl,
598 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
599 if (schema->elemDecl != NULL)
600 xmlHashFree(schema->elemDecl,
601 (xmlHashDeallocator) xmlSchemaFreeElement);
602 if (schema->typeDecl != NULL)
603 xmlHashFree(schema->typeDecl,
604 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000605 if (schema->groupDecl != NULL)
606 xmlHashFree(schema->groupDecl,
607 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000608 if (schema->schemasImports != NULL)
609 xmlHashFree(schema->schemasImports,
610 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillard4255d502002-04-16 15:50:10 +0000611 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000612 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000613 if (schema->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000614 xmlFreeDoc(schema->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +0000615
616 xmlFree(schema);
617}
618
619/************************************************************************
620 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000621 * Debug functions *
622 * *
623 ************************************************************************/
624
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000625#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000626
Daniel Veillard4255d502002-04-16 15:50:10 +0000627/**
628 * xmlSchemaElementDump:
629 * @elem: an element
630 * @output: the file output
631 *
632 * Dump the element
633 */
634static void
635xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000636 const xmlChar * name ATTRIBUTE_UNUSED,
637 const xmlChar * context ATTRIBUTE_UNUSED,
638 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000639{
640 if (elem == NULL)
641 return;
642
643 fprintf(output, "Element ");
644 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000645 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000646 fprintf(output, ": %s ", elem->name);
647 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000648 fprintf(output, "namespace '%s' ", namespace);
649
Daniel Veillard4255d502002-04-16 15:50:10 +0000650 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000651 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000652 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000654 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000655 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000656 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000657 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000658 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000659 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000660 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000661 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000662 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000663 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000664 fprintf(output, "\n");
665 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000666 fprintf(output, " ");
667 if (elem->minOccurs != 1)
668 fprintf(output, "min: %d ", elem->minOccurs);
669 if (elem->maxOccurs >= UNBOUNDED)
670 fprintf(output, "max: unbounded\n");
671 else if (elem->maxOccurs != 1)
672 fprintf(output, "max: %d\n", elem->maxOccurs);
673 else
674 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000675 }
676 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000677 fprintf(output, " type: %s", elem->namedType);
678 if (elem->namedTypeNs != NULL)
679 fprintf(output, " ns %s\n", elem->namedTypeNs);
680 else
681 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000682 }
683 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000684 fprintf(output, " substitutionGroup: %s", elem->substGroup);
685 if (elem->substGroupNs != NULL)
686 fprintf(output, " ns %s\n", elem->substGroupNs);
687 else
688 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000689 }
690 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000691 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000692}
693
694/**
695 * xmlSchemaAnnotDump:
696 * @output: the file output
697 * @annot: a annotation
698 *
699 * Dump the annotation
700 */
701static void
702xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
703{
704 xmlChar *content;
705
706 if (annot == NULL)
707 return;
708
709 content = xmlNodeGetContent(annot->content);
710 if (content != NULL) {
711 fprintf(output, " Annot: %s\n", content);
712 xmlFree(content);
713 } else
714 fprintf(output, " Annot: empty\n");
715}
716
717/**
718 * xmlSchemaTypeDump:
719 * @output: the file output
720 * @type: a type structure
721 *
722 * Dump a SchemaType structure
723 */
724static void
725xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
726{
727 if (type == NULL) {
728 fprintf(output, "Type: NULL\n");
729 return;
730 }
731 fprintf(output, "Type: ");
732 if (type->name != NULL)
733 fprintf(output, "%s, ", type->name);
734 else
735 fprintf(output, "no name");
736 switch (type->type) {
737 case XML_SCHEMA_TYPE_BASIC:
738 fprintf(output, "basic ");
739 break;
740 case XML_SCHEMA_TYPE_SIMPLE:
741 fprintf(output, "simple ");
742 break;
743 case XML_SCHEMA_TYPE_COMPLEX:
744 fprintf(output, "complex ");
745 break;
746 case XML_SCHEMA_TYPE_SEQUENCE:
747 fprintf(output, "sequence ");
748 break;
749 case XML_SCHEMA_TYPE_CHOICE:
750 fprintf(output, "choice ");
751 break;
752 case XML_SCHEMA_TYPE_ALL:
753 fprintf(output, "all ");
754 break;
755 case XML_SCHEMA_TYPE_UR:
756 fprintf(output, "ur ");
757 break;
758 case XML_SCHEMA_TYPE_RESTRICTION:
759 fprintf(output, "restriction ");
760 break;
761 case XML_SCHEMA_TYPE_EXTENSION:
762 fprintf(output, "extension ");
763 break;
764 default:
765 fprintf(output, "unknowntype%d ", type->type);
766 break;
767 }
768 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000769 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000770 }
771 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000772 case XML_SCHEMA_CONTENT_UNKNOWN:
773 fprintf(output, "unknown ");
774 break;
775 case XML_SCHEMA_CONTENT_EMPTY:
776 fprintf(output, "empty ");
777 break;
778 case XML_SCHEMA_CONTENT_ELEMENTS:
779 fprintf(output, "element ");
780 break;
781 case XML_SCHEMA_CONTENT_MIXED:
782 fprintf(output, "mixed ");
783 break;
784 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
785 fprintf(output, "mixed_or_elems ");
786 break;
787 case XML_SCHEMA_CONTENT_BASIC:
788 fprintf(output, "basic ");
789 break;
790 case XML_SCHEMA_CONTENT_SIMPLE:
791 fprintf(output, "simple ");
792 break;
793 case XML_SCHEMA_CONTENT_ANY:
794 fprintf(output, "any ");
795 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000796 }
797 fprintf(output, "\n");
798 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000799 fprintf(output, " ");
800 if (type->minOccurs != 1)
801 fprintf(output, "min: %d ", type->minOccurs);
802 if (type->maxOccurs >= UNBOUNDED)
803 fprintf(output, "max: unbounded\n");
804 else if (type->maxOccurs != 1)
805 fprintf(output, "max: %d\n", type->maxOccurs);
806 else
807 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000808 }
809 if (type->annot != NULL)
810 xmlSchemaAnnotDump(output, type->annot);
811 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000812 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000813
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000814 fprintf(output, " subtypes: ");
815 while (sub != NULL) {
816 fprintf(output, "%s ", sub->name);
817 sub = sub->next;
818 }
819 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000820 }
821
822}
823
824/**
825 * xmlSchemaDump:
826 * @output: the file output
827 * @schema: a schema structure
828 *
829 * Dump a Schema structure.
830 */
831void
832xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
833{
834 if (schema == NULL) {
835 fprintf(output, "Schemas: NULL\n");
836 return;
837 }
838 fprintf(output, "Schemas: ");
839 if (schema->name != NULL)
840 fprintf(output, "%s, ", schema->name);
841 else
842 fprintf(output, "no name, ");
843 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000844 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000845 else
846 fprintf(output, "no target namespace");
847 fprintf(output, "\n");
848 if (schema->annot != NULL)
849 xmlSchemaAnnotDump(output, schema->annot);
850
851 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
852 output);
853 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000854 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000855}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000856#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000857
858/************************************************************************
859 * *
860 * Parsing functions *
861 * *
862 ************************************************************************/
863
864/**
865 * xmlSchemaGetType:
866 * @schema: the schemas context
867 * @name: the type name
868 * @ns: the type namespace
869 *
870 * Lookup a type in the schemas or the predefined types
871 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000872 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +0000873 */
874static xmlSchemaTypePtr
875xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000876 const xmlChar * namespace)
877{
Daniel Veillard4255d502002-04-16 15:50:10 +0000878 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +0000879 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +0000880
881 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000882 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000883 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000884 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
885 if (ret != NULL)
886 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000887 }
888 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +0000889 if (ret != NULL)
890 return (ret);
891 import = xmlHashLookup(schema->schemasImports, namespace);
892 if (import != NULL)
893 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000894#ifdef DEBUG
895 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000896 if (namespace == NULL)
897 fprintf(stderr, "Unable to lookup type %s", name);
898 else
899 fprintf(stderr, "Unable to lookup type %s:%s", name,
900 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000901 }
902#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000903 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000904}
905
906/************************************************************************
907 * *
908 * Parsing functions *
909 * *
910 ************************************************************************/
911
912#define IS_BLANK_NODE(n) \
913 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
914
915/**
916 * xmlSchemaIsBlank:
917 * @str: a string
918 *
919 * Check if a string is ignorable
920 *
921 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
922 */
923static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000924xmlSchemaIsBlank(xmlChar * str)
925{
Daniel Veillard4255d502002-04-16 15:50:10 +0000926 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000927 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000928 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +0000929 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000930 return (0);
931 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +0000932 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000933 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000934}
935
936/**
937 * xmlSchemaAddNotation:
938 * @ctxt: a schema validation context
939 * @schema: the schema being built
940 * @name: the item name
941 *
942 * Add an XML schema Attrribute declaration
943 * *WARNING* this interface is highly subject to change
944 *
945 * Returns the new struture or NULL in case of error
946 */
947static xmlSchemaNotationPtr
948xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000949 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +0000950{
951 xmlSchemaNotationPtr ret = NULL;
952 int val;
953
954 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
955 return (NULL);
956
957 if (schema->notaDecl == NULL)
958 schema->notaDecl = xmlHashCreate(10);
959 if (schema->notaDecl == NULL)
960 return (NULL);
961
962 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
963 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000964 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000965 return (NULL);
966 }
967 memset(ret, 0, sizeof(xmlSchemaNotation));
968 ret->name = xmlStrdup(name);
969 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
970 ret);
971 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000972 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
973 XML_SCHEMAP_REDEFINED_NOTATION,
974 "Notation %s already defined\n",
975 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000976 xmlFree((char *) ret->name);
977 xmlFree(ret);
978 return (NULL);
979 }
980 return (ret);
981}
982
983
984/**
985 * xmlSchemaAddAttribute:
986 * @ctxt: a schema validation context
987 * @schema: the schema being built
988 * @name: the item name
989 * @container: the container's name
990 *
991 * Add an XML schema Attrribute declaration
992 * *WARNING* this interface is highly subject to change
993 *
994 * Returns the new struture or NULL in case of error
995 */
996static xmlSchemaAttributePtr
997xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
998 const xmlChar * name)
999{
1000 xmlSchemaAttributePtr ret = NULL;
1001 int val;
1002
1003 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1004 return (NULL);
1005
1006 if (schema->attrDecl == NULL)
1007 schema->attrDecl = xmlHashCreate(10);
1008 if (schema->attrDecl == NULL)
1009 return (NULL);
1010
1011 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1012 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001013 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001014 return (NULL);
1015 }
1016 memset(ret, 0, sizeof(xmlSchemaAttribute));
1017 ret->name = xmlStrdup(name);
1018 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001019 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001020 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001021 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1022 XML_SCHEMAP_REDEFINED_ATTR,
1023 "Attribute %s already defined\n",
1024 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001025 xmlFree((char *) ret->name);
1026 xmlFree(ret);
1027 return (NULL);
1028 }
1029 return (ret);
1030}
1031
1032/**
1033 * xmlSchemaAddAttributeGroup:
1034 * @ctxt: a schema validation context
1035 * @schema: the schema being built
1036 * @name: the item name
1037 *
1038 * Add an XML schema Attrribute Group declaration
1039 *
1040 * Returns the new struture or NULL in case of error
1041 */
1042static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001043xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1044 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001045{
1046 xmlSchemaAttributeGroupPtr ret = NULL;
1047 int val;
1048
1049 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1050 return (NULL);
1051
1052 if (schema->attrgrpDecl == NULL)
1053 schema->attrgrpDecl = xmlHashCreate(10);
1054 if (schema->attrgrpDecl == NULL)
1055 return (NULL);
1056
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001057 ret =
1058 (xmlSchemaAttributeGroupPtr)
1059 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001060 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001061 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001062 return (NULL);
1063 }
1064 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
1065 ret->name = xmlStrdup(name);
1066 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001067 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001068 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001069 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1070 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1071 "Attribute group %s already defined\n",
1072 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001073 xmlFree((char *) ret->name);
1074 xmlFree(ret);
1075 return (NULL);
1076 }
1077 return (ret);
1078}
1079
1080/**
1081 * xmlSchemaAddElement:
1082 * @ctxt: a schema validation context
1083 * @schema: the schema being built
1084 * @name: the type name
1085 * @namespace: the type namespace
1086 *
1087 * Add an XML schema Element declaration
1088 * *WARNING* this interface is highly subject to change
1089 *
1090 * Returns the new struture or NULL in case of error
1091 */
1092static xmlSchemaElementPtr
1093xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1094 const xmlChar * name, const xmlChar * namespace)
1095{
1096 xmlSchemaElementPtr ret = NULL;
1097 int val;
1098
1099 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1100 return (NULL);
1101
1102 if (schema->elemDecl == NULL)
1103 schema->elemDecl = xmlHashCreate(10);
1104 if (schema->elemDecl == NULL)
1105 return (NULL);
1106
1107 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1108 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001109 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001110 return (NULL);
1111 }
1112 memset(ret, 0, sizeof(xmlSchemaElement));
1113 ret->name = xmlStrdup(name);
1114 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001115 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001116 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001117 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001118
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001119 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
1120 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1121 namespace, ret);
1122 if (val != 0) {
1123 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1124 XML_SCHEMAP_REDEFINED_ELEMENT,
1125 "Element %s already defined\n",
1126 name, NULL);
1127 xmlFree((char *) ret->name);
1128 xmlFree(ret);
1129 return (NULL);
1130 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001131 }
1132 return (ret);
1133}
1134
1135/**
1136 * xmlSchemaAddType:
1137 * @ctxt: a schema validation context
1138 * @schema: the schema being built
1139 * @name: the item name
1140 *
1141 * Add an XML schema Simple Type definition
1142 * *WARNING* this interface is highly subject to change
1143 *
1144 * Returns the new struture or NULL in case of error
1145 */
1146static xmlSchemaTypePtr
1147xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1148 const xmlChar * name)
1149{
1150 xmlSchemaTypePtr ret = NULL;
1151 int val;
1152
1153 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1154 return (NULL);
1155
1156 if (schema->typeDecl == NULL)
1157 schema->typeDecl = xmlHashCreate(10);
1158 if (schema->typeDecl == NULL)
1159 return (NULL);
1160
1161 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1162 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001163 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001164 return (NULL);
1165 }
1166 memset(ret, 0, sizeof(xmlSchemaType));
1167 ret->name = xmlStrdup(name);
1168 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1169 ret);
1170 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001171 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1172 XML_SCHEMAP_REDEFINED_TYPE,
1173 "Type %s already defined\n",
1174 name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001175 xmlFree((char *) ret->name);
1176 xmlFree(ret);
1177 return (NULL);
1178 }
1179 ret->minOccurs = 1;
1180 ret->maxOccurs = 1;
1181
1182 return (ret);
1183}
1184
1185/**
1186 * xmlSchemaAddGroup:
1187 * @ctxt: a schema validation context
1188 * @schema: the schema being built
1189 * @name: the group name
1190 *
1191 * Add an XML schema Group definition
1192 *
1193 * Returns the new struture or NULL in case of error
1194 */
1195static xmlSchemaTypePtr
1196xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001197 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001198{
1199 xmlSchemaTypePtr ret = NULL;
1200 int val;
1201
1202 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1203 return (NULL);
1204
1205 if (schema->groupDecl == NULL)
1206 schema->groupDecl = xmlHashCreate(10);
1207 if (schema->groupDecl == NULL)
1208 return (NULL);
1209
1210 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1211 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001212 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001213 return (NULL);
1214 }
1215 memset(ret, 0, sizeof(xmlSchemaType));
1216 ret->name = xmlStrdup(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001217 val =
1218 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1219 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001220 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001221 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1222 XML_SCHEMAP_REDEFINED_GROUP,
1223 "Group %s already defined\n",
1224 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001225 xmlFree((char *) ret->name);
1226 xmlFree(ret);
1227 return (NULL);
1228 }
1229 ret->minOccurs = 1;
1230 ret->maxOccurs = 1;
1231
1232 return (ret);
1233}
1234
1235/************************************************************************
1236 * *
1237 * Utilities for parsing *
1238 * *
1239 ************************************************************************/
1240
1241/**
1242 * xmlGetQNameProp:
1243 * @ctxt: a schema validation context
1244 * @node: a subtree containing XML Schema informations
1245 * @name: the attribute name
1246 * @namespace: the result namespace if any
1247 *
1248 * Extract a QName Attribute value
1249 *
1250 * Returns the NCName or NULL if not found, and also update @namespace
1251 * with the namespace URI
1252 */
1253static xmlChar *
1254xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001255 const char *name, xmlChar ** namespace)
1256{
Daniel Veillard4255d502002-04-16 15:50:10 +00001257 xmlChar *val, *ret, *prefix;
1258 xmlNsPtr ns;
1259
1260
1261 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001262 *namespace = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001263 val = xmlGetProp(node, (const xmlChar *) name);
1264 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001265 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001266
1267 ret = xmlSplitQName2(val, &prefix);
1268 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001269 return (val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001270 xmlFree(val);
1271
1272 ns = xmlSearchNs(node->doc, node, prefix);
1273 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001274 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1275 "Attribute %s: the QName prefix %s is undefined\n",
1276 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001277 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001278 *namespace = xmlStrdup(ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +00001279 }
1280 xmlFree(prefix);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001281 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001282}
1283
1284/**
1285 * xmlGetMaxOccurs:
1286 * @ctxt: a schema validation context
1287 * @node: a subtree containing XML Schema informations
1288 *
1289 * Get the maxOccurs property
1290 *
1291 * Returns the default if not found, or the value
1292 */
1293static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001294xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1295{
Daniel Veillard4255d502002-04-16 15:50:10 +00001296 xmlChar *val, *cur;
1297 int ret = 0;
1298
1299 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1300 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001301 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001302
1303 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001304 xmlFree(val);
1305 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001306 }
1307
1308 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001309 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001310 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001311 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001312 ret = ret * 10 + (*cur - '0');
1313 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001314 }
William M. Brack76e95df2003-10-18 16:20:14 +00001315 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001316 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001317 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001318 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1319 "invalid value for maxOccurs: %s\n", val, NULL);
1320 xmlFree(val);
1321 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001322 }
1323 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001324 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001325}
1326
1327/**
1328 * xmlGetMinOccurs:
1329 * @ctxt: a schema validation context
1330 * @node: a subtree containing XML Schema informations
1331 *
1332 * Get the minOccurs property
1333 *
1334 * Returns the default if not found, or the value
1335 */
1336static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001337xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1338{
Daniel Veillard4255d502002-04-16 15:50:10 +00001339 xmlChar *val, *cur;
1340 int ret = 0;
1341
1342 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1343 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001344 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001345
1346 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001347 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001348 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001349 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 ret = ret * 10 + (*cur - '0');
1351 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001352 }
William M. Brack76e95df2003-10-18 16:20:14 +00001353 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001354 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001355 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001356 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1357 "invalid value for minOccurs: %s\n", val, NULL);
1358 xmlFree(val);
1359 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001360 }
1361 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001362 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001363}
1364
1365/**
1366 * xmlGetBooleanProp:
1367 * @ctxt: a schema validation context
1368 * @node: a subtree containing XML Schema informations
1369 * @name: the attribute name
1370 * @def: the default value
1371 *
1372 * Get is a bolean property is set
1373 *
1374 * Returns the default if not found, 0 if found to be false,
1375 * 1 if found to be true
1376 */
1377static int
1378xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001379 const char *name, int def)
1380{
Daniel Veillard4255d502002-04-16 15:50:10 +00001381 xmlChar *val;
1382
1383 val = xmlGetProp(node, (const xmlChar *) name);
1384 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001385 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001386
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001387 if (xmlStrEqual(val, BAD_CAST "true"))
1388 def = 1;
1389 else if (xmlStrEqual(val, BAD_CAST "false"))
1390 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001391 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001392 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1393 "Attribute %s: the value %s is not boolean\n",
1394 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001395 }
1396 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001397 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001398}
1399
1400/************************************************************************
1401 * *
1402 * Shema extraction from an Infoset *
1403 * *
1404 ************************************************************************/
1405static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1406 ctxt, xmlSchemaPtr schema,
1407 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001408static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1409 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001410 xmlSchemaPtr schema,
1411 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1413 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001414 xmlSchemaPtr schema,
1415 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001416 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001417static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1418 xmlSchemaPtr schema,
1419 xmlNodePtr node);
1420static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1421 xmlSchemaPtr schema,
1422 xmlNodePtr node);
1423static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1424 ctxt,
1425 xmlSchemaPtr schema,
1426 xmlNodePtr node);
1427static xmlSchemaAttributeGroupPtr
1428xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1429 xmlSchemaPtr schema, xmlNodePtr node);
1430static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1431 xmlSchemaPtr schema,
1432 xmlNodePtr node);
1433static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1434 xmlSchemaPtr schema,
1435 xmlNodePtr node);
1436static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001437xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1438 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001439
1440/**
1441 * xmlSchemaParseAttrDecls:
1442 * @ctxt: a schema validation context
1443 * @schema: the schema being built
1444 * @node: a subtree containing XML Schema informations
1445 * @type: the hosting type
1446 *
1447 * parse a XML schema attrDecls declaration corresponding to
1448 * <!ENTITY % attrDecls
1449 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1450 */
1451static xmlNodePtr
1452xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1453 xmlNodePtr child, xmlSchemaTypePtr type)
1454{
1455 xmlSchemaAttributePtr lastattr, attr;
1456
1457 lastattr = NULL;
1458 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001459 (IS_SCHEMA(child, "attributeGroup"))) {
1460 attr = NULL;
1461 if (IS_SCHEMA(child, "attribute")) {
1462 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1463 } else if (IS_SCHEMA(child, "attributeGroup")) {
1464 attr = (xmlSchemaAttributePtr)
1465 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1466 }
1467 if (attr != NULL) {
1468 if (lastattr == NULL) {
1469 type->attributes = attr;
1470 lastattr = attr;
1471 } else {
1472 lastattr->next = attr;
1473 lastattr = attr;
1474 }
1475 }
1476 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001477 }
1478 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001479 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1480 if (attr != NULL) {
1481 if (lastattr == NULL) {
1482 type->attributes = attr;
1483 lastattr = attr;
1484 } else {
1485 lastattr->next = attr;
1486 lastattr = attr;
1487 }
1488 }
1489 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001490 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001491 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001492}
1493
1494/**
1495 * xmlSchemaParseAnnotation:
1496 * @ctxt: a schema validation context
1497 * @schema: the schema being built
1498 * @node: a subtree containing XML Schema informations
1499 *
1500 * parse a XML schema Attrribute declaration
1501 * *WARNING* this interface is highly subject to change
1502 *
1503 * Returns -1 in case of error, 0 if the declaration is inproper and
1504 * 1 in case of success.
1505 */
1506static xmlSchemaAnnotPtr
1507xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1508 xmlNodePtr node)
1509{
1510 xmlSchemaAnnotPtr ret;
1511
1512 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1513 return (NULL);
1514 ret = xmlSchemaNewAnnot(ctxt, node);
1515
1516 return (ret);
1517}
1518
1519/**
1520 * xmlSchemaParseFacet:
1521 * @ctxt: a schema validation context
1522 * @schema: the schema being built
1523 * @node: a subtree containing XML Schema informations
1524 *
1525 * parse a XML schema Facet declaration
1526 * *WARNING* this interface is highly subject to change
1527 *
1528 * Returns the new type structure or NULL in case of error
1529 */
1530static xmlSchemaFacetPtr
1531xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001533{
1534 xmlSchemaFacetPtr facet;
1535 xmlNodePtr child = NULL;
1536 xmlChar *value;
1537
1538 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1539 return (NULL);
1540
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001541 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 if (facet == NULL) {
1543 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1544 return (NULL);
1545 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001546 facet->node = node;
1547 value = xmlGetProp(node, (const xmlChar *) "value");
1548 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001549 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1550 "Facet %s has no value\n", node->name, NULL);
1551 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001552 return (NULL);
1553 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001554 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001555 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001556 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001557 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001558 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001559 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001560 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001561 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001563 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001564 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001565 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001567 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001569 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001571 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001572 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001573 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001574 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001575 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1576 } else if (IS_SCHEMA(node, "minLength")) {
1577 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1578 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001579 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1580 "Unknown facet type %s\n", node->name, NULL);
1581 xmlSchemaFreeFacet(facet);
1582 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001583 }
1584 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1585 facet->value = value;
1586 child = node->children;
1587
1588 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001589 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1590 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001591 }
1592 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001593 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1594 "Facet %s has unexpected child content\n",
1595 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001596 }
1597 return (facet);
1598}
1599
1600/**
1601 * xmlSchemaParseAny:
1602 * @ctxt: a schema validation context
1603 * @schema: the schema being built
1604 * @node: a subtree containing XML Schema informations
1605 *
1606 * parse a XML schema Any declaration
1607 * *WARNING* this interface is highly subject to change
1608 *
1609 * Returns the new type structure or NULL in case of error
1610 */
1611static xmlSchemaTypePtr
1612xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1613 xmlNodePtr node)
1614{
1615 xmlSchemaTypePtr type;
1616 xmlNodePtr child = NULL;
1617 xmlChar name[30];
1618
1619 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1620 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001621 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001622 type = xmlSchemaAddType(ctxt, schema, name);
1623 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001624 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001625 type->node = node;
1626 type->type = XML_SCHEMA_TYPE_ANY;
1627 child = node->children;
1628 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1629 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1630
1631 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001632 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1633 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001634 }
1635 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001636 xmlSchemaPErr2(ctxt, node, child,
1637 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1638 "Sequence %s has unexpected content\n", type->name,
1639 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001640 }
1641
1642 return (type);
1643}
1644
1645/**
1646 * xmlSchemaParseNotation:
1647 * @ctxt: a schema validation context
1648 * @schema: the schema being built
1649 * @node: a subtree containing XML Schema informations
1650 *
1651 * parse a XML schema Notation declaration
1652 *
1653 * Returns the new structure or NULL in case of error
1654 */
1655static xmlSchemaNotationPtr
1656xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001657 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001658{
1659 xmlChar *name;
1660 xmlSchemaNotationPtr ret;
1661 xmlNodePtr child = NULL;
1662
1663 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1664 return (NULL);
1665 name = xmlGetProp(node, (const xmlChar *) "name");
1666 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001667 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1668 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001669 return (NULL);
1670 }
1671 ret = xmlSchemaAddNotation(ctxt, schema, name);
1672 if (ret == NULL) {
1673 xmlFree(name);
1674 return (NULL);
1675 }
1676 child = node->children;
1677 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001678 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1679 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001680 }
1681 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001682 xmlSchemaPErr2(ctxt, node, child,
1683 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1684 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001685 }
1686
1687 return (ret);
1688}
1689
1690/**
1691 * xmlSchemaParseAnyAttribute:
1692 * @ctxt: a schema validation context
1693 * @schema: the schema being built
1694 * @node: a subtree containing XML Schema informations
1695 *
1696 * parse a XML schema AnyAttrribute declaration
1697 * *WARNING* this interface is highly subject to change
1698 *
1699 * Returns an attribute def structure or NULL
1700 */
1701static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001702xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1703 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001704{
1705 xmlChar *processContents;
1706 xmlSchemaAttributePtr ret;
1707 xmlNodePtr child = NULL;
1708 char name[100];
1709
1710 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1711 return (NULL);
1712
1713 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001714 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *) name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001715 if (ret == NULL) {
1716 return (NULL);
1717 }
1718 ret->id = xmlGetProp(node, (const xmlChar *) "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001719 processContents =
1720 xmlGetProp(node, (const xmlChar *) "processContents");
1721 if ((processContents == NULL)
1722 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1723 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1724 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1725 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1726 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1727 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001728 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001729 xmlSchemaPErr2(ctxt, node, child,
1730 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1731 "anyAttribute has unexpected content for processContents: %s\n",
1732 processContents, NULL);
1733 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001734 }
1735 if (processContents != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001736 xmlFree(processContents);
Daniel Veillard4255d502002-04-16 15:50:10 +00001737
1738 child = node->children;
1739 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001740 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1741 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001742 }
1743 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001744 xmlSchemaPErr2(ctxt, node, child,
1745 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1746 "anyAttribute %s has unexpected content\n",
1747 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001748 }
1749
1750 return (ret);
1751}
1752
1753
1754/**
1755 * xmlSchemaParseAttribute:
1756 * @ctxt: a schema validation context
1757 * @schema: the schema being built
1758 * @node: a subtree containing XML Schema informations
1759 *
1760 * parse a XML schema Attrribute declaration
1761 * *WARNING* this interface is highly subject to change
1762 *
1763 * Returns -1 in case of error, 0 if the declaration is inproper and
1764 * 1 in case of success.
1765 */
1766static xmlSchemaAttributePtr
1767xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1768 xmlNodePtr node)
1769{
1770 xmlChar *name, *refNs = NULL, *ref = NULL;
1771 xmlSchemaAttributePtr ret;
1772 xmlNodePtr child = NULL;
1773
1774 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1775 return (NULL);
1776 name = xmlGetProp(node, (const xmlChar *) "name");
1777 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001778 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001779
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001780 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1781 if (ref == NULL) {
1782 xmlSchemaPErr2(ctxt, node, child,
1783 XML_SCHEMAP_ATTR_NONAME_NOREF,
1784 "Attribute has no name nor ref\n", NULL, NULL);
1785 return (NULL);
1786 }
1787 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1788 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001789 }
1790 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1791 if (ret == NULL) {
1792 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001793 if (ref != NULL)
1794 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001795 return (NULL);
1796 }
1797 xmlFree(name);
1798 ret->ref = ref;
1799 ret->refNs = refNs;
1800 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001801 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001802 child = node->children;
1803 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001804 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1805 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 }
1807 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001808 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1809 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001810 }
1811 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
1813 "attribute %s has unexpected content\n", name,
1814 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001815 }
1816
1817 return (ret);
1818}
1819
1820/**
1821 * xmlSchemaParseAttributeGroup:
1822 * @ctxt: a schema validation context
1823 * @schema: the schema being built
1824 * @node: a subtree containing XML Schema informations
1825 *
1826 * parse a XML schema Attribute Group declaration
1827 * *WARNING* this interface is highly subject to change
1828 *
1829 * Returns the attribute group or NULL in case of error.
1830 */
1831static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001832xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1833 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001834{
1835 xmlChar *name, *refNs = NULL, *ref = NULL;
1836 xmlSchemaAttributeGroupPtr ret;
1837 xmlSchemaAttributePtr last = NULL, attr;
1838 xmlNodePtr child = NULL;
1839 xmlChar *oldcontainer;
1840
1841 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1842 return (NULL);
1843 oldcontainer = ctxt->container;
1844 name = xmlGetProp(node, (const xmlChar *) "name");
1845 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001846 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001847
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001848 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1849 if (ref == NULL) {
1850 xmlSchemaPErr2(ctxt, node, child,
1851 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
1852 "AttributeGroup has no name nor ref\n", NULL,
1853 NULL);
1854 return (NULL);
1855 }
1856 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1857 name = xmlStrdup((xmlChar *) buf);
1858 if (name == NULL) {
1859 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
1860 return (NULL);
1861 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001862 }
1863 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1864 if (ret == NULL) {
1865 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001866 if (ref != NULL)
1867 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001868 return (NULL);
1869 }
1870 ret->ref = ref;
1871 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00001872 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001873 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001874 child = node->children;
1875 ctxt->container = name;
1876 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001877 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1878 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001879 }
1880 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001881 (IS_SCHEMA(child, "attributeGroup"))) {
1882 attr = NULL;
1883 if (IS_SCHEMA(child, "attribute")) {
1884 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1885 } else if (IS_SCHEMA(child, "attributeGroup")) {
1886 attr = (xmlSchemaAttributePtr)
1887 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1888 }
1889 if (attr != NULL) {
1890 if (last == NULL) {
1891 ret->attributes = attr;
1892 last = attr;
1893 } else {
1894 last->next = attr;
1895 last = attr;
1896 }
1897 }
1898 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001899 }
1900 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001901 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001902 }
1903 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001904 xmlSchemaPErr2(ctxt, node, child,
1905 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
1906 "attribute group %s has unexpected content\n", name,
1907 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001908 }
1909
1910 ctxt->container = oldcontainer;
Daniel Veillard91a13252003-03-27 23:44:43 +00001911 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001912 return (ret);
1913}
1914
1915/**
1916 * xmlSchemaParseElement:
1917 * @ctxt: a schema validation context
1918 * @schema: the schema being built
1919 * @node: a subtree containing XML Schema informations
1920 *
1921 * parse a XML schema Element declaration
1922 * *WARNING* this interface is highly subject to change
1923 *
1924 * Returns -1 in case of error, 0 if the declaration is inproper and
1925 * 1 in case of success.
1926 */
1927static xmlSchemaElementPtr
1928xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1929 xmlNodePtr node, int toplevel)
1930{
1931 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1932 xmlSchemaElementPtr ret;
1933 xmlNodePtr child = NULL;
1934 xmlChar *oldcontainer;
1935
1936 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1937 return (NULL);
1938 oldcontainer = ctxt->container;
1939 name = xmlGetProp(node, (const xmlChar *) "name");
1940 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001941 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001942
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001943 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1944 if (ref == NULL) {
1945 xmlSchemaPErr2(ctxt, node, child,
1946 XML_SCHEMAP_ELEM_NONAME_NOREF,
1947 "Element has no name nor ref\n", NULL, NULL);
1948 return (NULL);
1949 }
1950 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1951 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001952 }
1953 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1954 if (namespace == NULL)
1955 ret =
1956 xmlSchemaAddElement(ctxt, schema, name,
1957 schema->targetNamespace);
1958 else
1959 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001960 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001961 if (namespace != NULL)
1962 xmlFree(namespace);
1963 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001964 xmlFree(name);
1965 if (ref != NULL)
1966 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001967 return (NULL);
1968 }
1969 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1970 ret->ref = ref;
1971 ret->refNs = refNs;
1972 if (ref != NULL)
1973 ret->flags |= XML_SCHEMAS_ELEM_REF;
1974 if (toplevel)
1975 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1976 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1977 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1978 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1979 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1980 ctxt->container = name;
1981
1982 ret->id = xmlGetProp(node, BAD_CAST "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001983 ret->namedType =
1984 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1985 ret->substGroup =
1986 xmlGetQNameProp(ctxt, node, "substitutionGroup",
1987 &(ret->substGroupNs));
Daniel Veillard4255d502002-04-16 15:50:10 +00001988 fixed = xmlGetProp(node, BAD_CAST "fixed");
1989 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1990 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001991
Daniel Veillard4255d502002-04-16 15:50:10 +00001992 ret->value = xmlGetProp(node, BAD_CAST "default");
1993 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
1995 "Element %s has both default and fixed\n",
1996 ret->name, NULL);
1997 xmlFree(fixed);
Daniel Veillard4255d502002-04-16 15:50:10 +00001998 } else if (fixed != NULL) {
1999 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002000 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002001 }
2002
2003 child = node->children;
2004 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002005 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2006 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002007 }
2008 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002009 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002010 child = child->next;
2011 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002012 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002013 child = child->next;
2014 }
2015 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002016 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2017 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002018 }
2019 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002020 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2021 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002022 }
2023
2024 ctxt->container = oldcontainer;
2025 xmlFree(name);
2026 return (ret);
2027}
2028
2029/**
2030 * xmlSchemaParseUnion:
2031 * @ctxt: a schema validation context
2032 * @schema: the schema being built
2033 * @node: a subtree containing XML Schema informations
2034 *
2035 * parse a XML schema Union definition
2036 * *WARNING* this interface is highly subject to change
2037 *
2038 * Returns -1 in case of error, 0 if the declaration is inproper and
2039 * 1 in case of success.
2040 */
2041static xmlSchemaTypePtr
2042xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002043 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002044{
2045 xmlSchemaTypePtr type, subtype, last = NULL;
2046 xmlNodePtr child = NULL;
2047 xmlChar name[30];
2048
2049 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2050 return (NULL);
2051
2052
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002053 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002054 type = xmlSchemaAddType(ctxt, schema, name);
2055 if (type == NULL)
2056 return (NULL);
2057 type->node = node;
2058 type->type = XML_SCHEMA_TYPE_LIST;
2059 type->id = xmlGetProp(node, BAD_CAST "id");
2060 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
2061
2062 child = node->children;
2063 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002064 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2065 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002066 }
2067 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002068 subtype = (xmlSchemaTypePtr)
2069 xmlSchemaParseSimpleType(ctxt, schema, child);
2070 if (subtype != NULL) {
2071 if (last == NULL) {
2072 type->subtypes = subtype;
2073 last = subtype;
2074 } else {
2075 last->next = subtype;
2076 last = subtype;
2077 }
2078 last->next = NULL;
2079 }
2080 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002081 }
2082 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002083 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2084 "Union %s has unexpected content\n", type->name,
2085 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002086 }
2087 return (type);
2088}
2089
2090/**
2091 * xmlSchemaParseList:
2092 * @ctxt: a schema validation context
2093 * @schema: the schema being built
2094 * @node: a subtree containing XML Schema informations
2095 *
2096 * parse a XML schema List definition
2097 * *WARNING* this interface is highly subject to change
2098 *
2099 * Returns -1 in case of error, 0 if the declaration is inproper and
2100 * 1 in case of success.
2101 */
2102static xmlSchemaTypePtr
2103xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002104 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002105{
2106 xmlSchemaTypePtr type, subtype;
2107 xmlNodePtr child = NULL;
2108 xmlChar name[30];
2109
2110 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2111 return (NULL);
2112
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002113 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002114 type = xmlSchemaAddType(ctxt, schema, name);
2115 if (type == NULL)
2116 return (NULL);
2117 type->node = node;
2118 type->type = XML_SCHEMA_TYPE_LIST;
2119 type->id = xmlGetProp(node, BAD_CAST "id");
2120 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2121
2122 child = node->children;
2123 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002124 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2125 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002126 }
2127 subtype = NULL;
2128 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002129 subtype = (xmlSchemaTypePtr)
2130 xmlSchemaParseSimpleType(ctxt, schema, child);
2131 child = child->next;
2132 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 }
2134 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002135 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2136 "List %s has unexpected content\n", type->name,
2137 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002138 }
2139 return (type);
2140}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002141
Daniel Veillard4255d502002-04-16 15:50:10 +00002142/**
2143 * xmlSchemaParseSimpleType:
2144 * @ctxt: a schema validation context
2145 * @schema: the schema being built
2146 * @node: a subtree containing XML Schema informations
2147 *
2148 * parse a XML schema Simple Type definition
2149 * *WARNING* this interface is highly subject to change
2150 *
2151 * Returns -1 in case of error, 0 if the declaration is inproper and
2152 * 1 in case of success.
2153 */
2154static xmlSchemaTypePtr
2155xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2156 xmlNodePtr node)
2157{
2158 xmlSchemaTypePtr type, subtype;
2159 xmlNodePtr child = NULL;
2160 xmlChar *name;
2161
2162 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2163 return (NULL);
2164
2165
2166 name = xmlGetProp(node, (const xmlChar *) "name");
2167 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002168 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002169
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002170 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
2171 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002172 }
2173 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002174 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_SIMPLETYPE_NONAME,
2175 "simpleType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002176 return (NULL);
2177 }
2178 type = xmlSchemaAddType(ctxt, schema, name);
2179 xmlFree(name);
2180 if (type == NULL)
2181 return (NULL);
2182 type->node = node;
2183 type->type = XML_SCHEMA_TYPE_SIMPLE;
2184 type->id = xmlGetProp(node, BAD_CAST "id");
2185
2186 child = node->children;
2187 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002188 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2189 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002190 }
2191 subtype = NULL;
2192 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002193 subtype = (xmlSchemaTypePtr)
2194 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2195 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002196 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002197 subtype = (xmlSchemaTypePtr)
2198 xmlSchemaParseList(ctxt, schema, child);
2199 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002200 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002201 subtype = (xmlSchemaTypePtr)
2202 xmlSchemaParseUnion(ctxt, schema, child);
2203 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002204 }
2205 type->subtypes = subtype;
2206 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002207 xmlSchemaPErr2(ctxt, node, child,
2208 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2209 "SimpleType %s has unexpected content\n",
2210 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002211 }
2212
2213 return (type);
2214}
2215
2216
2217/**
2218 * xmlSchemaParseGroup:
2219 * @ctxt: a schema validation context
2220 * @schema: the schema being built
2221 * @node: a subtree containing XML Schema informations
2222 *
2223 * parse a XML schema Group definition
2224 * *WARNING* this interface is highly subject to change
2225 *
2226 * Returns -1 in case of error, 0 if the declaration is inproper and
2227 * 1 in case of success.
2228 */
2229static xmlSchemaTypePtr
2230xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002232{
2233 xmlSchemaTypePtr type, subtype;
2234 xmlNodePtr child = NULL;
2235 xmlChar *name, *ref = NULL, *refNs = NULL;
2236
2237 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2238 return (NULL);
2239
2240
2241 name = xmlGetProp(node, (const xmlChar *) "name");
2242 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002244
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002245 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2246 if (ref == NULL) {
2247 xmlSchemaPErr2(ctxt, node, child,
2248 XML_SCHEMAP_GROUP_NONAME_NOREF,
2249 "Group has no name nor ref\n", NULL, NULL);
2250 return (NULL);
2251 }
2252 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2253 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002254 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002255 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard1d913862003-11-21 00:28:39 +00002256 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002257 if (type == NULL)
2258 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002259
Daniel Veillard4255d502002-04-16 15:50:10 +00002260 type->node = node;
2261 type->type = XML_SCHEMA_TYPE_GROUP;
2262 type->id = xmlGetProp(node, BAD_CAST "id");
2263 type->ref = ref;
2264 type->refNs = refNs;
2265 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2266 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2267
2268 child = node->children;
2269 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002270 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2271 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002272 }
2273 subtype = NULL;
2274 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002275 subtype = (xmlSchemaTypePtr)
2276 xmlSchemaParseAll(ctxt, schema, child);
2277 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002278 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002279 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002281 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002282 subtype = (xmlSchemaTypePtr)
2283 xmlSchemaParseSequence(ctxt, schema, child);
2284 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002285 }
2286 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002287 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002289 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2290 "Group %s has unexpected content\n", type->name,
2291 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002292 }
2293
2294 return (type);
2295}
2296
2297/**
2298 * xmlSchemaParseAll:
2299 * @ctxt: a schema validation context
2300 * @schema: the schema being built
2301 * @node: a subtree containing XML Schema informations
2302 *
2303 * parse a XML schema All definition
2304 * *WARNING* this interface is highly subject to change
2305 *
2306 * Returns -1 in case of error, 0 if the declaration is inproper and
2307 * 1 in case of success.
2308 */
2309static xmlSchemaTypePtr
2310xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002311 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002312{
2313 xmlSchemaTypePtr type, subtype, last = NULL;
2314 xmlNodePtr child = NULL;
2315 xmlChar name[30];
2316
2317 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2318 return (NULL);
2319
2320
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002321 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002322 type = xmlSchemaAddType(ctxt, schema, name);
2323 if (type == NULL)
2324 return (NULL);
2325 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002326 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 type->id = xmlGetProp(node, BAD_CAST "id");
2328 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2329 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2330
2331 child = node->children;
2332 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002333 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2334 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002335 }
2336 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002337 subtype = (xmlSchemaTypePtr)
2338 xmlSchemaParseElement(ctxt, schema, child, 0);
2339 if (subtype != NULL) {
2340 if (last == NULL) {
2341 type->subtypes = subtype;
2342 last = subtype;
2343 } else {
2344 last->next = subtype;
2345 last = subtype;
2346 }
2347 last->next = NULL;
2348 }
2349 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002350 }
2351 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002352 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2353 "All %s has unexpected content\n", type->name,
2354 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002355 }
2356
2357 return (type);
2358}
2359
2360/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002361 * xmlSchemaImportSchema
2362 *
2363 * @ctxt: a schema validation context
2364 * @schemaLocation: an URI defining where to find the imported schema
2365 *
2366 * import a XML schema
2367 * *WARNING* this interface is highly subject to change
2368 *
2369 * Returns -1 in case of error and 1 in case of success.
2370 */
2371static xmlSchemaImportPtr
2372xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2373 const xmlChar *schemaLocation)
2374{
2375 xmlSchemaImportPtr import;
2376 xmlSchemaParserCtxtPtr newctxt;
2377
2378 newctxt = xmlSchemaNewParserCtxt((const char *) schemaLocation);
2379 if (newctxt == NULL) {
2380 xmlSchemaPErrMemory(NULL, "allocating parser context",
2381 NULL);
2382 return (NULL);
2383 }
2384 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2385 ctxt->userData);
2386
2387 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2388 if (import == NULL) {
2389 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2390 NULL);
2391 xmlSchemaFreeParserCtxt(newctxt);
2392 return (NULL);
2393 }
2394
2395 memset(import, 0, sizeof(xmlSchemaImport));
2396 import->schemaLocation = xmlStrdup(schemaLocation);
2397 import->schema = xmlSchemaParse(newctxt);
2398
2399 if (import->schema == NULL) {
2400 /* FIXME use another error enum here ? */
2401 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2402 "failed to import schema at location %s\n",
2403 schemaLocation, NULL);
2404
2405 xmlSchemaFreeParserCtxt(newctxt);
2406 if (import->schemaLocation != NULL)
2407 xmlFree((xmlChar *)import->schemaLocation);
2408 xmlFree(import);
2409 return NULL;
2410 }
2411
2412 xmlSchemaFreeParserCtxt(newctxt);
2413 return import;
2414}
2415
2416
2417/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002418 * xmlSchemaParseImport:
2419 * @ctxt: a schema validation context
2420 * @schema: the schema being built
2421 * @node: a subtree containing XML Schema informations
2422 *
2423 * parse a XML schema Import definition
2424 * *WARNING* this interface is highly subject to change
2425 *
2426 * Returns -1 in case of error, 0 if the declaration is inproper and
2427 * 1 in case of success.
2428 */
2429static int
2430xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002431 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002432{
2433 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002434 xmlSchemaImportPtr import = NULL;
Daniel Veillard5a872412002-05-22 06:40:27 +00002435 xmlChar *namespace;
2436 xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002437 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002438 xmlURIPtr check;
2439
Daniel Veillard1d913862003-11-21 00:28:39 +00002440
Daniel Veillard5a872412002-05-22 06:40:27 +00002441 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2442 return (-1);
2443
2444 namespace = xmlGetProp(node, BAD_CAST "namespace");
2445 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002446 check = xmlParseURI((const char *) namespace);
2447 if (check == NULL) {
2448 xmlSchemaPErr2(ctxt, node, child,
2449 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2450 "Import namespace attribute is not an URI: %s\n",
2451 namespace, NULL);
2452 xmlFree(namespace);
2453 return (-1);
2454 } else {
2455 xmlFreeURI(check);
2456 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002457 }
2458 schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2459 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002460 xmlChar *base = NULL;
2461 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002462 check = xmlParseURI((const char *) schemaLocation);
2463 if (check == NULL) {
2464 xmlSchemaPErr2(ctxt, node, child,
2465 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2466 "Import schemaLocation attribute is not an URI: %s\n",
2467 schemaLocation, NULL);
2468 if (namespace != NULL)
2469 xmlFree(namespace);
2470 xmlFree(schemaLocation);
2471 return (-1);
2472 } else {
2473 xmlFreeURI(check);
2474 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002475 base = xmlNodeGetBase(node->doc, node);
2476 if (base == NULL) {
2477 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2478 } else {
2479 URI = xmlBuildURI(schemaLocation, base);
2480 }
2481 if (base != NULL) xmlFree(base);
2482 if (URI != NULL) {
2483 xmlFree(schemaLocation);
2484 schemaLocation = URI;
2485 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002486 }
2487 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002488 schema->schemasImports = xmlHashCreate(10);
2489 if (schema->schemasImports == NULL) {
2490 xmlSchemaPErr2(ctxt, node, child,
2491 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2492 "Internal: failed to build import table\n",
2493 NULL, NULL);
2494 if (namespace != NULL)
2495 xmlFree(namespace);
2496 if (schemaLocation != NULL)
2497 xmlFree(schemaLocation);
2498 return (-1);
2499 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002500 }
2501 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002502 import = xmlHashLookup(schema->schemasImports,
2503 XML_SCHEMAS_DEFAULT_NAMESPACE);
2504 if (import != NULL)
2505 previous = import->schemaLocation;
2506 else
2507 previous = NULL;
2508
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002509 if (schemaLocation != NULL) {
2510 if (previous != NULL) {
2511 if (!xmlStrEqual(schemaLocation, previous)) {
2512 xmlSchemaPErr2(ctxt, node, child,
2513 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2514 "Redefining import for default namespace with a different URI: %s\n",
2515 schemaLocation, NULL);
2516 }
2517 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002518 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2519 if (import == NULL) {
2520 if (schemaLocation != NULL)
2521 xmlFree(schemaLocation);
2522 if (namespace != NULL)
2523 xmlFree(namespace);
2524 return (-1);
2525 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002526 xmlHashAddEntry(schema->schemasImports,
2527 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002528 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002529 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002530 xmlFree(schemaLocation);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002531 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002532 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002533 import = xmlHashLookup(schema->schemasImports, namespace);
2534 if (import != NULL)
2535 previous = import->schemaLocation;
2536 else
2537 previous = NULL;
2538
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002539 if (schemaLocation != NULL) {
2540 if (previous != NULL) {
2541 if (!xmlStrEqual(schemaLocation, previous)) {
2542 xmlSchemaPErr2(ctxt, node, child,
2543 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2544 "Redefining import for namespace %s with a different URI: %s\n",
2545 namespace, schemaLocation);
2546 }
2547 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002548 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2549 if (import == NULL) {
2550 if (schemaLocation != NULL)
2551 xmlFree(schemaLocation);
2552 if (namespace != NULL)
2553 xmlFree(namespace);
2554 return (-1);
2555 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002556 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002557 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002558 }
2559 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002560 xmlFree(namespace);
Daniel Veillard5a872412002-05-22 06:40:27 +00002561 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002562 if (schemaLocation != NULL)
2563 xmlFree(schemaLocation);
Daniel Veillard5a872412002-05-22 06:40:27 +00002564
2565 child = node->children;
2566 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002567 /*
2568 * the annotations here are simply discarded ...
2569 */
2570 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002571 }
2572 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002573 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2574 "Import has unexpected content\n", NULL, NULL);
2575 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002576 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002577 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002578}
2579
2580/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002581 * xmlSchemaParseChoice:
2582 * @ctxt: a schema validation context
2583 * @schema: the schema being built
2584 * @node: a subtree containing XML Schema informations
2585 *
2586 * parse a XML schema Choice definition
2587 * *WARNING* this interface is highly subject to change
2588 *
2589 * Returns -1 in case of error, 0 if the declaration is inproper and
2590 * 1 in case of success.
2591 */
2592static xmlSchemaTypePtr
2593xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002594 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002595{
2596 xmlSchemaTypePtr type, subtype, last = NULL;
2597 xmlNodePtr child = NULL;
2598 xmlChar name[30];
2599
2600 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2601 return (NULL);
2602
2603
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002604 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002605 type = xmlSchemaAddType(ctxt, schema, name);
2606 if (type == NULL)
2607 return (NULL);
2608 type->node = node;
2609 type->type = XML_SCHEMA_TYPE_CHOICE;
2610 type->id = xmlGetProp(node, BAD_CAST "id");
2611 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2612 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2613
2614 child = node->children;
2615 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002616 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2617 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002618 }
2619 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002620 (IS_SCHEMA(child, "group")) ||
2621 (IS_SCHEMA(child, "any")) ||
2622 (IS_SCHEMA(child, "choice")) ||
2623 (IS_SCHEMA(child, "sequence"))) {
2624 subtype = NULL;
2625 if (IS_SCHEMA(child, "element")) {
2626 subtype = (xmlSchemaTypePtr)
2627 xmlSchemaParseElement(ctxt, schema, child, 0);
2628 } else if (IS_SCHEMA(child, "group")) {
2629 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2630 } else if (IS_SCHEMA(child, "any")) {
2631 subtype = xmlSchemaParseAny(ctxt, schema, child);
2632 } else if (IS_SCHEMA(child, "sequence")) {
2633 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2634 } else if (IS_SCHEMA(child, "choice")) {
2635 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2636 }
2637 if (subtype != NULL) {
2638 if (last == NULL) {
2639 type->subtypes = subtype;
2640 last = subtype;
2641 } else {
2642 last->next = subtype;
2643 last = subtype;
2644 }
2645 last->next = NULL;
2646 }
2647 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002648 }
2649 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002650 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
2651 "Choice %s has unexpected content\n", type->name,
2652 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002653 }
2654
2655 return (type);
2656}
2657
2658/**
2659 * xmlSchemaParseSequence:
2660 * @ctxt: a schema validation context
2661 * @schema: the schema being built
2662 * @node: a subtree containing XML Schema informations
2663 *
2664 * parse a XML schema Sequence definition
2665 * *WARNING* this interface is highly subject to change
2666 *
2667 * Returns -1 in case of error, 0 if the declaration is inproper and
2668 * 1 in case of success.
2669 */
2670static xmlSchemaTypePtr
2671xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002672 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002673{
2674 xmlSchemaTypePtr type, subtype, last = NULL;
2675 xmlNodePtr child = NULL;
2676 xmlChar name[30];
2677
2678 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2679 return (NULL);
2680
2681
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002682 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 type = xmlSchemaAddType(ctxt, schema, name);
2684 if (type == NULL)
2685 return (NULL);
2686 type->node = node;
2687 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2688 type->id = xmlGetProp(node, BAD_CAST "id");
2689 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2690 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2691
2692 child = node->children;
2693 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002694 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2695 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002696 }
2697 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002698 (IS_SCHEMA(child, "group")) ||
2699 (IS_SCHEMA(child, "any")) ||
2700 (IS_SCHEMA(child, "choice")) ||
2701 (IS_SCHEMA(child, "sequence"))) {
2702 subtype = NULL;
2703 if (IS_SCHEMA(child, "element")) {
2704 subtype = (xmlSchemaTypePtr)
2705 xmlSchemaParseElement(ctxt, schema, child, 0);
2706 } else if (IS_SCHEMA(child, "group")) {
2707 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2708 } else if (IS_SCHEMA(child, "any")) {
2709 subtype = xmlSchemaParseAny(ctxt, schema, child);
2710 } else if (IS_SCHEMA(child, "choice")) {
2711 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2712 } else if (IS_SCHEMA(child, "sequence")) {
2713 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2714 }
2715 if (subtype != NULL) {
2716 if (last == NULL) {
2717 type->subtypes = subtype;
2718 last = subtype;
2719 } else {
2720 last->next = subtype;
2721 last = subtype;
2722 }
2723 last->next = NULL;
2724 }
2725 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002726 }
2727 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002728 xmlSchemaPErr2(ctxt, node, child,
2729 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2730 "Sequence %s has unexpected content\n", type->name,
2731 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 }
2733
2734 return (type);
2735}
2736
2737/**
2738 * xmlSchemaParseRestriction:
2739 * @ctxt: a schema validation context
2740 * @schema: the schema being built
2741 * @node: a subtree containing XML Schema informations
2742 * @simple: is that part of a simple type.
2743 *
2744 * parse a XML schema Restriction definition
2745 * *WARNING* this interface is highly subject to change
2746 *
2747 * Returns the type definition or NULL in case of error
2748 */
2749static xmlSchemaTypePtr
2750xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2751 xmlNodePtr node, int simple)
2752{
2753 xmlSchemaTypePtr type, subtype;
2754 xmlSchemaFacetPtr facet, lastfacet = NULL;
2755 xmlNodePtr child = NULL;
2756 xmlChar name[30];
2757 xmlChar *oldcontainer;
2758
2759 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2760 return (NULL);
2761
2762 oldcontainer = ctxt->container;
2763
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002765 type = xmlSchemaAddType(ctxt, schema, name);
2766 if (type == NULL)
2767 return (NULL);
2768 type->node = node;
2769 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2770 type->id = xmlGetProp(node, BAD_CAST "id");
2771 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2772 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002773 xmlSchemaPErr2(ctxt, node, child,
2774 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
2775 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002776 }
2777 ctxt->container = name;
2778
2779 child = node->children;
2780 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002781 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2782 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002783 }
2784 subtype = NULL;
2785
2786 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002787 subtype = (xmlSchemaTypePtr)
2788 xmlSchemaParseAll(ctxt, schema, child);
2789 child = child->next;
2790 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002791 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002792 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2793 child = child->next;
2794 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002795 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002796 subtype = (xmlSchemaTypePtr)
2797 xmlSchemaParseSequence(ctxt, schema, child);
2798 child = child->next;
2799 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002800 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002801 subtype = (xmlSchemaTypePtr)
2802 xmlSchemaParseGroup(ctxt, schema, child);
2803 child = child->next;
2804 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002805 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002806 if (IS_SCHEMA(child, "simpleType")) {
2807 subtype = (xmlSchemaTypePtr)
2808 xmlSchemaParseSimpleType(ctxt, schema, child);
2809 child = child->next;
2810 type->baseType = subtype;
2811 }
2812 /*
2813 * Facets
2814 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002815 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002816 (IS_SCHEMA(child, "minExclusive")) ||
2817 (IS_SCHEMA(child, "maxInclusive")) ||
2818 (IS_SCHEMA(child, "maxExclusive")) ||
2819 (IS_SCHEMA(child, "totalDigits")) ||
2820 (IS_SCHEMA(child, "fractionDigits")) ||
2821 (IS_SCHEMA(child, "pattern")) ||
2822 (IS_SCHEMA(child, "enumeration")) ||
2823 (IS_SCHEMA(child, "whiteSpace")) ||
2824 (IS_SCHEMA(child, "length")) ||
2825 (IS_SCHEMA(child, "maxLength")) ||
2826 (IS_SCHEMA(child, "minLength"))) {
2827 facet = xmlSchemaParseFacet(ctxt, schema, child);
2828 if (facet != NULL) {
2829 if (lastfacet == NULL) {
2830 type->facets = facet;
2831 lastfacet = facet;
2832 } else {
2833 lastfacet->next = facet;
2834 lastfacet = facet;
2835 }
2836 lastfacet->next = NULL;
2837 }
2838 child = child->next;
2839 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002840 }
2841 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2842 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002843 xmlSchemaPErr2(ctxt, node, child,
2844 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
2845 "Restriction %s has unexpected content\n",
2846 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002847 }
2848 ctxt->container = oldcontainer;
2849 return (type);
2850}
2851
2852/**
2853 * xmlSchemaParseExtension:
2854 * @ctxt: a schema validation context
2855 * @schema: the schema being built
2856 * @node: a subtree containing XML Schema informations
2857 *
2858 * parse a XML schema Extension definition
2859 * *WARNING* this interface is highly subject to change
2860 *
2861 * Returns the type definition or NULL in case of error
2862 */
2863static xmlSchemaTypePtr
2864xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002865 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002866{
2867 xmlSchemaTypePtr type, subtype;
2868 xmlNodePtr child = NULL;
2869 xmlChar name[30];
2870 xmlChar *oldcontainer;
2871
2872 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2873 return (NULL);
2874
2875 oldcontainer = ctxt->container;
2876
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002878 type = xmlSchemaAddType(ctxt, schema, name);
2879 if (type == NULL)
2880 return (NULL);
2881 type->node = node;
2882 type->type = XML_SCHEMA_TYPE_EXTENSION;
2883 type->id = xmlGetProp(node, BAD_CAST "id");
2884 ctxt->container = name;
2885
2886 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2887 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002888 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
2889 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002890 }
2891 child = node->children;
2892 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002893 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2894 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002895 }
2896 subtype = NULL;
2897
2898 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002899 subtype = xmlSchemaParseAll(ctxt, schema, child);
2900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002901 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002902 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2903 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002904 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002905 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2906 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002907 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002908 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2909 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002910 }
2911 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002912 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002913 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2914 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002915 xmlSchemaPErr2(ctxt, node, child,
2916 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
2917 "Extension %s has unexpected content\n", type->name,
2918 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 }
2920 ctxt->container = oldcontainer;
2921 return (type);
2922}
2923
2924/**
2925 * xmlSchemaParseSimpleContent:
2926 * @ctxt: a schema validation context
2927 * @schema: the schema being built
2928 * @node: a subtree containing XML Schema informations
2929 *
2930 * parse a XML schema SimpleContent definition
2931 * *WARNING* this interface is highly subject to change
2932 *
2933 * Returns the type definition or NULL in case of error
2934 */
2935static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002936xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
2937 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002938{
2939 xmlSchemaTypePtr type, subtype;
2940 xmlNodePtr child = NULL;
2941 xmlChar name[30];
2942
2943 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2944 return (NULL);
2945
2946
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002947 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002948 type = xmlSchemaAddType(ctxt, schema, name);
2949 if (type == NULL)
2950 return (NULL);
2951 type->node = node;
2952 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2953 type->id = xmlGetProp(node, BAD_CAST "id");
2954
2955 child = node->children;
2956 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002957 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2958 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002959 }
2960 subtype = NULL;
2961 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002962 subtype = (xmlSchemaTypePtr)
2963 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2964 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002965 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002966 subtype = (xmlSchemaTypePtr)
2967 xmlSchemaParseExtension(ctxt, schema, child);
2968 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002969 }
2970 type->subtypes = subtype;
2971 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002972 xmlSchemaPErr2(ctxt, node, child,
2973 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
2974 "SimpleContent %s has unexpected content\n",
2975 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002976 }
2977 return (type);
2978}
2979
2980/**
2981 * xmlSchemaParseComplexContent:
2982 * @ctxt: a schema validation context
2983 * @schema: the schema being built
2984 * @node: a subtree containing XML Schema informations
2985 *
2986 * parse a XML schema ComplexContent definition
2987 * *WARNING* this interface is highly subject to change
2988 *
2989 * Returns the type definition or NULL in case of error
2990 */
2991static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002992xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
2993 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002994{
2995 xmlSchemaTypePtr type, subtype;
2996 xmlNodePtr child = NULL;
2997 xmlChar name[30];
2998
2999 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3000 return (NULL);
3001
3002
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003003 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003004 type = xmlSchemaAddType(ctxt, schema, name);
3005 if (type == NULL)
3006 return (NULL);
3007 type->node = node;
3008 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
3009 type->id = xmlGetProp(node, BAD_CAST "id");
3010
3011 child = node->children;
3012 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003013 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3014 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003015 }
3016 subtype = NULL;
3017 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 subtype = (xmlSchemaTypePtr)
3019 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3020 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003021 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003022 subtype = (xmlSchemaTypePtr)
3023 xmlSchemaParseExtension(ctxt, schema, child);
3024 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003025 }
3026 type->subtypes = subtype;
3027 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003028 xmlSchemaPErr2(ctxt, node, child,
3029 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3030 "ComplexContent %s has unexpected content\n",
3031 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003032 }
3033 return (type);
3034}
3035
3036/**
3037 * xmlSchemaParseComplexType:
3038 * @ctxt: a schema validation context
3039 * @schema: the schema being built
3040 * @node: a subtree containing XML Schema informations
3041 *
3042 * parse a XML schema Complex Type definition
3043 * *WARNING* this interface is highly subject to change
3044 *
3045 * Returns the type definition or NULL in case of error
3046 */
3047static xmlSchemaTypePtr
3048xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3049 xmlNodePtr node)
3050{
3051 xmlSchemaTypePtr type, subtype;
3052 xmlNodePtr child = NULL;
3053 xmlChar *name;
3054 xmlChar *oldcontainer;
3055
3056 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3057 return (NULL);
3058
3059 oldcontainer = ctxt->container;
3060 name = xmlGetProp(node, (const xmlChar *) "name");
3061 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003063
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003064 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
3065 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00003066 }
3067 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 xmlSchemaPErr2(ctxt, node, child,
3069 XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF,
3070 "complexType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003071 return (NULL);
3072 }
3073 type = xmlSchemaAddType(ctxt, schema, name);
3074 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003075 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003076 return (NULL);
3077 }
3078 type->node = node;
3079 type->type = XML_SCHEMA_TYPE_COMPLEX;
3080 type->id = xmlGetProp(node, BAD_CAST "id");
3081 ctxt->container = name;
3082
3083 child = node->children;
3084 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003085 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3086 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003087 }
3088 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003089 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3090 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003091 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003092 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003094 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003095 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003096
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003097 if (IS_SCHEMA(child, "all")) {
3098 subtype = xmlSchemaParseAll(ctxt, schema, child);
3099 child = child->next;
3100 } else if (IS_SCHEMA(child, "choice")) {
3101 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3102 child = child->next;
3103 } else if (IS_SCHEMA(child, "sequence")) {
3104 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3105 child = child->next;
3106 } else if (IS_SCHEMA(child, "group")) {
3107 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3108 child = child->next;
3109 }
3110 if (subtype != NULL)
3111 type->subtypes = subtype;
3112 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003113 }
3114 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003115 xmlSchemaPErr2(ctxt, node, child,
3116 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3117 "ComplexType %s has unexpected content\n",
3118 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003119 }
3120 ctxt->container = oldcontainer;
3121 xmlFree(name);
3122 return (type);
3123}
3124
3125
3126/**
3127 * xmlSchemaParseSchema:
3128 * @ctxt: a schema validation context
3129 * @node: a subtree containing XML Schema informations
3130 *
3131 * parse a XML schema definition from a node set
3132 * *WARNING* this interface is highly subject to change
3133 *
3134 * Returns the internal XML Schema structure built from the resource or
3135 * NULL in case of error
3136 */
3137static xmlSchemaPtr
3138xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3139{
3140 xmlSchemaPtr schema = NULL;
3141 xmlSchemaAnnotPtr annot;
3142 xmlNodePtr child = NULL;
3143 xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003144 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003145
3146 if ((ctxt == NULL) || (node == NULL))
3147 return (NULL);
3148
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003149 nberrors = ctxt->nberrors;
3150 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003151 if (IS_SCHEMA(node, "schema")) {
3152 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003153 if (schema == NULL)
3154 return (NULL);
3155 schema->targetNamespace =
3156 xmlGetProp(node, BAD_CAST "targetNamespace");
3157 schema->id = xmlGetProp(node, BAD_CAST "id");
3158 schema->version = xmlGetProp(node, BAD_CAST "version");
3159 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
3160 if (val != NULL) {
3161 if (xmlStrEqual(val, BAD_CAST "qualified"))
3162 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3163 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3164 xmlSchemaPErr2(ctxt, node, child,
3165 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3166 "Invalid value %s for elementFormDefault\n",
3167 val, NULL);
3168 }
3169 xmlFree(val);
3170 }
3171 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
3172 if (val != NULL) {
3173 if (xmlStrEqual(val, BAD_CAST "qualified"))
3174 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3175 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3176 xmlSchemaPErr2(ctxt, node, child,
3177 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3178 "Invalid value %s for attributeFormDefault\n",
3179 val, NULL);
3180 }
3181 xmlFree(val);
3182 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003183
3184 child = node->children;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003185 while ((IS_SCHEMA(child, "include")) ||
3186 (IS_SCHEMA(child, "import")) ||
3187 (IS_SCHEMA(child, "redefine")) ||
3188 (IS_SCHEMA(child, "annotation"))) {
3189 if (IS_SCHEMA(child, "annotation")) {
3190 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3191 if (schema->annot == NULL)
3192 schema->annot = annot;
3193 else
3194 xmlSchemaFreeAnnot(annot);
3195 } else if (IS_SCHEMA(child, "include")) {
3196 TODO} else if (IS_SCHEMA(child, "import")) {
3197 xmlSchemaParseImport(ctxt, schema, child);
3198 } else if (IS_SCHEMA(child, "redefine")) {
3199 TODO}
3200 child = child->next;
3201 }
3202 while (child != NULL) {
3203 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003205 child = child->next;
3206 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003207 xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003208 child = child->next;
3209 } else if (IS_SCHEMA(child, "element")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 xmlSchemaParseElement(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 child = child->next;
3212 } else if (IS_SCHEMA(child, "attribute")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 xmlSchemaParseAttribute(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003214 child = child->next;
3215 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003216 xmlSchemaParseAttributeGroup(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003217 child = child->next;
3218 } else if (IS_SCHEMA(child, "group")) {
3219 xmlSchemaParseGroup(ctxt, schema, child);
3220 child = child->next;
3221 } else if (IS_SCHEMA(child, "notation")) {
3222 xmlSchemaParseNotation(ctxt, schema, child);
3223 child = child->next;
3224 } else {
3225 xmlSchemaPErr2(ctxt, node, child,
3226 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3227 "Schemas: unexpected element %s here \n",
3228 child->name, NULL);
3229 child = child->next;
3230 }
3231 while (IS_SCHEMA(child, "annotation")) {
3232 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3233 if (schema->annot == NULL)
3234 schema->annot = annot;
3235 else
3236 xmlSchemaFreeAnnot(annot);
3237 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 }
3239 }
3240 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003241 if (ctxt->nberrors != 0) {
3242 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003243 xmlSchemaFree(schema);
3244 schema = NULL;
3245 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003246 }
3247 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003248#ifdef DEBUG
3249 if (schema == NULL)
3250 xmlGenericError(xmlGenericErrorContext,
3251 "xmlSchemaParse() failed\n");
3252#endif
3253
3254 return (schema);
3255}
3256
3257/************************************************************************
3258 * *
3259 * Validating using Schemas *
3260 * *
3261 ************************************************************************/
3262
3263/************************************************************************
3264 * *
3265 * Reading/Writing Schemas *
3266 * *
3267 ************************************************************************/
3268
3269/**
3270 * xmlSchemaNewParserCtxt:
3271 * @URL: the location of the schema
3272 *
3273 * Create an XML Schemas parse context for that file/resource expected
3274 * to contain an XML Schemas file.
3275 *
3276 * Returns the parser context or NULL in case of error
3277 */
3278xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003279xmlSchemaNewParserCtxt(const char *URL)
3280{
Daniel Veillard4255d502002-04-16 15:50:10 +00003281 xmlSchemaParserCtxtPtr ret;
3282
3283 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003284 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003285
3286 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3287 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003288 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3289 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003290 return (NULL);
3291 }
3292 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003293 ret->URL = xmlStrdup((const xmlChar *) URL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003294 return (ret);
3295}
3296
3297/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003298 * xmlSchemaNewMemParserCtxt:
3299 * @buffer: a pointer to a char array containing the schemas
3300 * @size: the size of the array
3301 *
3302 * Create an XML Schemas parse context for that memory buffer expected
3303 * to contain an XML Schemas file.
3304 *
3305 * Returns the parser context or NULL in case of error
3306 */
3307xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003308xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3309{
Daniel Veillard6045c902002-10-09 21:13:59 +00003310 xmlSchemaParserCtxtPtr ret;
3311
3312 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003313 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003314
3315 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3316 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003317 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3318 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003319 return (NULL);
3320 }
3321 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3322 ret->buffer = buffer;
3323 ret->size = size;
3324 return (ret);
3325}
3326
3327/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003328 * xmlSchemaNewDocParserCtxt:
3329 * @doc: a preparsed document tree
3330 *
3331 * Create an XML Schemas parse context for that document.
3332 * NB. The document may be modified during the parsing process.
3333 *
3334 * Returns the parser context or NULL in case of error
3335 */
3336xmlSchemaParserCtxtPtr
3337xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3338{
3339 xmlSchemaParserCtxtPtr ret;
3340
3341 if (doc == NULL)
3342 return (NULL);
3343
3344 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3345 if (ret == NULL) {
3346 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3347 NULL);
3348 return (NULL);
3349 }
3350 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3351 ret->doc = doc;
3352
3353 return (ret);
3354}
3355
3356/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003357 * xmlSchemaFreeParserCtxt:
3358 * @ctxt: the schema parser context
3359 *
3360 * Free the resources associated to the schema parser context
3361 */
3362void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003363xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3364{
Daniel Veillard4255d502002-04-16 15:50:10 +00003365 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003366 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003367 if (ctxt->URL != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003368 xmlFree(ctxt->URL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003369 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003370 xmlFreeDoc(ctxt->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00003371 xmlFree(ctxt);
3372}
3373
3374/************************************************************************
3375 * *
3376 * Building the content models *
3377 * *
3378 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003379
Daniel Veillard4255d502002-04-16 15:50:10 +00003380/**
3381 * xmlSchemaBuildAContentModel:
3382 * @type: the schema type definition
3383 * @ctxt: the schema parser context
3384 * @name: the element name whose content is being built
3385 *
3386 * Generate the automata sequence needed for that type
3387 */
3388static void
3389xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390 xmlSchemaParserCtxtPtr ctxt,
3391 const xmlChar * name)
3392{
Daniel Veillard4255d502002-04-16 15:50:10 +00003393 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003394 xmlGenericError(xmlGenericErrorContext,
3395 "Found unexpected type = NULL in %s content model\n",
3396 name);
3397 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 }
3399 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003400 case XML_SCHEMA_TYPE_ANY:
3401 /* TODO : handle the namespace too */
3402 /* TODO : make that a specific transition type */
3403 TODO ctxt->state =
3404 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3405 BAD_CAST "*", NULL);
3406 break;
3407 case XML_SCHEMA_TYPE_ELEMENT:{
3408 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003409
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003410 /* TODO : handle the namespace too */
3411 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003412
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413 if (elem->maxOccurs >= UNBOUNDED) {
3414 if (elem->minOccurs > 1) {
3415 xmlAutomataStatePtr tmp;
3416 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003417
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003418 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3419 oldstate,
3420 NULL);
3421 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003422
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 counter = xmlAutomataNewCounter(ctxt->am,
3424 elem->minOccurs -
3425 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003426
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003427 if (elem->refDecl != NULL) {
3428 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3429 elem->refDecl,
3430 ctxt,
3431 elem->refDecl->
3432 name);
3433 } else {
3434 ctxt->state =
3435 xmlAutomataNewTransition(ctxt->am,
3436 ctxt->state, NULL,
3437 elem->name, type);
3438 }
3439 tmp = ctxt->state;
3440 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3441 counter);
3442 ctxt->state =
3443 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3444 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003445
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003446 } else {
3447 if (elem->refDecl != NULL) {
3448 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3449 elem->refDecl,
3450 ctxt,
3451 elem->refDecl->
3452 name);
3453 } else {
3454 ctxt->state =
3455 xmlAutomataNewTransition(ctxt->am,
3456 ctxt->state, NULL,
3457 elem->name, type);
3458 }
3459 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3460 oldstate);
3461 if (elem->minOccurs == 0) {
3462 /* basically an elem* */
3463 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3464 ctxt->state);
3465 }
3466 }
3467 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3468 xmlAutomataStatePtr tmp;
3469 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003470
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003471 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3472 oldstate, NULL);
3473 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003474
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003475 counter = xmlAutomataNewCounter(ctxt->am,
3476 elem->minOccurs - 1,
3477 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003478
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003479 if (elem->refDecl != NULL) {
3480 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3481 elem->refDecl, ctxt,
3482 elem->refDecl->name);
3483 } else {
3484 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3485 ctxt->state,
3486 NULL,
3487 elem->name,
3488 type);
3489 }
3490 tmp = ctxt->state;
3491 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3492 counter);
3493 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3494 NULL,
3495 counter);
3496 if (elem->minOccurs == 0) {
3497 /* basically an elem? */
3498 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3499 ctxt->state);
3500 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003501
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003502 } else {
3503 if (elem->refDecl != NULL) {
3504 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3505 elem->refDecl, ctxt,
3506 elem->refDecl->name);
3507 } else {
3508 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3509 ctxt->state,
3510 NULL,
3511 elem->name,
3512 type);
3513 }
3514 if (elem->minOccurs == 0) {
3515 /* basically an elem? */
3516 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3517 ctxt->state);
3518 }
3519 }
3520 break;
3521 }
3522 case XML_SCHEMA_TYPE_SEQUENCE:{
3523 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003524
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003525 /*
3526 * If max and min occurances are default (1) then
3527 * simply iterate over the subtypes
3528 */
3529 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
3530 subtypes = type->subtypes;
3531 while (subtypes != NULL) {
3532 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3533 subtypes = subtypes->next;
3534 }
3535 } else {
3536 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003537
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003538 if (type->maxOccurs >= UNBOUNDED) {
3539 if (type->minOccurs > 1) {
3540 xmlAutomataStatePtr tmp;
3541 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003542
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003543 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3544 oldstate,
3545 NULL);
3546 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003547
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003548 counter = xmlAutomataNewCounter(ctxt->am,
3549 type->
3550 minOccurs - 1,
3551 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003552
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003553 subtypes = type->subtypes;
3554 while (subtypes != NULL) {
3555 xmlSchemaBuildAContentModel(subtypes, ctxt,
3556 name);
3557 subtypes = subtypes->next;
3558 }
3559 tmp = ctxt->state;
3560 xmlAutomataNewCountedTrans(ctxt->am, tmp,
3561 oldstate, counter);
3562 ctxt->state =
3563 xmlAutomataNewCounterTrans(ctxt->am, tmp,
3564 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003565
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003566 } else {
3567 subtypes = type->subtypes;
3568 while (subtypes != NULL) {
3569 xmlSchemaBuildAContentModel(subtypes, ctxt,
3570 name);
3571 subtypes = subtypes->next;
3572 }
3573 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3574 oldstate);
3575 if (type->minOccurs == 0) {
3576 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3577 ctxt->state);
3578 }
3579 }
3580 } else if ((type->maxOccurs > 1)
3581 || (type->minOccurs > 1)) {
3582 xmlAutomataStatePtr tmp;
3583 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003584
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003585 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3586 oldstate,
3587 NULL);
3588 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00003589
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003590 counter = xmlAutomataNewCounter(ctxt->am,
3591 type->minOccurs -
3592 1,
3593 type->maxOccurs -
3594 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003595
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003596 subtypes = type->subtypes;
3597 while (subtypes != NULL) {
3598 xmlSchemaBuildAContentModel(subtypes, ctxt,
3599 name);
3600 subtypes = subtypes->next;
3601 }
3602 tmp = ctxt->state;
3603 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3604 counter);
3605 ctxt->state =
3606 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3607 counter);
3608 if (type->minOccurs == 0) {
3609 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3610 ctxt->state);
3611 }
Daniel Veillardb509f152002-04-17 16:28:10 +00003612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613 } else {
3614 subtypes = type->subtypes;
3615 while (subtypes != NULL) {
3616 xmlSchemaBuildAContentModel(subtypes, ctxt,
3617 name);
3618 subtypes = subtypes->next;
3619 }
3620 if (type->minOccurs == 0) {
3621 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3622 ctxt->state);
3623 }
3624 }
3625 }
3626 break;
3627 }
3628 case XML_SCHEMA_TYPE_CHOICE:{
3629 xmlSchemaTypePtr subtypes;
3630 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00003631
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003632 start = ctxt->state;
3633 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00003634
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003635 /*
3636 * iterate over the subtypes and remerge the end with an
3637 * epsilon transition
3638 */
3639 if (type->maxOccurs == 1) {
3640 subtypes = type->subtypes;
3641 while (subtypes != NULL) {
3642 ctxt->state = start;
3643 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3644 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3645 subtypes = subtypes->next;
3646 }
3647 } else {
3648 int counter;
3649 xmlAutomataStatePtr hop;
3650 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3651 UNBOUNDED : type->maxOccurs - 1;
3652 int minOccurs =
3653 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00003654
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003655 /*
3656 * use a counter to keep track of the number of transtions
3657 * which went through the choice.
3658 */
3659 counter =
3660 xmlAutomataNewCounter(ctxt->am, minOccurs,
3661 maxOccurs);
3662 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00003663
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003664 subtypes = type->subtypes;
3665 while (subtypes != NULL) {
3666 ctxt->state = start;
3667 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3668 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3669 subtypes = subtypes->next;
3670 }
3671 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
3672 counter);
3673 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
3674 counter);
3675 }
3676 if (type->minOccurs == 0) {
3677 xmlAutomataNewEpsilon(ctxt->am, start, end);
3678 }
3679 ctxt->state = end;
3680 break;
3681 }
3682 case XML_SCHEMA_TYPE_ALL:{
3683 xmlAutomataStatePtr start;
3684 xmlSchemaTypePtr subtypes;
3685 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3686 int lax;
3687
3688 subtypes = type->subtypes;
3689 if (subtypes == NULL)
3690 break;
3691 start = ctxt->state;
3692 while (subtypes != NULL) {
3693 ctxt->state = start;
3694 elem = (xmlSchemaElementPtr) subtypes;
3695
3696 /* TODO : handle the namespace too */
3697 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3698 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
3699 ctxt->state, elem->name, 1,
3700 1, subtypes);
3701 } else {
3702 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
3703 ctxt->state, elem->name,
3704 elem->minOccurs,
3705 elem->maxOccurs,
3706 subtypes);
3707 }
3708 subtypes = subtypes->next;
3709 }
3710 lax = type->minOccurs == 0;
3711 ctxt->state =
3712 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3713 lax);
3714 break;
3715 }
3716 case XML_SCHEMA_TYPE_RESTRICTION:
3717 if (type->subtypes != NULL)
3718 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3719 break;
3720 case XML_SCHEMA_TYPE_EXTENSION:
3721 if (type->baseType != NULL) {
3722 xmlSchemaTypePtr subtypes;
3723
3724 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3725 subtypes = type->subtypes;
3726 while (subtypes != NULL) {
3727 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3728 subtypes = subtypes->next;
3729 }
3730 } else if (type->subtypes != NULL)
3731 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3732 break;
3733 case XML_SCHEMA_TYPE_GROUP:
3734 if (type->subtypes == NULL) {
3735 }
3736 case XML_SCHEMA_TYPE_COMPLEX:
3737 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3738 if (type->subtypes != NULL)
3739 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3740 break;
3741 default:
3742 xmlGenericError(xmlGenericErrorContext,
3743 "Found unexpected type %d in %s content model\n",
3744 type->type, name);
3745 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003746 }
3747}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003748
Daniel Veillard4255d502002-04-16 15:50:10 +00003749/**
3750 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003751 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00003752 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003753 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00003754 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003755 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00003756 */
3757static void
3758xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003759 xmlSchemaParserCtxtPtr ctxt,
3760 const xmlChar * name)
3761{
Daniel Veillard4255d502002-04-16 15:50:10 +00003762 xmlAutomataStatePtr start;
3763
Daniel Veillard4255d502002-04-16 15:50:10 +00003764 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003765 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003766 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003767 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3768 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003769 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003770 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003771 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003772 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003773 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003774
3775#ifdef DEBUG_CONTENT
3776 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003778#endif
3779
Daniel Veillard4255d502002-04-16 15:50:10 +00003780 ctxt->am = xmlNewAutomata();
3781 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003782 xmlGenericError(xmlGenericErrorContext,
3783 "Cannot create automata for elem %s\n", name);
3784 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003785 }
3786 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3787 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3788 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00003789 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003790 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003791 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
3792 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003793 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003794 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
3795 "Content model of %s is not determinist:\n", name,
3796 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003797 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00003798#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003799 xmlGenericError(xmlGenericErrorContext,
3800 "Content model of %s:\n", name);
3801 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003802#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003803 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003804 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003805 xmlFreeAutomata(ctxt->am);
3806 ctxt->am = NULL;
3807}
3808
3809/**
3810 * xmlSchemaRefFixupCallback:
3811 * @elem: the schema element context
3812 * @ctxt: the schema parser context
3813 *
3814 * Free the resources associated to the schema parser context
3815 */
3816static void
3817xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003818 xmlSchemaParserCtxtPtr ctxt,
3819 const xmlChar * name,
3820 const xmlChar * context ATTRIBUTE_UNUSED,
3821 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003822{
3823 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003824 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003825 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003826 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003828 if (elem->subtypes != NULL) {
3829 xmlSchemaPErr(ctxt, elem->node,
3830 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
3831 "Schemas: element %s have both ref and subtype\n",
3832 name, NULL);
3833 return;
3834 }
3835 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3836 elem->ref, elem->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003837
3838 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003839 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
3840 "Schemas: element %s ref to %s not found\n",
3841 name, elem->ref);
3842 return;
3843 }
3844 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003845 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003846 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003847
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003848 if (elem->subtypes != NULL) {
3849 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
3850 "Schemas: element %s have both type and subtype\n",
3851 name, NULL);
3852 return;
3853 }
3854 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3855 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003856
3857 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003858 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
3859 "Schemas: element %s type %s not found\n", name,
3860 elem->namedType);
3861 return;
3862 }
3863 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003864 }
3865}
3866
3867/**
3868 * xmlSchemaTypeFixup:
3869 * @typeDecl: the schema type definition
3870 * @ctxt: the schema parser context
3871 *
3872 * Fixes the content model of the type.
3873 */
3874static void
3875xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003876 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003877{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00003878 if (typeDecl == NULL)
3879 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003881 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003883 switch (typeDecl->type) {
3884 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
3885 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3886 if (typeDecl->subtypes != NULL)
3887 typeDecl->contentType =
3888 typeDecl->subtypes->contentType;
3889 break;
3890 }
3891 case XML_SCHEMA_TYPE_RESTRICTION:{
3892 if (typeDecl->subtypes != NULL)
3893 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003894
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003895 if (typeDecl->base != NULL) {
3896 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003897
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 baseType =
3899 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3900 typeDecl->baseNs);
3901 if (baseType == NULL) {
3902 xmlSchemaPErr(ctxt, typeDecl->node,
3903 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003904 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003905 name, typeDecl->base);
3906 }
3907 typeDecl->baseType = baseType;
3908 }
3909 if (typeDecl->subtypes == NULL)
3910 /* 1.1.1 */
3911 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3912 else if ((typeDecl->subtypes->subtypes == NULL) &&
3913 ((typeDecl->subtypes->type ==
3914 XML_SCHEMA_TYPE_ALL)
3915 || (typeDecl->subtypes->type ==
3916 XML_SCHEMA_TYPE_SEQUENCE)))
3917 /* 1.1.2 */
3918 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3919 else if ((typeDecl->subtypes->type ==
3920 XML_SCHEMA_TYPE_CHOICE)
3921 && (typeDecl->subtypes->subtypes == NULL))
3922 /* 1.1.3 */
3923 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3924 else {
3925 /* 1.2 and 2.X are applied at the other layer */
3926 typeDecl->contentType =
3927 XML_SCHEMA_CONTENT_ELEMENTS;
3928 }
3929 break;
3930 }
3931 case XML_SCHEMA_TYPE_EXTENSION:{
3932 xmlSchemaContentType explicitContentType;
3933 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00003934
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003935 if (typeDecl->base != NULL) {
3936 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003937
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003938 baseType =
3939 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3940 typeDecl->baseNs);
3941 if (baseType == NULL) {
3942 xmlSchemaPErr(ctxt, typeDecl->node,
3943 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003944 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003945 name, typeDecl->base);
3946 }
3947 typeDecl->baseType = baseType;
3948 }
3949 if (typeDecl->subtypes != NULL)
3950 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003951
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003952 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3953 if (typeDecl->subtypes == NULL)
3954 /* 1.1.1 */
3955 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3956 else if ((typeDecl->subtypes->subtypes == NULL) &&
3957 ((typeDecl->subtypes->type ==
3958 XML_SCHEMA_TYPE_ALL)
3959 || (typeDecl->subtypes->type ==
3960 XML_SCHEMA_TYPE_SEQUENCE)))
3961 /* 1.1.2 */
3962 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3963 else if ((typeDecl->subtypes->type ==
3964 XML_SCHEMA_TYPE_CHOICE)
3965 && (typeDecl->subtypes->subtypes == NULL))
3966 /* 1.1.3 */
3967 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003968
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003969 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3970 typeDecl->baseNs);
3971 if (base == NULL) {
3972 xmlSchemaPErr(ctxt, typeDecl->node,
3973 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
3974 "Schemas: base type %s of type %s not found\n",
3975 typeDecl->base, name);
3976 return;
3977 }
3978 xmlSchemaTypeFixup(base, ctxt, NULL);
3979 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3980 /* 2.1 */
3981 typeDecl->contentType = base->contentType;
3982 } else if (base->contentType ==
3983 XML_SCHEMA_CONTENT_EMPTY) {
3984 /* 2.2 imbitable ! */
3985 typeDecl->contentType =
3986 XML_SCHEMA_CONTENT_ELEMENTS;
3987 } else {
3988 /* 2.3 imbitable pareil ! */
3989 typeDecl->contentType =
3990 XML_SCHEMA_CONTENT_ELEMENTS;
3991 }
3992 break;
3993 }
3994 case XML_SCHEMA_TYPE_COMPLEX:{
3995 if (typeDecl->subtypes == NULL) {
3996 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3997 } else {
3998 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3999 typeDecl->contentType =
4000 XML_SCHEMA_CONTENT_MIXED;
4001 else {
4002 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4003 NULL);
4004 if (typeDecl->subtypes != NULL)
4005 typeDecl->contentType =
4006 typeDecl->subtypes->contentType;
4007 }
4008 }
4009 break;
4010 }
4011 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4012 if (typeDecl->subtypes == NULL) {
4013 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4014 } else {
4015 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4016 typeDecl->contentType =
4017 XML_SCHEMA_CONTENT_MIXED;
4018 else {
4019 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4020 NULL);
4021 if (typeDecl->subtypes != NULL)
4022 typeDecl->contentType =
4023 typeDecl->subtypes->contentType;
4024 }
4025 }
4026 break;
4027 }
4028 case XML_SCHEMA_TYPE_SEQUENCE:
4029 case XML_SCHEMA_TYPE_GROUP:
4030 case XML_SCHEMA_TYPE_ALL:
4031 case XML_SCHEMA_TYPE_CHOICE:
4032 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4033 break;
4034 case XML_SCHEMA_TYPE_BASIC:
4035 case XML_SCHEMA_TYPE_ANY:
4036 case XML_SCHEMA_TYPE_FACET:
4037 case XML_SCHEMA_TYPE_SIMPLE:
4038 case XML_SCHEMA_TYPE_UR:
4039 case XML_SCHEMA_TYPE_ELEMENT:
4040 case XML_SCHEMA_TYPE_ATTRIBUTE:
4041 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4042 case XML_SCHEMA_TYPE_NOTATION:
4043 case XML_SCHEMA_TYPE_LIST:
4044 case XML_SCHEMA_TYPE_UNION:
4045 case XML_SCHEMA_FACET_MININCLUSIVE:
4046 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4047 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4048 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4049 case XML_SCHEMA_FACET_TOTALDIGITS:
4050 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4051 case XML_SCHEMA_FACET_PATTERN:
4052 case XML_SCHEMA_FACET_ENUMERATION:
4053 case XML_SCHEMA_FACET_WHITESPACE:
4054 case XML_SCHEMA_FACET_LENGTH:
4055 case XML_SCHEMA_FACET_MAXLENGTH:
4056 case XML_SCHEMA_FACET_MINLENGTH:
4057 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
4058 break;
4059 }
4060 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004061#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004062 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004063 xmlGenericError(xmlGenericErrorContext,
4064 "Type of %s : %s:%d :", name,
4065 typeDecl->node->doc->URL,
4066 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004067 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004068 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004069 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004070 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004071 case XML_SCHEMA_CONTENT_SIMPLE:
4072 xmlGenericError(xmlGenericErrorContext, "simple\n");
4073 break;
4074 case XML_SCHEMA_CONTENT_ELEMENTS:
4075 xmlGenericError(xmlGenericErrorContext, "elements\n");
4076 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004077 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004078 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4079 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004080 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004081 xmlGenericError(xmlGenericErrorContext, "empty\n");
4082 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004083 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4085 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004086 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004087 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4088 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004089 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004090 xmlGenericError(xmlGenericErrorContext, "basic\n");
4091 break;
4092 default:
4093 xmlGenericError(xmlGenericErrorContext,
4094 "not registered !!!\n");
4095 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004096 }
4097#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004098}
4099
4100/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004101 * xmlSchemaCheckFacet:
4102 * @facet: the facet
4103 * @typeDecl: the schema type definition
4104 * @ctxt: the schema parser context or NULL
4105 * @name: name of the type
4106 *
4107 * Checks the default values types, especially for facets
4108 *
4109 * Returns 0 if okay or -1 in cae of error
4110 */
4111int
4112xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004113 xmlSchemaTypePtr typeDecl,
4114 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004115{
4116 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4117 int ret = 0;
4118
4119 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004120 nonNegativeIntegerType =
4121 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4122 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004123 }
4124 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004125 case XML_SCHEMA_FACET_MININCLUSIVE:
4126 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4127 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4128 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4129 /*
4130 * Okay we need to validate the value
4131 * at that point.
4132 */
4133 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004134
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004135 vctxt = xmlSchemaNewValidCtxt(NULL);
4136 if (vctxt == NULL)
4137 break;
4138 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4139 facet->value);
4140 facet->val = vctxt->value;
4141 vctxt->value = NULL;
4142 if (facet->val == NULL) {
4143 /* error code */
4144 if (ctxt != NULL) {
4145 xmlSchemaPErr(ctxt, facet->node,
4146 XML_SCHEMAP_INVALID_FACET,
4147 "Schemas: type %s facet value %s invalid\n",
4148 name, facet->value);
4149 }
4150 ret = -1;
4151 }
4152 xmlSchemaFreeValidCtxt(vctxt);
4153 break;
4154 }
4155 case XML_SCHEMA_FACET_ENUMERATION:{
4156 /*
4157 * Okay we need to validate the value
4158 * at that point.
4159 */
4160 xmlSchemaValidCtxtPtr vctxt;
4161 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004162
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004163 vctxt = xmlSchemaNewValidCtxt(NULL);
4164 if (vctxt == NULL)
4165 break;
4166 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4167 facet->value);
4168 if (tmp != 0) {
4169 if (ctxt != NULL) {
4170 xmlSchemaPErr(ctxt, facet->node,
4171 XML_SCHEMAP_INVALID_ENUM,
4172 "Schemas: type %s enumeration value %s invalid\n",
4173 name, facet->value);
4174 }
4175 ret = -1;
4176 }
4177 xmlSchemaFreeValidCtxt(vctxt);
4178 break;
4179 }
4180 case XML_SCHEMA_FACET_PATTERN:
4181 facet->regexp = xmlRegexpCompile(facet->value);
4182 if (facet->regexp == NULL) {
4183 xmlSchemaPErr(ctxt, typeDecl->node,
4184 XML_SCHEMAP_REGEXP_INVALID,
4185 "Schemas: type %s facet regexp %s invalid\n",
4186 name, facet->value);
4187 ret = -1;
4188 }
4189 break;
4190 case XML_SCHEMA_FACET_TOTALDIGITS:
4191 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4192 case XML_SCHEMA_FACET_LENGTH:
4193 case XML_SCHEMA_FACET_MAXLENGTH:
4194 case XML_SCHEMA_FACET_MINLENGTH:{
4195 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004196
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004197 tmp =
4198 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4199 facet->value,
4200 &facet->val);
4201 if (tmp != 0) {
4202 /* error code */
4203 if (ctxt != NULL) {
4204 xmlSchemaPErr(ctxt, facet->node,
4205 XML_SCHEMAP_INVALID_FACET_VALUE,
4206 "Schemas: type %s facet value %s invalid\n",
4207 name, facet->value);
4208 }
4209 ret = -1;
4210 }
4211 break;
4212 }
4213 case XML_SCHEMA_FACET_WHITESPACE:{
4214 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4215 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4216 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4217 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4218 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4219 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4220 } else {
4221 if (ctxt != NULL) {
4222 xmlSchemaPErr(ctxt, facet->node,
4223 XML_SCHEMAP_INVALID_WHITE_SPACE,
4224 "Schemas: type %s whiteSpace value %s invalid\n",
4225 name, facet->value);
4226 }
4227 ret = -1;
4228 }
4229 }
4230 default:
4231 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004232 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004233 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004234}
4235
4236/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004237 * xmlSchemaCheckDefaults:
4238 * @typeDecl: the schema type definition
4239 * @ctxt: the schema parser context
4240 *
4241 * Checks the default values types, especially for facets
4242 */
4243static void
4244xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004245 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004246{
Daniel Veillard4255d502002-04-16 15:50:10 +00004247 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004248 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004249 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004250 if (typeDecl->facets != NULL) {
4251 xmlSchemaFacetPtr facet = typeDecl->facets;
4252
4253 while (facet != NULL) {
4254 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4255 facet = facet->next;
4256 }
4257 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004258 }
4259}
4260
4261/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004262 * xmlSchemaAttrGrpFixup:
4263 * @attrgrpDecl: the schema attribute definition
4264 * @ctxt: the schema parser context
4265 * @name: the attribute name
4266 *
4267 * Fixes finish doing the computations on the attributes definitions
4268 */
4269static void
4270xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004271 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004272{
4273 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004274 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004275 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004276 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004277 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004278 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004279
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004280 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4281 attrgrpDecl->refNs);
4282 if (ref == NULL) {
4283 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4284 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4285 "Schemas: attribute group %s reference %s not found\n",
4286 name, attrgrpDecl->ref);
4287 return;
4288 }
4289 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4290 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004291 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004292 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4293 "Schemas: attribute %s has no attributes nor reference\n",
4294 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004295 }
4296}
4297
4298/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 * xmlSchemaAttrFixup:
4300 * @attrDecl: the schema attribute definition
4301 * @ctxt: the schema parser context
4302 * @name: the attribute name
4303 *
4304 * Fixes finish doing the computations on the attributes definitions
4305 */
4306static void
4307xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004308 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004309{
4310 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004311 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004312 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004313 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004314 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004315 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004316
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4318 attrDecl->typeNs);
4319 if (type == NULL) {
4320 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4321 "Schemas: attribute %s type %s not found\n",
4322 name, attrDecl->typeName);
4323 }
4324 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004325 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004326 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004327
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004328 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4329 attrDecl->refNs);
4330 if (ref == NULL) {
4331 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4332 "Schemas: attribute %s reference %s not found\n",
4333 name, attrDecl->ref);
4334 return;
4335 }
4336 xmlSchemaAttrFixup(ref, ctxt, NULL);
4337 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004339 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4340 "Schemas: attribute %s has no type nor reference\n",
4341 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004342 }
4343}
4344
4345/**
4346 * xmlSchemaParse:
4347 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004349 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004350 * XML Shema struture which can be used to validate instances.
4351 * *WARNING* this interface is highly subject to change
4352 *
4353 * Returns the internal XML Schema structure built from the resource or
4354 * NULL in case of error
4355 */
4356xmlSchemaPtr
4357xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4358{
4359 xmlSchemaPtr ret = NULL;
4360 xmlDocPtr doc;
4361 xmlNodePtr root, cur, delete;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004362 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004363
4364 xmlSchemaInitTypes();
4365
Daniel Veillard6045c902002-10-09 21:13:59 +00004366 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 return (NULL);
4368
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004369 nberrors = ctxt->nberrors;
4370 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 ctxt->counter = 0;
4372 ctxt->container = NULL;
4373
4374 /*
4375 * First step is to parse the input document into an DOM/Infoset
4376 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004377 if (ctxt->URL != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004378 doc = xmlParseFile((const char *) ctxt->URL);
4379 if (doc == NULL) {
4380 xmlSchemaPErr(ctxt, NULL,
4381 XML_SCHEMAP_FAILED_LOAD,
4382 "xmlSchemaParse: could not load %s\n",
4383 ctxt->URL, NULL);
4384 return (NULL);
4385 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004386 } else if (ctxt->buffer != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004387 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4388 if (doc == NULL) {
4389 xmlSchemaPErr(ctxt, NULL,
4390 XML_SCHEMAP_FAILED_PARSE,
4391 "xmlSchemaParse: could not parse\n",
4392 NULL, NULL);
4393 return (NULL);
4394 }
4395 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4396 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard9d751502003-10-29 13:21:47 +00004397 } else if (ctxt->doc != NULL) {
4398 doc = ctxt->doc;
Daniel Veillard6045c902002-10-09 21:13:59 +00004399 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004400 xmlSchemaPErr(ctxt, NULL,
4401 XML_SCHEMAP_NOTHING_TO_PARSE,
4402 "xmlSchemaParse: could not parse\n",
4403 NULL, NULL);
4404 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 }
4406
4407 /*
4408 * Then extract the root and Schema parse it
4409 */
4410 root = xmlDocGetRootElement(doc);
4411 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004412 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4413 XML_SCHEMAP_NOROOT,
4414 "schemas has no root", NULL, NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004415 xmlFreeDoc(doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00004416 return (NULL);
4417 }
4418
4419 /*
4420 * Remove all the blank text nodes
4421 */
4422 delete = NULL;
4423 cur = root;
4424 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004425 if (delete != NULL) {
4426 xmlUnlinkNode(delete);
4427 xmlFreeNode(delete);
4428 delete = NULL;
4429 }
4430 if (cur->type == XML_TEXT_NODE) {
4431 if (IS_BLANK_NODE(cur)) {
4432 if (xmlNodeGetSpacePreserve(cur) != 1) {
4433 delete = cur;
4434 }
4435 }
4436 } else if ((cur->type != XML_ELEMENT_NODE) &&
4437 (cur->type != XML_CDATA_SECTION_NODE)) {
4438 delete = cur;
4439 goto skip_children;
4440 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004441
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004442 /*
4443 * Skip to next node
4444 */
4445 if (cur->children != NULL) {
4446 if ((cur->children->type != XML_ENTITY_DECL) &&
4447 (cur->children->type != XML_ENTITY_REF_NODE) &&
4448 (cur->children->type != XML_ENTITY_NODE)) {
4449 cur = cur->children;
4450 continue;
4451 }
4452 }
4453 skip_children:
4454 if (cur->next != NULL) {
4455 cur = cur->next;
4456 continue;
4457 }
4458
4459 do {
4460 cur = cur->parent;
4461 if (cur == NULL)
4462 break;
4463 if (cur == root) {
4464 cur = NULL;
4465 break;
4466 }
4467 if (cur->next != NULL) {
4468 cur = cur->next;
4469 break;
4470 }
4471 } while (cur != NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004472 }
4473 if (delete != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004474 xmlUnlinkNode(delete);
4475 xmlFreeNode(delete);
4476 delete = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004477 }
4478
4479 /*
4480 * Then do the parsing for good
4481 */
4482 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004483 if (ret == NULL) {
4484 xmlFreeDoc(doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004485 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004486 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004487 ret->doc = doc;
4488
4489 /*
4490 * Then fix all the references.
4491 */
4492 ctxt->schema = ret;
4493 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004495
4496 /*
4497 * Then fixup all types properties
4498 */
4499 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4500
4501 /*
4502 * Then build the content model for all elements
4503 */
4504 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004505 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004506
4507 /*
4508 * Then check the defaults part of the type like facets values
4509 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004510 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4511 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004512
4513 /*
4514 * Then fixup all attributes declarations
4515 */
4516 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4517
Daniel Veillard13e04c62002-04-23 17:51:29 +00004518 /*
4519 * Then fixup all attributes group declarations
4520 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004521 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4522 ctxt);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004523
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004524 if (ctxt->nberrors != 0) {
4525 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004526 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004527 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004528 return (ret);
4529}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004530
Daniel Veillard4255d502002-04-16 15:50:10 +00004531/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004532 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004534 * @err: the error callback
4535 * @warn: the warning callback
4536 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004538 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 */
4540void
4541xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004542 xmlSchemaValidityErrorFunc err,
4543 xmlSchemaValidityWarningFunc warn, void *ctx)
4544{
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004546 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004547 ctxt->error = err;
4548 ctxt->warning = warn;
4549 ctxt->userData = ctx;
4550}
4551
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004552/**
4553 * xmlSchemaFacetTypeToString:
4554 * @type: the facet type
4555 *
4556 * Convert the xmlSchemaTypeType to a char string.
4557 *
4558 * Returns the char string representation of the facet type if the
4559 * type is a facet and an "Internal Error" string otherwise.
4560 */
4561static const char *
4562xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4563{
4564 switch (type) {
4565 case XML_SCHEMA_FACET_PATTERN:
4566 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004567 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004568 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004569 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004570 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004571 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004572 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004574 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004575 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004576 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004577 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004578 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004579 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004580 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004581 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004582 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004584 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004585 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004586 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004587 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004588 return ("fractionDigits");
4589 default:
4590 break;
4591 }
4592 return ("Internal Error");
4593}
4594
4595/**
4596 * xmlSchemaValidateFacets:
4597 * @ctxt: a schema validation context
4598 * @base: the base type
4599 * @facets: the list of facets to check
4600 * @value: the lexical repr of the value to validate
4601 * @val: the precomputed value
4602 *
4603 * Check a value against all facet conditions
4604 *
4605 * Returns 0 if the element is schemas valid, a positive error code
4606 * number otherwise and -1 in case of internal or API error.
4607 */
4608static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004609xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4610 xmlSchemaTypePtr base,
4611 xmlSchemaFacetPtr facets, xmlChar * value)
4612{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004613 int ret = 0;
4614 int tmp = 0;
4615 xmlSchemaTypeType type;
4616 xmlSchemaFacetPtr facet = facets;
4617
4618 while (facet != NULL) {
4619 type = facet->type;
4620 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004621 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004622
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004623 while (facet != NULL) {
4624 tmp =
4625 xmlSchemaValidateFacet(base, facet, value,
4626 ctxt->value);
4627 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004628 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 }
4630 facet = facet->next;
4631 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004632 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004633 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004634
4635 if (tmp != 0) {
4636 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 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 +00004638 }
4639 if (facet != NULL)
4640 facet = facet->next;
4641 }
4642 return (ret);
4643}
4644
Daniel Veillard4255d502002-04-16 15:50:10 +00004645/************************************************************************
4646 * *
4647 * Simple type validation *
4648 * *
4649 ************************************************************************/
4650
4651/**
4652 * xmlSchemaValidateSimpleValue:
4653 * @ctxt: a schema validation context
4654 * @type: the type declaration
4655 * @value: the value to validate
4656 *
4657 * Validate a value against a simple type
4658 *
4659 * Returns 0 if the value is valid, a positive error code
4660 * number otherwise and -1 in case of internal or API error.
4661 */
4662static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004663xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
4664 xmlSchemaTypePtr type, xmlChar * value)
4665{
Daniel Veillard4255d502002-04-16 15:50:10 +00004666 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004667
Daniel Veillard4255d502002-04-16 15:50:10 +00004668 /*
4669 * First normalize the value accordingly to Schema Datatype
4670 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4671 */
4672 /*
4673 * Then check the normalized value against the lexical space of the
4674 * type.
4675 */
4676 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004677 if (ctxt->value != NULL) {
4678 xmlSchemaFreeValue(ctxt->value);
4679 ctxt->value = NULL;
4680 }
4681 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4682 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004683 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004684 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 +00004685 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004686 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004687 xmlSchemaTypePtr base;
4688 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004689
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004690 base = type->baseType;
4691 if (base != NULL) {
4692 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4693 } else if (type->subtypes != NULL) {
4694
4695 }
4696 /*
4697 * Do not validate facets when working on building the Schemas
4698 */
4699 if (ctxt->schema != NULL) {
4700 if (ret == 0) {
4701 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004702 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004703 }
4704 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004705 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004706 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004707
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004708 base = type->subtypes;
4709 if (base != NULL) {
4710 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4711 } else {
4712 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004713 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004714 xmlSchemaTypePtr base;
4715 xmlChar *cur, *end, tmp;
4716 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00004717
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004718 base = type->subtypes;
4719 if (base == NULL) {
4720 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
4721 "Internal: List type %s has no base type\n",
4722 type->name, NULL);
4723 return (-1);
4724 }
4725 cur = value;
4726 do {
William M. Brack76e95df2003-10-18 16:20:14 +00004727 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004728 cur++;
4729 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00004730 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004731 end++;
4732 if (end == cur)
4733 break;
4734 tmp = *end;
4735 *end = 0;
4736 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4737 if (ret2 != 0)
4738 ret = 1;
4739 *end = tmp;
4740 cur = end;
4741 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004742 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004743 TODO}
4744 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004745}
4746
4747/************************************************************************
4748 * *
4749 * DOM Validation code *
4750 * *
4751 ************************************************************************/
4752
4753static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004754 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004755static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004756 xmlNodePtr elem,
4757 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004758static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004759 xmlNodePtr elem,
4760 xmlSchemaElementPtr elemDecl,
4761 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004762
4763/**
4764 * xmlSchemaRegisterAttributes:
4765 * @ctxt: a schema validation context
4766 * @attrs: a list of attributes
4767 *
4768 * Register the list of attributes as the set to be validated on that element
4769 *
4770 * Returns -1 in case of error, 0 otherwise
4771 */
4772static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004773xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
4774{
Daniel Veillard4255d502002-04-16 15:50:10 +00004775 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004776 if ((attrs->ns != NULL) &&
4777 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4778 attrs = attrs->next;
4779 continue;
4780 }
4781 if (ctxt->attrNr >= ctxt->attrMax) {
4782 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00004783
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004784 ctxt->attrMax *= 2;
4785 tmp = (xmlSchemaAttrStatePtr)
4786 xmlRealloc(ctxt->attr, ctxt->attrMax *
4787 sizeof(xmlSchemaAttrState));
4788 if (tmp == NULL) {
4789 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
4790 ctxt->attrMax /= 2;
4791 return (-1);
4792 }
4793 ctxt->attr = tmp;
4794 }
4795 ctxt->attr[ctxt->attrNr].attr = attrs;
4796 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4797 ctxt->attrNr++;
4798 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004799 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004800 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004801}
4802
4803/**
4804 * xmlSchemaCheckAttributes:
4805 * @ctxt: a schema validation context
4806 * @node: the node carrying it.
4807 *
4808 * Check that the registered set of attributes on the current node
4809 * has been properly validated.
4810 *
4811 * Returns 0 if validity constraints are met, 1 otherwise.
4812 */
4813static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004814xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4815{
Daniel Veillard4255d502002-04-16 15:50:10 +00004816 int ret = 0;
4817 int i;
4818
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
4820 if (ctxt->attr[i].attr == NULL)
4821 break;
4822 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4823 ret = 1;
4824 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
4825 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004826 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004827 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004828}
4829
4830/**
4831 * xmlSchemaValidateSimpleContent:
4832 * @ctxt: a schema validation context
4833 * @elem: an element
4834 * @type: the type declaration
4835 *
4836 * Validate the content of an element expected to be a simple type
4837 *
4838 * Returns 0 if the element is schemas valid, a positive error code
4839 * number otherwise and -1 in case of internal or API error.
4840 */
4841static int
4842xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004843 xmlNodePtr node ATTRIBUTE_UNUSED)
4844{
Daniel Veillard4255d502002-04-16 15:50:10 +00004845 xmlNodePtr child;
4846 xmlSchemaTypePtr type, base;
4847 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004848 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004849
4850 child = ctxt->node;
4851 type = ctxt->type;
4852
4853 /*
4854 * Validation Rule: Element Locally Valid (Type): 3.1.3
4855 */
4856 value = xmlNodeGetContent(child);
4857 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4858 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004859 case XML_SCHEMA_TYPE_RESTRICTION:{
4860 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004861
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004862 base = type->baseType;
4863 if (base != NULL) {
4864 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4865 } else {
4866 TODO}
4867 if (ret == 0) {
4868 facet = type->facets;
4869 ret =
4870 xmlSchemaValidateFacets(ctxt, base, facet, value);
4871 }
4872 break;
4873 }
4874 default:
4875 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004876 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004877 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00004878
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004879 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004880}
4881
4882/**
4883 * xmlSchemaValidateCheckNodeList
4884 * @nodelist: the list of nodes
4885 *
4886 * Check the node list is only made of text nodes and entities pointing
4887 * to text nodes
4888 *
4889 * Returns 1 if true, 0 if false and -1 in case of error
4890 */
4891static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004892xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
4893{
Daniel Veillard4255d502002-04-16 15:50:10 +00004894 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004895 if (nodelist->type == XML_ENTITY_REF_NODE) {
4896 TODO /* implement recursion in the entity content */
4897 }
4898 if ((nodelist->type != XML_TEXT_NODE) &&
4899 (nodelist->type != XML_COMMENT_NODE) &&
4900 (nodelist->type != XML_PI_NODE) &&
4901 (nodelist->type != XML_PI_NODE)) {
4902 return (0);
4903 }
4904 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004905 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004906 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004907}
4908
4909/**
4910 * xmlSchemaSkipIgnored:
4911 * @ctxt: a schema validation context
4912 * @type: the current type context
4913 * @node: the top node.
4914 *
4915 * Skip ignorable nodes in that context
4916 *
4917 * Returns the new sibling
4918 * number otherwise and -1 in case of internal or API error.
4919 */
4920static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00004921xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 xmlSchemaTypePtr type, xmlNodePtr node)
4923{
Daniel Veillard4255d502002-04-16 15:50:10 +00004924 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004925
Daniel Veillard4255d502002-04-16 15:50:10 +00004926 /*
4927 * TODO complete and handle entities
4928 */
4929 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00004931 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004932 ((node->type == XML_COMMENT_NODE) ||
4933 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4934 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4935 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
4936 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004937 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004938 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004939}
4940
4941/**
4942 * xmlSchemaValidateCallback:
4943 * @ctxt: a schema validation context
4944 * @name: the name of the element detected (might be NULL)
4945 * @type: the type
4946 *
4947 * A transition has been made in the automata associated to an element
4948 * content model
4949 */
4950static void
4951xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004952 const xmlChar * name ATTRIBUTE_UNUSED,
4953 xmlSchemaTypePtr type, xmlNodePtr node)
4954{
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 xmlSchemaTypePtr oldtype = ctxt->type;
4956 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004957
Daniel Veillard4255d502002-04-16 15:50:10 +00004958#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004959 xmlGenericError(xmlGenericErrorContext,
4960 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004961 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004962#endif
4963 ctxt->type = type;
4964 ctxt->node = node;
4965 xmlSchemaValidateContent(ctxt, node);
4966 ctxt->type = oldtype;
4967 ctxt->node = oldnode;
4968}
4969
4970
4971#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004972
Daniel Veillard4255d502002-04-16 15:50:10 +00004973/**
4974 * xmlSchemaValidateSimpleRestrictionType:
4975 * @ctxt: a schema validation context
4976 * @node: the top node.
4977 *
4978 * Validate the content of a restriction type.
4979 *
4980 * Returns 0 if the element is schemas valid, a positive error code
4981 * number otherwise and -1 in case of internal or API error.
4982 */
4983static int
4984xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4985 xmlNodePtr node)
4986{
4987 xmlNodePtr child;
4988 xmlSchemaTypePtr type;
4989 int ret;
4990
4991 child = ctxt->node;
4992 type = ctxt->type;
4993
4994 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004995 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004996 return (-1);
4997 }
4998 /*
4999 * Only text and text based entities references shall be found there
5000 */
5001 ret = xmlSchemaValidateCheckNodeList(child);
5002 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005004 return (-1);
5005 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005006 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 +00005007 return (-1);
5008 }
5009 ctxt->type = type->subtypes;
5010 xmlSchemaValidateContent(ctxt, node);
5011 ctxt->type = type;
5012 return (ret);
5013}
5014#endif
5015
5016/**
5017 * xmlSchemaValidateSimpleType:
5018 * @ctxt: a schema validation context
5019 * @node: the top node.
5020 *
5021 * Validate the content of an simple type.
5022 *
5023 * Returns 0 if the element is schemas valid, a positive error code
5024 * number otherwise and -1 in case of internal or API error.
5025 */
5026static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005027xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5028{
Daniel Veillard4255d502002-04-16 15:50:10 +00005029 xmlNodePtr child;
5030 xmlSchemaTypePtr type;
5031 xmlAttrPtr attr;
5032 int ret;
5033
5034 child = ctxt->node;
5035 type = ctxt->type;
5036
5037 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005038 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5039 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005040 }
5041 /*
5042 * Only text and text based entities references shall be found there
5043 */
5044 ret = xmlSchemaValidateCheckNodeList(child);
5045 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5047 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005048 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005049 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5050 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005051 }
5052 /*
5053 * Validation Rule: Element Locally Valid (Type): 3.1.1
5054 */
5055 attr = node->properties;
5056 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005057 if ((attr->ns == NULL) ||
5058 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5059 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5060 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5061 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5062 (!xmlStrEqual
5063 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5064 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5065 return (ctxt->err);
5066 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005067 }
5068
5069 ctxt->type = type->subtypes;
5070 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5071 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005072 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005073}
5074
5075/**
5076 * xmlSchemaValidateElementType:
5077 * @ctxt: a schema validation context
5078 * @node: the top node.
5079 *
5080 * Validate the content of an element type.
5081 * Validation Rule: Element Locally Valid (Complex Type)
5082 *
5083 * Returns 0 if the element is schemas valid, a positive error code
5084 * number otherwise and -1 in case of internal or API error.
5085 */
5086static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5088{
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 xmlNodePtr child;
5090 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005091 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 xmlSchemaElementPtr decl;
5093 int ret, attrBase;
5094
5095 oldregexp = ctxt->regexp;
5096
5097 child = ctxt->node;
5098 type = ctxt->type;
5099
5100 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005101 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5102 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005103 }
5104 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 if (type->minOccurs > 0) {
5106 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5107 }
5108 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005109 }
5110
5111 /*
5112 * Verify the element matches
5113 */
5114 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005115 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5116 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005117 }
5118 /*
5119 * Verify the attributes
5120 */
5121 attrBase = ctxt->attrBase;
5122 ctxt->attrBase = ctxt->attrNr;
5123 xmlSchemaRegisterAttributes(ctxt, child->properties);
5124 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5125 /*
5126 * Verify the element content recursively
5127 */
5128 decl = (xmlSchemaElementPtr) type;
5129 oldregexp = ctxt->regexp;
5130 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5132 (xmlRegExecCallbacks)
5133 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005134#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005135 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005136#endif
5137 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005138 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5139 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005140
5141 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005142 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005143#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005144 xmlGenericError(xmlGenericErrorContext,
5145 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005146#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005147 if (ret == 0) {
5148 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5149 } else if (ret < 0) {
5150 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005151#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005152 } else {
5153 xmlGenericError(xmlGenericErrorContext,
5154 "Element %s content check succeeded\n",
5155 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005156
5157#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005158 }
5159 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 }
5161 /*
5162 * Verify that all attributes were Schemas-validated
5163 */
5164 xmlSchemaCheckAttributes(ctxt, node);
5165 ctxt->attrNr = ctxt->attrBase;
5166 ctxt->attrBase = attrBase;
5167
5168 ctxt->regexp = oldregexp;
5169
5170 ctxt->node = child;
5171 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005172 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005173}
5174
5175/**
5176 * xmlSchemaValidateBasicType:
5177 * @ctxt: a schema validation context
5178 * @node: the top node.
5179 *
5180 * Validate the content of an element expected to be a basic type type
5181 *
5182 * Returns 0 if the element is schemas valid, a positive error code
5183 * number otherwise and -1 in case of internal or API error.
5184 */
5185static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005186xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5187{
Daniel Veillard4255d502002-04-16 15:50:10 +00005188 int ret;
5189 xmlNodePtr child, cur;
5190 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005192
5193 child = ctxt->node;
5194 type = ctxt->type;
5195
5196 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005197 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5198 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005199 }
5200 /*
5201 * First check the content model of the node.
5202 */
5203 cur = child;
5204 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 switch (cur->type) {
5206 case XML_TEXT_NODE:
5207 case XML_CDATA_SECTION_NODE:
5208 case XML_PI_NODE:
5209 case XML_COMMENT_NODE:
5210 case XML_XINCLUDE_START:
5211 case XML_XINCLUDE_END:
5212 break;
5213 case XML_ENTITY_REF_NODE:
5214 case XML_ENTITY_NODE:
5215 TODO break;
5216 case XML_ELEMENT_NODE:
5217 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5218 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005219 case XML_ATTRIBUTE_NODE:
5220 case XML_DOCUMENT_NODE:
5221 case XML_DOCUMENT_TYPE_NODE:
5222 case XML_DOCUMENT_FRAG_NODE:
5223 case XML_NOTATION_NODE:
5224 case XML_HTML_DOCUMENT_NODE:
5225 case XML_DTD_NODE:
5226 case XML_ELEMENT_DECL:
5227 case XML_ATTRIBUTE_DECL:
5228 case XML_ENTITY_DECL:
5229 case XML_NAMESPACE_DECL:
5230#ifdef LIBXML_DOCB_ENABLED
5231 case XML_DOCB_DOCUMENT_NODE:
5232#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005233 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5234 return (ctxt->err);
5235 }
5236 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 }
5238 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005239 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005240 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005241 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005242
5243 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005244 xmlSchemaFreeValue(ctxt->value);
5245 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005246 }
5247 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5248 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005249 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005250 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 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 +00005252 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005253 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005254}
5255
5256/**
5257 * xmlSchemaValidateComplexType:
5258 * @ctxt: a schema validation context
5259 * @node: the top node.
5260 *
5261 * Validate the content of an element expected to be a complex type type
5262 * xmlschema-1.html#cvc-complex-type
5263 * Validation Rule: Element Locally Valid (Complex Type)
5264 *
5265 * Returns 0 if the element is schemas valid, a positive error code
5266 * number otherwise and -1 in case of internal or API error.
5267 */
5268static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5270{
Daniel Veillard4255d502002-04-16 15:50:10 +00005271 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005272 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 int ret;
5274
5275 child = ctxt->node;
5276 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005277 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005278
Daniel Veillard4255d502002-04-16 15:50:10 +00005279 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005280 case XML_SCHEMA_CONTENT_EMPTY:
5281 if (child != NULL) {
5282 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5283 }
5284 if (type->attributes != NULL) {
5285 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5286 }
5287 subtype = type->subtypes;
5288 while (subtype != NULL) {
5289 ctxt->type = subtype;
5290 xmlSchemaValidateComplexType(ctxt, node);
5291 subtype = subtype->next;
5292 }
5293 break;
5294 case XML_SCHEMA_CONTENT_ELEMENTS:
5295 case XML_SCHEMA_CONTENT_MIXED:
5296 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5297 /*
5298 * Skip ignorable nodes in that context
5299 */
5300 child = xmlSchemaSkipIgnored(ctxt, type, child);
5301 while (child != NULL) {
5302 if (child->type == XML_ELEMENT_NODE) {
5303 ret = xmlRegExecPushString(ctxt->regexp,
5304 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005305#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005306 if (ret < 0)
5307 xmlGenericError(xmlGenericErrorContext,
5308 " --> %s Error\n", child->name);
5309 else
5310 xmlGenericError(xmlGenericErrorContext,
5311 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005312#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005313 }
5314 child = child->next;
5315 /*
5316 * Skip ignorable nodes in that context
5317 */
5318 child = xmlSchemaSkipIgnored(ctxt, type, child);
5319 }
5320 break;
5321 case XML_SCHEMA_CONTENT_BASIC:{
5322 if (type->subtypes != NULL) {
5323 ctxt->type = type->subtypes;
5324 xmlSchemaValidateComplexType(ctxt, node);
5325 }
5326 if (type->baseType != NULL) {
5327 ctxt->type = type->baseType;
5328 xmlSchemaValidateBasicType(ctxt, node);
5329 }
5330 if (type->attributes != NULL) {
5331 xmlSchemaValidateAttributes(ctxt, node,
5332 type->attributes);
5333 }
5334 ctxt->type = type;
5335 break;
5336 }
5337 default:
5338 TODO xmlGenericError(xmlGenericErrorContext,
5339 "unimplemented content type %d\n",
5340 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005341 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005342 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005343}
5344
5345/**
5346 * xmlSchemaValidateContent:
5347 * @ctxt: a schema validation context
5348 * @elem: an element
5349 * @type: the type declaration
5350 *
5351 * Validate the content of an element against the type.
5352 *
5353 * Returns 0 if the element is schemas valid, a positive error code
5354 * number otherwise and -1 in case of internal or API error.
5355 */
5356static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005357xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5358{
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 xmlNodePtr child;
5360 xmlSchemaTypePtr type;
5361
5362 child = ctxt->node;
5363 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005364 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005365
Daniel Veillarde19fc232002-04-22 16:01:24 +00005366 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005367 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005368
Daniel Veillard4255d502002-04-16 15:50:10 +00005369 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005370 case XML_SCHEMA_TYPE_ANY:
5371 /* Any type will do it, fine */
5372 TODO /* handle recursivity */
5373 break;
5374 case XML_SCHEMA_TYPE_COMPLEX:
5375 xmlSchemaValidateComplexType(ctxt, node);
5376 break;
5377 case XML_SCHEMA_TYPE_ELEMENT:{
5378 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5379
5380 /*
5381 * Handle element reference here
5382 */
5383 if (decl->ref != NULL) {
5384 if (decl->refDecl == NULL) {
5385 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5386 return (-1);
5387 }
5388 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5389 decl = decl->refDecl;
5390 }
5391 xmlSchemaValidateElementType(ctxt, node);
5392 ctxt->type = type;
5393 break;
5394 }
5395 case XML_SCHEMA_TYPE_BASIC:
5396 xmlSchemaValidateBasicType(ctxt, node);
5397 break;
5398 case XML_SCHEMA_TYPE_FACET:
5399 TODO break;
5400 case XML_SCHEMA_TYPE_SIMPLE:
5401 xmlSchemaValidateSimpleType(ctxt, node);
5402 break;
5403 case XML_SCHEMA_TYPE_SEQUENCE:
5404 TODO break;
5405 case XML_SCHEMA_TYPE_CHOICE:
5406 TODO break;
5407 case XML_SCHEMA_TYPE_ALL:
5408 TODO break;
5409 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5410 TODO break;
5411 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5412 TODO break;
5413 case XML_SCHEMA_TYPE_UR:
5414 TODO break;
5415 case XML_SCHEMA_TYPE_RESTRICTION:
5416 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5417 TODO break;
5418 case XML_SCHEMA_TYPE_EXTENSION:
5419 TODO break;
5420 case XML_SCHEMA_TYPE_ATTRIBUTE:
5421 TODO break;
5422 case XML_SCHEMA_TYPE_GROUP:
5423 TODO break;
5424 case XML_SCHEMA_TYPE_NOTATION:
5425 TODO break;
5426 case XML_SCHEMA_TYPE_LIST:
5427 TODO break;
5428 case XML_SCHEMA_TYPE_UNION:
5429 TODO break;
5430 case XML_SCHEMA_FACET_MININCLUSIVE:
5431 TODO break;
5432 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5433 TODO break;
5434 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5435 TODO break;
5436 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5437 TODO break;
5438 case XML_SCHEMA_FACET_TOTALDIGITS:
5439 TODO break;
5440 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5441 TODO break;
5442 case XML_SCHEMA_FACET_PATTERN:
5443 TODO break;
5444 case XML_SCHEMA_FACET_ENUMERATION:
5445 TODO break;
5446 case XML_SCHEMA_FACET_WHITESPACE:
5447 TODO break;
5448 case XML_SCHEMA_FACET_LENGTH:
5449 TODO break;
5450 case XML_SCHEMA_FACET_MAXLENGTH:
5451 TODO break;
5452 case XML_SCHEMA_FACET_MINLENGTH:
5453 TODO break;
5454 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5455 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005456 }
5457 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5458
5459 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005460 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005461 ctxt->node = ctxt->node->next;
5462 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005464}
5465
5466/**
5467 * xmlSchemaValidateType:
5468 * @ctxt: a schema validation context
5469 * @elem: an element
5470 * @type: the list of type declarations
5471 *
5472 * Validate the content of an element against the types.
5473 *
5474 * Returns 0 if the element is schemas valid, a positive error code
5475 * number otherwise and -1 in case of internal or API error.
5476 */
5477static int
5478xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005479 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5480{
Daniel Veillard4255d502002-04-16 15:50:10 +00005481 xmlChar *nil;
5482
Daniel Veillard2db8c122003-07-08 12:16:59 +00005483 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005484 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005485
Daniel Veillard4255d502002-04-16 15:50:10 +00005486 /*
5487 * 3.3.4 : 2
5488 */
5489 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005490 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5491 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005492 }
5493 /*
5494 * 3.3.4: 3
5495 */
5496 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5497 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005498 /* 3.3.4: 3.2 */
5499 if (xmlStrEqual(nil, BAD_CAST "true")) {
5500 if (elem->children != NULL) {
5501 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5502 return (ctxt->err);
5503 }
5504 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5505 (elemDecl->value != NULL)) {
5506 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5507 return (ctxt->err);
5508 }
5509 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005510 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005511 /* 3.3.4: 3.1 */
5512 if (nil != NULL) {
5513 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5514 xmlFree(nil);
5515 return (ctxt->err);
5516 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005517 }
5518
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005519 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00005520
5521 ctxt->type = elemDecl->subtypes;
5522 ctxt->node = elem->children;
5523 xmlSchemaValidateContent(ctxt, elem);
5524 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005525
5526 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005527}
5528
5529
5530/**
5531 * xmlSchemaValidateAttributes:
5532 * @ctxt: a schema validation context
5533 * @elem: an element
5534 * @attributes: the list of attribute declarations
5535 *
5536 * Validate the attributes of an element.
5537 *
5538 * Returns 0 if the element is schemas valid, a positive error code
5539 * number otherwise and -1 in case of internal or API error.
5540 */
5541static int
5542xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005543 xmlSchemaAttributePtr attributes)
5544{
Daniel Veillard4255d502002-04-16 15:50:10 +00005545 int i, ret;
5546 xmlAttrPtr attr;
5547 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005548 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005549
5550 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005551 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005552 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005553 /*
5554 * Handle attribute groups
5555 */
5556 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5557 group = (xmlSchemaAttributeGroupPtr) attributes;
5558 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5559 attributes = group->next;
5560 continue;
5561 }
5562 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5563 attr = ctxt->attr[i].attr;
5564 if (attr == NULL)
5565 continue;
5566 if (attributes->ref != NULL) {
5567 if (!xmlStrEqual(attr->name, attributes->ref))
5568 continue;
5569 if (attr->ns != NULL) {
5570 if ((attributes->refNs == NULL) ||
5571 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5572 continue;
5573 } else if (attributes->refNs != NULL) {
5574 continue;
5575 }
5576 } else {
5577 if (!xmlStrEqual(attr->name, attributes->name))
5578 continue;
5579 /*
5580 * TODO: handle the mess about namespaces here.
5581 */
5582 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */ ) {
5583 TODO}
5584 }
5585 ctxt->cur = (xmlNodePtr) attributes;
5586 if (attributes->subtypes == NULL) {
5587 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
5588 continue;
5589 }
5590 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5591 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5592 value);
5593 if (ret != 0) {
5594 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
5595 } else {
5596 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5597 }
5598 if (value != NULL) {
5599 xmlFree(value);
5600 }
5601 }
5602 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005603 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005604 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005605}
5606
5607/**
5608 * xmlSchemaValidateElement:
5609 * @ctxt: a schema validation context
5610 * @elem: an element
5611 *
5612 * Validate an element in a tree
5613 *
5614 * Returns 0 if the element is schemas valid, a positive error code
5615 * number otherwise and -1 in case of internal or API error.
5616 */
5617static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005618xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
5619{
Daniel Veillard4255d502002-04-16 15:50:10 +00005620 xmlSchemaElementPtr elemDecl;
5621 int ret, attrBase;
5622
5623 if (elem->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005624 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5625 elem->name, elem->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005626 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005627 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5628 elem->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005629 /*
5630 * 3.3.4 : 1
5631 */
5632 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
5634 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005635 }
5636 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005637 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
5638 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005639 }
5640 /*
5641 * Verify the attributes
5642 */
5643 attrBase = ctxt->attrBase;
5644 ctxt->attrBase = ctxt->attrNr;
5645 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5646 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5647 /*
5648 * Verify the element content recursively
5649 */
5650 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5652 (xmlRegExecCallbacks)
5653 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005654#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005655 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005656#endif
5657 }
5658 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005659 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005660 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005661#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662 xmlGenericError(xmlGenericErrorContext,
5663 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005664#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005665 if (ret == 0) {
5666 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
5667 } else if (ret < 0) {
5668 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005669#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670 } else {
5671 xmlGenericError(xmlGenericErrorContext,
5672 "Element %s content check succeeded\n",
5673 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005674
5675#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 }
5677 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005678 }
5679 /*
5680 * Verify that all attributes were Schemas-validated
5681 */
5682 xmlSchemaCheckAttributes(ctxt, elem);
5683 ctxt->attrNr = ctxt->attrBase;
5684 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005685
5686 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005687}
5688
5689/**
5690 * xmlSchemaValidateDocument:
5691 * @ctxt: a schema validation context
5692 * @doc: a parsed document tree
5693 *
5694 * Validate a document tree in memory.
5695 *
5696 * Returns 0 if the document is schemas valid, a positive error code
5697 * number otherwise and -1 in case of internal or API error.
5698 */
5699static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005700xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5701{
Daniel Veillard4255d502002-04-16 15:50:10 +00005702 xmlNodePtr root;
5703 xmlSchemaElementPtr elemDecl;
5704
5705 root = xmlDocGetRootElement(doc);
5706 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005707 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
5708 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005709 }
5710 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005711 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5712 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005713 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005714 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5715 root->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005716 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005717 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005718 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005719 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005720 }
5721 /*
5722 * Okay, start the recursive validation
5723 */
5724 xmlSchemaValidateElement(ctxt, root);
5725
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005726 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005727}
5728
5729/************************************************************************
5730 * *
5731 * SAX Validation code *
5732 * *
5733 ************************************************************************/
5734
5735/************************************************************************
5736 * *
5737 * Validation interfaces *
5738 * *
5739 ************************************************************************/
5740
5741/**
5742 * xmlSchemaNewValidCtxt:
5743 * @schema: a precompiled XML Schemas
5744 *
5745 * Create an XML Schemas validation context based on the given schema
5746 *
5747 * Returns the validation context or NULL in case of error
5748 */
5749xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005750xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
5751{
Daniel Veillard4255d502002-04-16 15:50:10 +00005752 xmlSchemaValidCtxtPtr ret;
5753
5754 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5755 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005756 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 return (NULL);
5758 }
5759 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5760 ret->schema = schema;
5761 ret->attrNr = 0;
5762 ret->attrMax = 10;
5763 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005764 sizeof
5765 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00005766 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005767 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
5768 free(ret);
5769 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 }
5771 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5772 return (ret);
5773}
5774
5775/**
5776 * xmlSchemaFreeValidCtxt:
5777 * @ctxt: the schema validation context
5778 *
5779 * Free the resources associated to the schema validation context
5780 */
5781void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005782xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
5783{
Daniel Veillard4255d502002-04-16 15:50:10 +00005784 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005786 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005787 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005788 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005789 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005790 xmlFree(ctxt);
5791}
5792
5793/**
5794 * xmlSchemaSetValidErrors:
5795 * @ctxt: a schema validation context
5796 * @err: the error function
5797 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00005798 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00005799 *
5800 * Set the error and warning callback informations
5801 */
5802void
5803xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 xmlSchemaValidityErrorFunc err,
5805 xmlSchemaValidityWarningFunc warn, void *ctx)
5806{
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 ctxt->error = err;
5810 ctxt->warning = warn;
5811 ctxt->userData = ctx;
5812}
5813
5814/**
5815 * xmlSchemaValidateDoc:
5816 * @ctxt: a schema validation context
5817 * @doc: a parsed document tree
5818 *
5819 * Validate a document tree in memory.
5820 *
5821 * Returns 0 if the document is schemas valid, a positive error code
5822 * number otherwise and -1 in case of internal or API error.
5823 */
5824int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005825xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5826{
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 int ret;
5828
5829 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005830 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005831
5832 ctxt->doc = doc;
5833 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005834 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005835}
5836
5837/**
5838 * xmlSchemaValidateStream:
5839 * @ctxt: a schema validation context
5840 * @input: the input to use for reading the data
5841 * @enc: an optional encoding information
5842 * @sax: a SAX handler for the resulting events
5843 * @user_data: the context to provide to the SAX handler.
5844 *
5845 * Validate a document tree in memory.
5846 *
5847 * Returns 0 if the document is schemas valid, a positive error code
5848 * number otherwise and -1 in case of internal or API error.
5849 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005850int
Daniel Veillard4255d502002-04-16 15:50:10 +00005851xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005852 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5853 xmlSAXHandlerPtr sax, void *user_data)
5854{
Daniel Veillard4255d502002-04-16 15:50:10 +00005855 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005856 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005857 ctxt->input = input;
5858 ctxt->enc = enc;
5859 ctxt->sax = sax;
5860 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005861 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005862}
5863
5864#endif /* LIBXML_SCHEMAS_ENABLED */