blob: 3556756391aca50b7bfb7e022484f019cff4e2d8 [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
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
21 * - Elimated item creation for: <restriction>, <extension>,
22 * <simpleContent>, <complexContent>, <list>, <union>
23 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036
37#include <libxml/xmlschemas.h>
38#include <libxml/schemasInternals.h>
39#include <libxml/xmlschemastypes.h>
40#include <libxml/xmlautomata.h>
41#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000042#include <libxml/dict.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000046
Daniel Veillarda84c0b32003-06-02 16:58:46 +000047/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000048
Daniel Veillard82bbbd42003-05-11 20:16:09 +000049/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000050
Daniel Veillard82bbbd42003-05-11 20:16:09 +000051/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard118aed72002-09-24 14:13:13 +000053/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard4255d502002-04-16 15:50:10 +000055/* #define DEBUG_AUTOMATA 1 */
56
Daniel Veillard3646d642004-06-02 19:19:14 +000057/* #define DEBUG_ATTR_VALIDATION 1 */
58
Daniel Veillardc0826a72004-08-10 14:17:33 +000059/* #define DEBUG_UNION_VALIDATION 1 */
60
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000061/* #define DEBUG_IDC 1 */
62
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000063/* #define DEBUG_INCLUDES 1 */
64
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000065#define DUMP_CONTENT_MODEL
66
Daniel Veillardc0826a72004-08-10 14:17:33 +000067
Daniel Veillard4255d502002-04-16 15:50:10 +000068#define UNBOUNDED (1 << 30)
69#define TODO \
70 xmlGenericError(xmlGenericErrorContext, \
71 "Unimplemented block at %s:%d\n", \
72 __FILE__, __LINE__);
73
William M. Brack2f2a6632004-08-20 23:09:47 +000074#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000075
Daniel Veillard4255d502002-04-16 15:50:10 +000076/*
77 * The XML Schemas namespaces
78 */
79static const xmlChar *xmlSchemaNs = (const xmlChar *)
80 "http://www.w3.org/2001/XMLSchema";
81
82static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
83 "http://www.w3.org/2001/XMLSchema-instance";
84
Daniel Veillardc0826a72004-08-10 14:17:33 +000085static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
86 "Element decl.";
87static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
88 "Element ref.";
89static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
90 "Attribute decl.";
91static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
92 "Attribute ref.";
93static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000094 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000095static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000096 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000097static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
98 "Model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000099#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000100static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
101 "Model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000102#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103
Daniel Veillard4255d502002-04-16 15:50:10 +0000104#define IS_SCHEMA(node, type) \
105 ((node != NULL) && (node->ns != NULL) && \
106 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
107 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
108
Daniel Veillardc0826a72004-08-10 14:17:33 +0000109#define FREE_AND_NULL(str) \
110 if (str != NULL) { \
111 xmlFree(str); \
112 str = NULL; \
113 }
114
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000115#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000116 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
117 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000118
119#define IS_COMPLEX_TYPE(item) \
120 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
121 (item->builtInType == XML_SCHEMAS_ANYTYPE))
122
123#define IS_SIMPLE_TYPE(item) \
124 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
125 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
126 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000128#define IS_ANY_SIMPLE_TYPE(item) \
129 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
130 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
131
132#define IS_NOT_TYPEFIXED(item) \
133 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
134 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
135
136#define HAS_COMPLEX_CONTENT(item) \
137 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
138 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
139 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
140
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000141#define HAS_SIMPLE_CONTENT(item) \
142 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
143 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
144
145#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
146
147#define IS_PARTICLE_EMPTIABLE(item) \
148 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
149
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000150#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
151
152#define IS_MODEL_GROUP(item) \
153 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
154 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
155 (item->type == XML_SCHEMA_TYPE_ALL))
156
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000157#define ELEM_TYPE(item) item->subtypes
158
159#define SUBST_GROUP_AFF(item) item->refDecl
160
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000161#if 0
162#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
163#endif
164
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000165/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000166#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
167#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
168#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000169*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000170
Daniel Veillard4255d502002-04-16 15:50:10 +0000171#define XML_SCHEMAS_PARSE_ERROR 1
172
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000173#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
174
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000175
176/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000177* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
178* locate schemata to be imported
179* using the namespace name; otherwise
180* the location URI will be used */
181
182/*
183* xmlSchemaParserOption:
184*
185* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000186*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000187typedef enum {
188 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000189 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000190 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000191 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000192} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000193*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000195typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197
198typedef struct _xmlSchemaItemList xmlSchemaItemList;
199typedef xmlSchemaItemList *xmlSchemaItemListPtr;
200
201struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000202 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000203 int nbItems; /* used for dynamic addition of schemata */
204 int sizeItems; /* used for dynamic addition of schemata */
205};
206
Daniel Veillard4255d502002-04-16 15:50:10 +0000207struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000208 void *userData; /* user specific data block */
209 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
210 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000211 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000212 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000213 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000214
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000215 xmlSchemaPtr topschema; /* The main schema */
216 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
217
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000218 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000219 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000220 int counter;
221
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000222 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000223 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000224 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000225
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 const char *buffer;
227 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000228
Daniel Veillard4255d502002-04-16 15:50:10 +0000229 /*
230 * Used to build complex element content models
231 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000232 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlAutomataStatePtr start;
234 xmlAutomataStatePtr end;
235 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000236
237 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000238 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000239 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
240 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000241 xmlSchemaAssemblePtr assemble;
242 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000243 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000244 const xmlChar **localImports; /* list of locally imported namespaces */
245 int sizeLocalImports;
246 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000247 xmlHashTablePtr substGroups;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248};
249
250
251#define XML_SCHEMAS_ATTR_UNKNOWN 1
252#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000253#define XML_SCHEMAS_ATTR_PROHIBITED 3
254#define XML_SCHEMAS_ATTR_MISSING 4
255#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
256#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000257#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
258#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000259#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
260#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000261
262typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
263typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
264struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000265 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000266 xmlAttrPtr attr;
267 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000268 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000269 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000270};
271
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000272/**
273 * xmlSchemaBasicItem:
274 *
275 * The abstract base type for schema components.
276 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000277typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
278typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
279struct _xmlSchemaBasicItem {
280 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281};
282
283/**
284 * xmlSchemaAnnotItem:
285 *
286 * The abstract base type for annotated schema components.
287 * (Extends xmlSchemaBasicItem)
288 */
289typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
290typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
291struct _xmlSchemaAnnotItem {
292 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000293 xmlSchemaAnnotPtr annot;
294};
295
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000296/**
297 * xmlSchemaTreeItem:
298 *
299 * The abstract base type for tree-like structured schema components.
300 * (Extends xmlSchemaAnnotItem)
301 */
302typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
303typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
304struct _xmlSchemaTreeItem {
305 xmlSchemaTypeType type;
306 xmlSchemaAnnotPtr annot;
307 xmlSchemaTreeItemPtr next;
308 xmlSchemaTreeItemPtr children;
309};
310
311/**
312 * xmlSchemaQNameRef:
313 *
314 * A component reference item (not a schema component)
315 * (Extends xmlSchemaBasicItem)
316 */
317typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
318typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
319struct _xmlSchemaQNameRef {
320 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000321 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000322 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000323 const xmlChar *name;
324 const xmlChar *targetNamespace;
325};
326
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000327/**
328 * xmlSchemaParticle:
329 *
330 * A particle component.
331 * (Extends xmlSchemaTreeItem)
332 */
333typedef struct _xmlSchemaParticle xmlSchemaParticle;
334typedef xmlSchemaParticle *xmlSchemaParticlePtr;
335struct _xmlSchemaParticle {
336 xmlSchemaTypeType type;
337 xmlSchemaAnnotPtr annot;
338 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
339 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
340 int minOccurs;
341 int maxOccurs;
342 xmlNodePtr node;
343};
344
345/**
346 * xmlSchemaModelGroup:
347 *
348 * A model group component.
349 * (Extends xmlSchemaTreeItem)
350 */
351typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
352typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
353struct _xmlSchemaModelGroup {
354 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
355 xmlSchemaAnnotPtr annot;
356 xmlSchemaTreeItemPtr next; /* not used */
357 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
358 xmlNodePtr node;
359};
360
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000361#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000362/**
363 * xmlSchemaModelGroupDef:
364 *
365 * A model group definition component.
366 * (Extends xmlSchemaTreeItem)
367 */
368typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
369typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
370struct _xmlSchemaModelGroupDef {
371 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
372 xmlSchemaAnnotPtr annot;
373 xmlSchemaTreeItemPtr next; /* not used */
374 xmlSchemaTreeItemPtr children; /* the "model group" */
375 const xmlChar *name;
376 const xmlChar *targetNamespace;
377 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000378 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000379};
380
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000381typedef struct _xmlSchemaIDC xmlSchemaIDC;
382typedef xmlSchemaIDC *xmlSchemaIDCPtr;
383
384/**
385 * xmlSchemaIDCSelect:
386 *
387 * The identity-constraint "field" and "selector" item, holding the
388 * XPath expression.
389 */
390typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
391typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
392struct _xmlSchemaIDCSelect {
393 xmlSchemaIDCSelectPtr next;
394 xmlSchemaIDCPtr idc;
395 int index; /* an index position if significant for IDC key-sequences */
396 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000397 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000398};
399
400/**
401 * xmlSchemaIDC:
402 *
403 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000404 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000405 */
406
407struct _xmlSchemaIDC {
408 xmlSchemaTypeType type;
409 xmlSchemaAnnotPtr annot;
410 xmlSchemaIDCPtr next;
411 xmlNodePtr node;
412 const xmlChar *name;
413 const xmlChar *targetNamespace;
414 xmlSchemaIDCSelectPtr selector;
415 xmlSchemaIDCSelectPtr fields;
416 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000417 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000418};
419
420/**
421 * xmlSchemaIDCAug:
422 *
423 * The augmented IDC information used for validation.
424 */
425typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
426typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
427struct _xmlSchemaIDCAug {
428 xmlSchemaIDCAugPtr next; /* next in a list */
429 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000430 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000431 tables need to be bubbled upwards */
432};
433
434/**
435 * xmlSchemaPSVIIDCKeySequence:
436 *
437 * The key sequence of a node table item.
438 */
439typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
440typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
441struct _xmlSchemaPSVIIDCKey {
442 xmlSchemaTypePtr type;
443 xmlSchemaValPtr compValue;
444};
445
446/**
447 * xmlSchemaPSVIIDCNode:
448 *
449 * The node table item of a node table.
450 */
451typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
452typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
453struct _xmlSchemaPSVIIDCNode {
454 xmlNodePtr node;
455 xmlSchemaPSVIIDCKeyPtr *keys;
456};
457
458/**
459 * xmlSchemaPSVIIDCBinding:
460 *
461 * The identity-constraint binding item of the [identity-constraint table].
462 */
463typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
464typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
465struct _xmlSchemaPSVIIDCBinding {
466 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
467 xmlSchemaIDCPtr definition; /* the IDC definition */
468 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
469 int nbNodes; /* number of entries in the node table */
470 int sizeNodes; /* size of the node table */
471 int nbDupls; /* number of already identified duplicates in the node
472 table */
473 /* int nbKeys; number of keys in each key-sequence */
474};
475
476#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
477#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
478
479#define XPATH_STATE_OBJ_MATCHES -2
480#define XPATH_STATE_OBJ_BLOCKED -3
481
482typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
483typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
484
485/**
486 * xmlSchemaIDCStateObj:
487 *
488 * The state object used to evaluate XPath expressions.
489 */
490typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
491typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
492struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000493 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000494 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000495 int depth; /* depth of creation */
496 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000497 int nbHistory;
498 int sizeHistory;
499 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
500 matcher */
501 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000502 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503};
504
505#define IDC_MATCHER 0
506
507/**
508 * xmlSchemaIDCMatcher:
509 *
510 * Used to IDC selectors (and fields) successively.
511 */
512struct _xmlSchemaIDCMatcher {
513 int type;
514 int depth; /* the tree depth at creation time */
515 xmlSchemaIDCMatcherPtr next; /* next in the list */
516 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
517 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
518 elements */
519 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000520 int targetDepth;
521};
522
523/*
524* Element info flags.
525*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000526#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
527/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
528/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529
530/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000531 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000532 *
533 * Holds information of an element node.
534 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000535typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
536typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
537struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000538 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000539 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000540 xmlNodePtr node;
541 const xmlChar *localName;
542 const xmlChar *namespaceName;
543 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000544 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000545 xmlSchemaValPtr value; /* the pre-computed value if any */
546 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
547 for the scope element*/
548 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
549 element */
550};
551
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000552#define XML_SCHEMA_VALID_INVALID_NEG_WILDCARD 1<<0
553
Daniel Veillard4255d502002-04-16 15:50:10 +0000554/**
555 * xmlSchemaValidCtxt:
556 *
557 * A Schemas validation context
558 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000559struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000560 void *userData; /* user specific data block */
561 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000562 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000563 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000564
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000565 xmlSchemaPtr schema; /* The schema in use */
566 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000567 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568 xmlCharEncoding enc;
569 xmlSAXHandlerPtr sax;
570 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000571
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572 xmlDocPtr myDoc;
573 int err;
574 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000575
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000576 xmlNodePtr node;
577 xmlNodePtr cur;
578 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000579
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000580 xmlRegExecCtxtPtr regexp;
581 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000582
Daniel Veillard3646d642004-06-02 19:19:14 +0000583 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000584 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000585 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000586 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000587 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000588 xmlNodePtr validationRoot;
589 xmlSchemaParserCtxtPtr pctxt;
590 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000591
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000592 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000593 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000594 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000595 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
596 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000597
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000598 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
599
600 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
601 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
602
603 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
604 int nbIdcNodes;
605 int sizeIdcNodes;
606
607 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
608 int nbIdcKeys;
609 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000610
611 int flags;
Daniel Veillard4255d502002-04-16 15:50:10 +0000612};
613
Daniel Veillard1d913862003-11-21 00:28:39 +0000614/*
615 * These are the entries in the schemas importSchemas hash table
616 */
617typedef struct _xmlSchemaImport xmlSchemaImport;
618typedef xmlSchemaImport *xmlSchemaImportPtr;
619struct _xmlSchemaImport {
620 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000621 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000622 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000623 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000624};
Daniel Veillard4255d502002-04-16 15:50:10 +0000625
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000626/*
627 * These are the entries associated to includes in a schemas
628 */
629typedef struct _xmlSchemaInclude xmlSchemaInclude;
630typedef xmlSchemaInclude *xmlSchemaIncludePtr;
631struct _xmlSchemaInclude {
632 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000633 const xmlChar *schemaLocation;
634 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000635 const xmlChar *origTargetNamespace;
636 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000637};
638
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000639/**
640 * xmlSchemaSubstGroup:
641 *
642 *
643 */
644typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
645typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
646struct _xmlSchemaSubstGroup {
647 xmlSchemaElementPtr head;
648 xmlSchemaItemListPtr members;
649};
650
Daniel Veillard4255d502002-04-16 15:50:10 +0000651/************************************************************************
652 * *
653 * Some predeclarations *
654 * *
655 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000656
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000657static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
658 xmlSchemaPtr schema,
659 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000660static void
661xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
662 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000663static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000664xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
665static int
666xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000667 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000668 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000669 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000670 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000671 int normalize,
672 int checkNodes);
673static int
674xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
675 xmlSchemaElementPtr elemDecl);
676static int
677xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000678 xmlSchemaWildcardPtr wild);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000679static int
680xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000681static int
682xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
683 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000684static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000685xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
686 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000687static void
688xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000689static int
690xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
691 xmlSchemaTypePtr type,
692 const xmlChar *value,
693 xmlSchemaValPtr *val);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000694static int
695xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000696static xmlSchemaTreeItemPtr
697xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
698 xmlNodePtr node, xmlSchemaTypeType type,
699 int withParticle);
700static const xmlChar *
701xmlSchemaCompTypeToString(xmlSchemaTypeType type);
702static xmlSchemaTypeLinkPtr
703xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000704
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705/************************************************************************
706 * *
707 * Datatype error handlers *
708 * *
709 ************************************************************************/
710
711/**
712 * xmlSchemaPErrMemory:
713 * @node: a context node
714 * @extra: extra informations
715 *
716 * Handle an out of memory condition
717 */
718static void
719xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
720 const char *extra, xmlNodePtr node)
721{
722 if (ctxt != NULL)
723 ctxt->nberrors++;
724 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
725 extra);
726}
727
728/**
729 * xmlSchemaPErr:
730 * @ctxt: the parsing context
731 * @node: the context node
732 * @error: the error code
733 * @msg: the error message
734 * @str1: extra data
735 * @str2: extra data
736 *
737 * Handle a parser error
738 */
739static void
740xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
741 const char *msg, const xmlChar * str1, const xmlChar * str2)
742{
743 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000744 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000745 void *data = NULL;
746
747 if (ctxt != NULL) {
748 ctxt->nberrors++;
749 channel = ctxt->error;
750 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000751 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000752 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000753 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000754 error, XML_ERR_ERROR, NULL, 0,
755 (const char *) str1, (const char *) str2, NULL, 0, 0,
756 msg, str1, str2);
757}
758
759/**
760 * xmlSchemaPErr2:
761 * @ctxt: the parsing context
762 * @node: the context node
763 * @node: the current child
764 * @error: the error code
765 * @msg: the error message
766 * @str1: extra data
767 * @str2: extra data
768 *
769 * Handle a parser error
770 */
771static void
772xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
773 xmlNodePtr child, int error,
774 const char *msg, const xmlChar * str1, const xmlChar * str2)
775{
776 if (child != NULL)
777 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
778 else
779 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
780}
781
Daniel Veillard01fa6152004-06-29 17:04:39 +0000782
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000784 * xmlSchemaPErrExt:
785 * @ctxt: the parsing context
786 * @node: the context node
787 * @error: the error code
788 * @strData1: extra data
789 * @strData2: extra data
790 * @strData3: extra data
791 * @msg: the message
792 * @str1: extra parameter for the message display
793 * @str2: extra parameter for the message display
794 * @str3: extra parameter for the message display
795 * @str4: extra parameter for the message display
796 * @str5: extra parameter for the message display
797 *
798 * Handle a parser error
799 */
800static void
801xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
802 const xmlChar * strData1, const xmlChar * strData2,
803 const xmlChar * strData3, const char *msg, const xmlChar * str1,
804 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
805 const xmlChar * str5)
806{
807
808 xmlGenericErrorFunc channel = NULL;
809 xmlStructuredErrorFunc schannel = NULL;
810 void *data = NULL;
811
812 if (ctxt != NULL) {
813 ctxt->nberrors++;
814 channel = ctxt->error;
815 data = ctxt->userData;
816 schannel = ctxt->serror;
817 }
818 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
819 error, XML_ERR_ERROR, NULL, 0,
820 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000821 (const char *) strData3, 0, 0, msg, str1, str2,
822 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000823}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000824
Daniel Veillard3646d642004-06-02 19:19:14 +0000825
826/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000827 * xmlSchemaVTypeErrMemory:
828 * @node: a context node
829 * @extra: extra informations
830 *
831 * Handle an out of memory condition
832 */
833static void
834xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
835 const char *extra, xmlNodePtr node)
836{
837 if (ctxt != NULL) {
838 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000839 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000840 }
841 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
842 extra);
843}
844
845/**
846 * xmlSchemaVErr3:
847 * @ctxt: the validation context
848 * @node: the context node
849 * @error: the error code
850 * @msg: the error message
851 * @str1: extra data
852 * @str2: extra data
853 * @str3: extra data
854 *
855 * Handle a validation error
856 */
857static void
858xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
859 const char *msg, const xmlChar *str1, const xmlChar *str2,
860 const xmlChar *str3)
861{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000862 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000863 xmlGenericErrorFunc channel = NULL;
864 void *data = NULL;
865
866 if (ctxt != NULL) {
867 ctxt->nberrors++;
868 ctxt->err = error;
869 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000870 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000871 data = ctxt->userData;
872 }
873 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000874 /* Removed, since the old schema error codes have been
875 * substituted for the global error codes.
876 *
877 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
878 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000879 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000880 error, XML_ERR_ERROR, NULL, 0,
881 (const char *) str1, (const char *) str2,
882 (const char *) str3, 0, 0,
883 msg, str1, str2, str3);
884}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000885
886/**
887 * xmlSchemaVErrExt:
888 * @ctxt: the validation context
889 * @node: the context node
890 * @error: the error code
891 * @msg: the message
892 * @str1: extra parameter for the message display
893 * @str2: extra parameter for the message display
894 * @str3: extra parameter for the message display
895 * @str4: extra parameter for the message display
896 * @str5: extra parameter for the message display
897 *
898 * Handle a validation error
899 */
900static void
901xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
902 const char *msg, const xmlChar * str1,
903 const xmlChar * str2, const xmlChar * str3,
904 const xmlChar * str4, const xmlChar * str5)
905{
906 xmlStructuredErrorFunc schannel = NULL;
907 xmlGenericErrorFunc channel = NULL;
908 void *data = NULL;
909
910 if (ctxt != NULL) {
911 ctxt->nberrors++;
912 ctxt->err = error;
913 channel = ctxt->error;
914 schannel = ctxt->serror;
915 data = ctxt->userData;
916 }
917 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000918 /* Removed, since the old schema error codes have been
919 * substituted for the global error codes.
920 *
921 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
922 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000923 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000924 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
925 msg, str1, str2, str3, str4, str5);
926}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000927/**
928 * xmlSchemaVErr:
929 * @ctxt: the validation context
930 * @node: the context node
931 * @error: the error code
932 * @msg: the error message
933 * @str1: extra data
934 * @str2: extra data
935 *
936 * Handle a validation error
937 */
938static void
939xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
940 const char *msg, const xmlChar * str1, const xmlChar * str2)
941{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000942 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000943 xmlGenericErrorFunc channel = NULL;
944 void *data = NULL;
945
946 if (ctxt != NULL) {
947 ctxt->nberrors++;
948 ctxt->err = error;
949 channel = ctxt->error;
950 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000951 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000952 }
953 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000954 /* Removed, since the old schema error codes have been
955 * substituted for the global error codes.
956 *
957 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
958 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000959 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000960 error, XML_ERR_ERROR, NULL, 0,
961 (const char *) str1, (const char *) str2, NULL, 0, 0,
962 msg, str1, str2);
963}
Daniel Veillard4255d502002-04-16 15:50:10 +0000964
Daniel Veillardc0826a72004-08-10 14:17:33 +0000965/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000966 * xmlSchemaGetComponentNode:
967 * @item: a schema component
968 *
969 * Returns node associated with the schema component.
970 * NOTE that such a node need not be available; plus, a component's
971 * node need not to reflect the component directly, since there is no
972 * one-to-one relationship between the XML Schema representation and
973 * the component representation.
974 */
975static xmlNodePtr
976xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
977{
978 switch (item->type) {
979 case XML_SCHEMA_TYPE_ELEMENT:
980 return (((xmlSchemaElementPtr) item)->node);
981 case XML_SCHEMA_TYPE_ATTRIBUTE:
982 return (((xmlSchemaAttributePtr) item)->node);
983 case XML_SCHEMA_TYPE_COMPLEX:
984 case XML_SCHEMA_TYPE_SIMPLE:
985 return (((xmlSchemaTypePtr) item)->node);
986 case XML_SCHEMA_TYPE_ANY:
987 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
988 return (((xmlSchemaWildcardPtr) item)->node);
989 case XML_SCHEMA_TYPE_PARTICLE:
990 return (((xmlSchemaParticlePtr) item)->node);
991 case XML_SCHEMA_TYPE_SEQUENCE:
992 case XML_SCHEMA_TYPE_CHOICE:
993 case XML_SCHEMA_TYPE_ALL:
994 return (((xmlSchemaModelGroupPtr) item)->node);
995 case XML_SCHEMA_TYPE_GROUP:
996 return (((xmlSchemaModelGroupDefPtr) item)->node);
997 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
998 return (((xmlSchemaAttributeGroupPtr) item)->node);
999 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1000 case XML_SCHEMA_TYPE_IDC_KEY:
1001 case XML_SCHEMA_TYPE_IDC_KEYREF:
1002 return (((xmlSchemaIDCPtr) item)->node);
1003 default:
1004 return (NULL);
1005 }
1006}
1007
1008#if 0
1009/**
1010 * xmlSchemaGetNextComponent:
1011 * @item: a schema component
1012 *
1013 * Returns the next sibling of the schema component.
1014 */
1015static xmlSchemaBasicItemPtr
1016xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1017{
1018 switch (item->type) {
1019 case XML_SCHEMA_TYPE_ELEMENT:
1020 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1021 case XML_SCHEMA_TYPE_ATTRIBUTE:
1022 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1023 case XML_SCHEMA_TYPE_COMPLEX:
1024 case XML_SCHEMA_TYPE_SIMPLE:
1025 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1026 case XML_SCHEMA_TYPE_ANY:
1027 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1028 return (NULL);
1029 case XML_SCHEMA_TYPE_PARTICLE:
1030 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1031 case XML_SCHEMA_TYPE_SEQUENCE:
1032 case XML_SCHEMA_TYPE_CHOICE:
1033 case XML_SCHEMA_TYPE_ALL:
1034 return (NULL);
1035 case XML_SCHEMA_TYPE_GROUP:
1036 return (NULL);
1037 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1038 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1039 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1040 case XML_SCHEMA_TYPE_IDC_KEY:
1041 case XML_SCHEMA_TYPE_IDC_KEYREF:
1042 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1043 default:
1044 return (NULL);
1045 }
1046}
1047#endif
1048
1049/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001050 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001051 * @attr: the attribute declaration/use
1052 *
1053 * Returns the name of the attribute; if the attribute
1054 * is a reference, the name of the referenced global type will be returned.
1055 */
1056static const xmlChar *
1057xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
1058{
1059 if (attr->ref != NULL)
1060 return(attr->ref);
1061 else
1062 return(attr->name);
1063}
1064
1065/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001066 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001067 * @type: the type (element or attribute)
1068 *
1069 * Returns the target namespace URI of the type; if the type is a reference,
1070 * the target namespace of the referenced type will be returned.
1071 */
1072static const xmlChar *
1073xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
1074{
1075 if (attr->ref != NULL)
1076 return (attr->refNs);
1077 else
1078 return(attr->targetNamespace);
1079}
1080
1081/**
1082 * xmlSchemaFormatNsUriLocal:
1083 * @buf: the string buffer
1084 * @uri: the namespace URI
1085 * @local: the local name
1086 *
1087 * Returns a representation of the given URI used
1088 * for error reports.
1089 *
1090 * Returns an empty string, if @ns is NULL, a formatted
1091 * string otherwise.
1092 */
1093static const xmlChar*
1094xmlSchemaFormatNsUriLocal(xmlChar **buf,
1095 const xmlChar *uri, const xmlChar *local)
1096{
1097 if (*buf != NULL)
1098 xmlFree(*buf);
1099 if (uri == NULL) {
1100 *buf = xmlStrdup(BAD_CAST "{'");
1101 *buf = xmlStrcat(*buf, local);
1102 } else {
1103 *buf = xmlStrdup(BAD_CAST "{'");
1104 *buf = xmlStrcat(*buf, uri);
1105 *buf = xmlStrcat(*buf, BAD_CAST "', '");
1106 *buf = xmlStrcat(*buf, local);
1107 }
1108 *buf = xmlStrcat(*buf, BAD_CAST "'}");
1109 return ((const xmlChar *) *buf);
1110}
1111
1112/**
1113 * xmlSchemaFormatNsPrefixLocal:
1114 * @buf: the string buffer
1115 * @ns: the namespace
1116 * @local: the local name
1117 *
1118 * Returns a representation of the given URI used
1119 * for error reports.
1120 *
1121 * Returns an empty string, if @ns is NULL, a formatted
1122 * string otherwise.
1123 */
1124static const xmlChar*
1125xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
1126 xmlNsPtr ns, const xmlChar *local)
1127{
1128 if (*buf != NULL) {
1129 xmlFree(*buf);
1130 *buf = NULL;
1131 }
1132 if ((ns == NULL) || (ns->prefix == NULL))
1133 return(local);
1134 else {
1135 *buf = xmlStrdup(ns->prefix);
1136 *buf = xmlStrcat(*buf, BAD_CAST ":");
1137 *buf = xmlStrcat(*buf, local);
1138 }
1139 return ((const xmlChar *) *buf);
1140}
1141
1142/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001143 * xmlSchemaFormatQName:
1144 * @buf: the string buffer
1145 * @namespaceName: the namespace name
1146 * @localName: the local name
1147 *
1148 * Returns the given QName in the format "{namespaceName}localName" or
1149 * just "localName" if @namespaceName is NULL.
1150 *
1151 * Returns the localName if @namespaceName is NULL, a formatted
1152 * string otherwise.
1153 */
1154static const xmlChar*
1155xmlSchemaFormatQName(xmlChar **buf,
1156 const xmlChar *namespaceName,
1157 const xmlChar *localName)
1158{
1159 FREE_AND_NULL(*buf)
1160 if (namespaceName == NULL)
1161 return(localName);
1162
1163 *buf = xmlStrdup(BAD_CAST "{");
1164 *buf = xmlStrcat(*buf, namespaceName);
1165 *buf = xmlStrcat(*buf, BAD_CAST "}");
1166 *buf = xmlStrcat(*buf, localName);
1167
1168 return ((const xmlChar *) *buf);
1169}
1170
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001171static const xmlChar *
1172xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1173{
1174 switch (item->type) {
1175 case XML_SCHEMA_TYPE_ELEMENT:
1176 return (((xmlSchemaElementPtr) item)->name);
1177 case XML_SCHEMA_TYPE_ATTRIBUTE:
1178 return (((xmlSchemaAttributePtr) item)->name);
1179 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1180 return (((xmlSchemaAttributeGroupPtr) item)->name);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +00001181 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001182 case XML_SCHEMA_TYPE_SIMPLE:
1183 case XML_SCHEMA_TYPE_COMPLEX:
1184 return (((xmlSchemaTypePtr) item)->name);
1185 case XML_SCHEMA_TYPE_GROUP:
1186 return (((xmlSchemaModelGroupDefPtr) item)->name);
1187 case XML_SCHEMA_TYPE_IDC_KEY:
1188 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1189 case XML_SCHEMA_TYPE_IDC_KEYREF:
1190 return (((xmlSchemaIDCPtr) item)->name);
1191 default:
1192 /*
1193 * Other components cannot have names.
1194 */
1195 break;
1196 }
1197 return (NULL);
1198}
1199
1200static const xmlChar *
1201xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1202{
1203 switch (item->type) {
1204 case XML_SCHEMA_TYPE_ELEMENT:
1205 return (((xmlSchemaElementPtr) item)->targetNamespace);
1206 case XML_SCHEMA_TYPE_ATTRIBUTE:
1207 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1208 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1209 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +00001210 case XML_SCHEMA_TYPE_BASIC:
1211 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001212 case XML_SCHEMA_TYPE_SIMPLE:
1213 case XML_SCHEMA_TYPE_COMPLEX:
1214 return (((xmlSchemaTypePtr) item)->targetNamespace);
1215 case XML_SCHEMA_TYPE_GROUP:
1216 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1217 case XML_SCHEMA_TYPE_IDC_KEY:
1218 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1219 case XML_SCHEMA_TYPE_IDC_KEYREF:
1220 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1221 default:
1222 /*
1223 * Other components cannot have names.
1224 */
1225 break;
1226 }
1227 return (NULL);
1228}
1229
1230static const xmlChar*
1231xmlSchemaGetComponentQName(xmlChar **buf,
1232 void *item)
1233{
1234 return (xmlSchemaFormatQName(buf,
1235 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1236 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1237}
1238
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001239/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001240 * xmlSchemaWildcardPCToString:
1241 * @pc: the type of processContents
1242 *
1243 * Returns a string representation of the type of
1244 * processContents.
1245 */
1246static const xmlChar *
1247xmlSchemaWildcardPCToString(int pc)
1248{
1249 switch (pc) {
1250 case XML_SCHEMAS_ANY_SKIP:
1251 return (BAD_CAST "skip");
1252 case XML_SCHEMAS_ANY_LAX:
1253 return (BAD_CAST "lax");
1254 case XML_SCHEMAS_ANY_STRICT:
1255 return (BAD_CAST "strict");
1256 default:
1257 return (BAD_CAST "invalid process contents");
1258 }
1259}
1260
1261/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001262 * xmlSchemaFormatItemForReport:
1263 * @buf: the string buffer
1264 * @itemDes: the designation of the item
1265 * @itemName: the name of the item
1266 * @item: the item as an object
1267 * @itemNode: the node of the item
1268 * @local: the local name
1269 * @parsing: if the function is used during the parse
1270 *
1271 * Returns a representation of the given item used
1272 * for error reports.
1273 *
1274 * The following order is used to build the resulting
1275 * designation if the arguments are not NULL:
1276 * 1a. If itemDes not NULL -> itemDes
1277 * 1b. If (itemDes not NULL) and (itemName not NULL)
1278 * -> itemDes + itemName
1279 * 2. If the preceding was NULL and (item not NULL) -> item
1280 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1281 *
1282 * If the itemNode is an attribute node, the name of the attribute
1283 * will be appended to the result.
1284 *
1285 * Returns the formatted string and sets @buf to the resulting value.
1286 */
1287static xmlChar*
1288xmlSchemaFormatItemForReport(xmlChar **buf,
1289 const xmlChar *itemDes,
1290 xmlSchemaTypePtr item,
1291 xmlNodePtr itemNode,
1292 int parsing)
1293{
1294 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001295 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001296
1297 if (*buf != NULL) {
1298 xmlFree(*buf);
1299 *buf = NULL;
1300 }
1301
William M. Brack2f2a6632004-08-20 23:09:47 +00001302 if (itemDes != NULL) {
1303 *buf = xmlStrdup(itemDes);
1304 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001305 switch (item->type) {
1306 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001307 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1308 *buf = xmlStrdup(BAD_CAST "'anyType'");
1309 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1310 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1311 else {
1312 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1313 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1314 *buf = xmlStrdup(BAD_CAST "'");
1315 *buf = xmlStrcat(*buf, item->name);
1316 *buf = xmlStrcat(*buf, BAD_CAST "'");
1317 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001318 break;
1319 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001320 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1321 *buf = xmlStrdup(xmlSchemaElemDesST);
1322 *buf = xmlStrcat(*buf, BAD_CAST " '");
1323 *buf = xmlStrcat(*buf, item->name);
1324 *buf = xmlStrcat(*buf, BAD_CAST "'");
1325 } else {
1326 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001327 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001328 break;
1329 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001330 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1331 *buf = xmlStrdup(xmlSchemaElemDesCT);
1332 *buf = xmlStrcat(*buf, BAD_CAST " '");
1333 *buf = xmlStrcat(*buf, item->name);
1334 *buf = xmlStrcat(*buf, BAD_CAST "'");
1335 } else {
1336 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001338 break;
1339 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1340 xmlSchemaAttributePtr attr;
1341
1342 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001343 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001344 (attr->ref == NULL)) {
1345 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1346 *buf = xmlStrcat(*buf, BAD_CAST " '");
1347 *buf = xmlStrcat(*buf, attr->name);
1348 *buf = xmlStrcat(*buf, BAD_CAST "'");
1349 } else {
1350 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1351 *buf = xmlStrcat(*buf, BAD_CAST " '");
1352 *buf = xmlStrcat(*buf, attr->refPrefix);
1353 *buf = xmlStrcat(*buf, BAD_CAST ":");
1354 *buf = xmlStrcat(*buf, attr->ref);
1355 *buf = xmlStrcat(*buf, BAD_CAST "'");
1356 }
1357 }
1358 break;
1359 case XML_SCHEMA_TYPE_ELEMENT: {
1360 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001361
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001362 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001363 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001364 (elem->ref == NULL)) {
1365 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1366 *buf = xmlStrcat(*buf, BAD_CAST " '");
1367 *buf = xmlStrcat(*buf, elem->name);
1368 *buf = xmlStrcat(*buf, BAD_CAST "'");
1369 } else {
1370 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1371 *buf = xmlStrcat(*buf, BAD_CAST " '");
1372 *buf = xmlStrcat(*buf, elem->refPrefix);
1373 *buf = xmlStrcat(*buf, BAD_CAST ":");
1374 *buf = xmlStrcat(*buf, elem->ref);
1375 *buf = xmlStrcat(*buf, BAD_CAST "'");
1376 }
1377 }
1378 break;
1379 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1380 case XML_SCHEMA_TYPE_IDC_KEY:
1381 case XML_SCHEMA_TYPE_IDC_KEYREF:
1382 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1383 *buf = xmlStrdup(BAD_CAST "unique '");
1384 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1385 *buf = xmlStrdup(BAD_CAST "key '");
1386 else
1387 *buf = xmlStrdup(BAD_CAST "keyRef '");
1388 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1389 *buf = xmlStrcat(*buf, BAD_CAST "'");
1390 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001391 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001392 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001393 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1394 ((xmlSchemaWildcardPtr) item)->processContents));
1395 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1396 break;
1397 case XML_SCHEMA_FACET_MININCLUSIVE:
1398 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1399 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1400 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1401 case XML_SCHEMA_FACET_TOTALDIGITS:
1402 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1403 case XML_SCHEMA_FACET_PATTERN:
1404 case XML_SCHEMA_FACET_ENUMERATION:
1405 case XML_SCHEMA_FACET_WHITESPACE:
1406 case XML_SCHEMA_FACET_LENGTH:
1407 case XML_SCHEMA_FACET_MAXLENGTH:
1408 case XML_SCHEMA_FACET_MINLENGTH:
1409 *buf = xmlStrdup(BAD_CAST "facet '");
1410 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1411 *buf = xmlStrcat(*buf, BAD_CAST "'");
1412 break;
1413 case XML_SCHEMA_TYPE_NOTATION:
1414 *buf = xmlStrdup(BAD_CAST "notation");
1415 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001416 case XML_SCHEMA_TYPE_GROUP: {
1417 xmlChar *s = NULL;
1418
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001419 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1420 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001421 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&s,
1422 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1423 ((xmlSchemaModelGroupDefPtr) item)->name));
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001424 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001425 FREE_AND_NULL(s)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001426 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001427 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001428 case XML_SCHEMA_TYPE_SEQUENCE:
1429 case XML_SCHEMA_TYPE_CHOICE:
1430 case XML_SCHEMA_TYPE_ALL:
1431 case XML_SCHEMA_TYPE_PARTICLE:
1432 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1433 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001434 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001435 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001436 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001437 } else
1438 named = 0;
1439
1440 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001441 xmlNodePtr elem;
1442
1443 if (itemNode->type == XML_ATTRIBUTE_NODE)
1444 elem = itemNode->parent;
1445 else
1446 elem = itemNode;
1447 *buf = xmlStrdup(BAD_CAST "Element '");
1448 if (parsing)
1449 *buf = xmlStrcat(*buf, elem->name);
1450 else
1451 *buf = xmlStrcat(*buf,
1452 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1453 *buf = xmlStrcat(*buf, BAD_CAST "'");
1454 }
1455 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1456 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1457 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1458 itemNode->ns, itemNode->name));
1459 *buf = xmlStrcat(*buf, BAD_CAST "'");
1460 }
1461 FREE_AND_NULL(str);
1462
1463 return (*buf);
1464}
1465
1466/**
1467 * xmlSchemaPFormatItemDes:
1468 * @buf: the string buffer
1469 * @item: the item as a schema object
1470 * @itemNode: the item as a node
1471 *
1472 * If the pointer to @buf is not NULL and @but holds no value,
1473 * the value is set to a item designation using
1474 * xmlSchemaFormatItemForReport. This one avoids adding
1475 * an attribute designation postfix.
1476 *
1477 * Returns a string of all enumeration elements.
1478 */
1479static void
1480xmlSchemaPRequestItemDes(xmlChar **buf,
1481 xmlSchemaTypePtr item,
1482 xmlNodePtr itemNode)
1483{
1484 if ((buf == 0) || (*buf != NULL))
1485 return;
1486 if (itemNode->type == XML_ATTRIBUTE_NODE)
1487 itemNode = itemNode->parent;
1488 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1489}
1490
1491/**
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001492 * xmlSchemaGetCanonValueWhtspExt:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001493 * @val: the precomputed value
1494 * @retValue: the returned value
1495 * @ws: the whitespace type of the value
1496 *
1497 * Get a the cononical representation of the value.
1498 * The caller has to free the returned retValue.
1499 *
1500 * Returns 0 if the value could be built and -1 in case of
1501 * API errors or if the value type is not supported yet.
1502 */
1503static int
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001504xmlSchemaGetCanonValueWhtspExt(const xmlChar *value,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001505 xmlSchemaValPtr val,
1506 xmlSchemaWhitespaceValueType ws,
1507 const xmlChar **retValue)
1508{
1509 xmlSchemaValType valType;
1510
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001511 if ((retValue == NULL) || ((value == NULL) && (val == NULL)))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001512 return (-1);
1513 *retValue = NULL;
1514 valType = xmlSchemaGetValType(val);
1515 switch (valType) {
1516 case XML_SCHEMAS_STRING:
1517 if (value == NULL)
1518 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001519 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1520 *retValue = xmlSchemaCollapseString(value);
1521 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1522 *retValue = xmlSchemaWhiteSpaceReplace(value);
1523 if ((*retValue) == NULL)
1524 *retValue = BAD_CAST xmlStrdup(value);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001525 break;
1526 case XML_SCHEMAS_NORMSTRING:
1527 if (value == NULL)
1528 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1529 else {
1530 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1531 *retValue = xmlSchemaCollapseString(value);
1532 else
1533 *retValue = xmlSchemaWhiteSpaceReplace(value);
1534 if ((*retValue) == NULL)
1535 *retValue = BAD_CAST xmlStrdup(value);
1536 }
1537 break;
1538 default:
1539 return (xmlSchemaGetCanonValue(val, retValue));
1540 }
1541 return (0);
1542}
1543
1544/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001545 * xmlSchemaFormatFacetEnumSet:
1546 * @buf: the string buffer
1547 * @type: the type holding the enumeration facets
1548 *
1549 * Builds a string consisting of all enumeration elements.
1550 *
1551 * Returns a string of all enumeration elements.
1552 */
1553static const xmlChar *
1554xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1555{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001556 xmlSchemaFacetPtr facet;
1557 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001558 const xmlChar *value = NULL;
1559 int res, found = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001560
1561 if (*buf != NULL)
1562 xmlFree(*buf);
1563 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001564
1565 do {
1566 /*
1567 * Use the whitespace type of the base type.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001568 */
1569 ws = (xmlSchemaWhitespaceValueType)
1570 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001571 for (facet = type->facets; facet != NULL; facet = facet->next) {
1572 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1573 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001574 found = 1;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001575 res = xmlSchemaGetCanonValueWhtspExt(facet->value, facet->val,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001576 ws, &value);
1577 if (res == -1) {
1578 xmlSchemaVErr(NULL, NULL,
1579 XML_SCHEMAV_INTERNAL,
1580 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1581 "compute the canonical lexical representation.\n",
1582 NULL, NULL);
1583 if (*buf != NULL)
1584 xmlFree(*buf);
1585 *buf = NULL;
1586 return (NULL);
1587 }
1588 if (*buf == NULL) {
1589 *buf = xmlStrdup(BAD_CAST "'");
1590 *buf = xmlStrcat(*buf, value);
1591 *buf = xmlStrcat(*buf, BAD_CAST "'");
1592 } else {
1593 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1594 *buf = xmlStrcat(*buf, value);
1595 *buf = xmlStrcat(*buf, BAD_CAST "'");
1596 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001597 if (value != NULL) {
1598 xmlFree((xmlChar *)value);
1599 value = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001600 }
1601 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001602 type = type->baseType;
1603 } while ((! found) && (type != NULL) &&
1604 (type->type != XML_SCHEMA_TYPE_BASIC));
1605
Daniel Veillardc0826a72004-08-10 14:17:33 +00001606 return ((const xmlChar *) *buf);
1607}
1608
1609/**
1610 * xmlSchemaVFacetErr:
1611 * @ctxt: the schema validation context
1612 * @error: the error code
1613 * @node: the node to be validated
1614 * @value: the value of the node
1615 * @type: the type holding the facet
1616 * @facet: the facet
1617 * @message: the error message of NULL
1618 * @str1: extra data
1619 * @str2: extra data
1620 * @str3: extra data
1621 *
1622 * Reports a facet validation error.
1623 * TODO: Should this report the value of an element as well?
1624 */
1625static void
1626xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1627 xmlParserErrors error,
1628 xmlNodePtr node,
1629 const xmlChar *value,
1630 unsigned long length,
1631 xmlSchemaTypePtr type,
1632 xmlSchemaFacetPtr facet,
1633 const char *message,
1634 const xmlChar *str1,
1635 const xmlChar *str2,
1636 const xmlChar *str3)
1637{
1638 xmlChar *str = NULL, *msg = NULL;
1639 xmlSchemaTypeType facetType;
1640
1641 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1642 msg = xmlStrcat(msg, BAD_CAST " [");
1643 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1644 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1645 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1646 facetType = XML_SCHEMA_FACET_ENUMERATION;
1647 /*
1648 * If enumerations are validated, one must not expect the
1649 * facet to be given.
1650 */
1651 } else
1652 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001653 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 msg = xmlStrcat(msg, BAD_CAST "']: ");
1655 if (message == NULL) {
1656 /*
1657 * Use a default message.
1658 */
1659 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1660 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1661 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1662
1663 char len[25], actLen[25];
1664
1665 /* FIXME, TODO: What is the max expected string length of the
1666 * this value?
1667 */
1668 if (node->type == XML_ATTRIBUTE_NODE)
1669 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1670 else
1671 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1672
1673 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1674 snprintf(actLen, 24, "%lu", length);
1675
1676 if (facetType == XML_SCHEMA_FACET_LENGTH)
1677 msg = xmlStrcat(msg,
1678 BAD_CAST "this differs from the allowed length of '%s'.\n");
1679 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1680 msg = xmlStrcat(msg,
1681 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1682 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1683 msg = xmlStrcat(msg,
1684 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1685
1686 if (node->type == XML_ATTRIBUTE_NODE)
1687 xmlSchemaVErrExt(ctxt, node, error,
1688 (const char *) msg,
1689 value, (const xmlChar *) actLen, (const xmlChar *) len,
1690 NULL, NULL);
1691 else
1692 xmlSchemaVErr(ctxt, node, error,
1693 (const char *) msg,
1694 (const xmlChar *) actLen, (const xmlChar *) len);
1695
1696 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1697 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1698 "of the set {%s}.\n");
1699 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1700 xmlSchemaFormatFacetEnumSet(&str, type));
1701 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1702 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1703 "by the pattern '%s'.\n");
1704 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001705 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001706 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1707 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1708 "minimum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001709 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001710 facet->value);
1711 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1712 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1713 "maximum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001714 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001715 facet->value);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001716 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001717 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
1718 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001719 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1720 facet->value);
1721 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001722 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
1723 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001724 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1725 facet->value);
Daniel Veillardf3598452005-04-05 11:10:45 +00001726 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001727 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
Daniel Veillardf3598452005-04-05 11:10:45 +00001728 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001729 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001730 facet->value);
1731 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001732 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
Daniel Veillardf3598452005-04-05 11:10:45 +00001733 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001734 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001735 facet->value);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001736 } else if (node->type == XML_ATTRIBUTE_NODE) {
1737 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001738 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001739 } else {
1740 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1741 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1742 }
1743 } else {
1744 msg = xmlStrcat(msg, (const xmlChar *) message);
1745 msg = xmlStrcat(msg, BAD_CAST ".\n");
1746 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1747 }
1748 FREE_AND_NULL(str)
1749 xmlFree(msg);
1750}
1751
1752/**
1753 * xmlSchemaVSimpleTypeErr:
1754 * @ctxt: the schema validation context
1755 * @error: the error code
1756 * @type: the type used for validation
1757 * @node: the node containing the validated value
1758 * @value: the validated value
1759 *
1760 * Reports a simple type validation error.
1761 * TODO: Should this report the value of an element as well?
1762 */
1763static void
1764xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1765 xmlParserErrors error,
1766 xmlNodePtr node,
1767 const xmlChar *value,
1768 xmlSchemaTypePtr type)
1769{
1770 xmlChar *str = NULL, *msg = NULL;
1771
1772 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1773 msg = xmlStrcat(msg, BAD_CAST " [");
1774 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1775 if (node->type == XML_ATTRIBUTE_NODE) {
1776 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1777 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1778 } else {
1779 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1780 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1781 }
1782 FREE_AND_NULL(str)
1783 xmlFree(msg);
1784}
1785
1786/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001787 * xmlSchemaVComplexTypeErr:
1788 * @ctxt: the schema validation context
1789 * @error: the error code
1790 * @node: the node containing the validated value
1791 * @type: the complex type used for validation
1792 * @message: the error message
1793 *
1794 * Reports a complex type validation error.
1795 */
1796static void
1797xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1798 xmlParserErrors error,
1799 xmlNodePtr node,
1800 xmlSchemaTypePtr type,
1801 const char *message)
1802{
1803 xmlChar *str = NULL, *msg = NULL;
1804
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001805 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001806 /* Specify the complex type only if it is global. */
1807 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001808 msg = xmlStrcat(msg, BAD_CAST " [");
1809 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1810 msg = xmlStrcat(msg, BAD_CAST "]");
1811 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001812 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1813 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001814 (const xmlChar *) message, NULL);
1815 FREE_AND_NULL(str)
1816 xmlFree(msg);
1817}
1818
1819/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001820 * xmlSchemaVComplexTypeElemErr:
1821 * @ctxt: the schema validation context
1822 * @error: the error code
1823 * @node: the node containing the validated value
1824 * @type: the complex type used for validation
1825 * @message: the error message
1826 *
1827 * Reports a complex type validation error.
1828 */
1829static void
1830xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1831 xmlParserErrors error,
1832 xmlNodePtr node,
1833 xmlSchemaTypePtr type,
1834 const char *message,
1835 int nbval,
1836 int nbneg,
1837 xmlChar **values)
1838{
1839 xmlChar *str = NULL, *msg = NULL;
1840 xmlChar *localName, *nsName;
1841 const xmlChar *cur, *end;
1842 int i;
1843
1844 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1845 /* Specify the complex type only if it is global. */
1846 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1847 msg = xmlStrcat(msg, BAD_CAST " [");
1848 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1849 msg = xmlStrcat(msg, BAD_CAST "]");
1850 FREE_AND_NULL(str)
1851 }
1852 msg = xmlStrcat(msg, BAD_CAST ": ");
1853 msg = xmlStrcat(msg, (const xmlChar *) message);
1854 /*
1855 * Note that is does not make sense to report that we have a
1856 * wildcard here, since the wildcard might be unfolded into
1857 * multiple transitions.
1858 */
1859 if (nbval + nbneg > 0) {
1860 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001861 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001862 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001863 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001864 nsName = NULL;
1865
1866 for (i = 0; i < nbval + nbneg; i++) {
1867 cur = values[i];
1868 /*
1869 * Get the local name.
1870 */
1871 localName = NULL;
1872
1873 end = cur;
1874 if (*end == '*') {
1875 localName = xmlStrdup(BAD_CAST "*");
1876 *end++;
1877 } else {
1878 while ((*end != 0) && (*end != '|'))
1879 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001880 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001881 }
1882 if (*end != 0) {
1883 *end++;
1884 /*
1885 * Skip "*|*" if they come with negated expressions, since
1886 * they represent the same negated wildcard.
1887 */
1888 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1889 /*
1890 * Get the namespace name.
1891 */
1892 cur = end;
1893 if (*end == '*') {
1894 nsName = xmlStrdup(BAD_CAST "{*}");
1895 } else {
1896 while (*end != 0)
1897 end++;
1898
1899 if (i >= nbval)
1900 nsName = xmlStrdup(BAD_CAST "{##other:");
1901 else
1902 nsName = xmlStrdup(BAD_CAST "{");
1903
1904 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1905 nsName = xmlStrcat(nsName, BAD_CAST "}");
1906 }
1907 str = xmlStrcat(str, BAD_CAST nsName);
1908 FREE_AND_NULL(nsName)
1909 } else {
1910 FREE_AND_NULL(localName);
1911 continue;
1912 }
1913 }
1914 str = xmlStrcat(str, BAD_CAST localName);
1915 FREE_AND_NULL(localName);
1916
1917 if (i < nbval + nbneg -1)
1918 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001919 }
1920 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001921 msg = xmlStrcat(msg, BAD_CAST str);
1922 FREE_AND_NULL(str)
1923 }
1924 msg = xmlStrcat(msg, BAD_CAST ".\n");
1925 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1926 xmlFree(msg);
1927}
1928
1929/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001930 * xmlSchemaPMissingAttrErr:
1931 * @ctxt: the schema validation context
1932 * @ownerDes: the designation of the owner
1933 * @ownerName: the name of the owner
1934 * @ownerItem: the owner as a schema object
1935 * @ownerElem: the owner as an element node
1936 * @node: the parent element node of the missing attribute node
1937 * @type: the corresponding type of the attribute node
1938 *
1939 * Reports an illegal attribute.
1940 */
1941static void
1942xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1943 xmlParserErrors error,
1944 xmlChar **ownerDes,
1945 xmlSchemaTypePtr ownerItem,
1946 xmlNodePtr ownerElem,
1947 const char *name,
1948 const char *message)
1949{
1950 xmlChar *des = NULL;
1951
1952 if (ownerDes == NULL)
1953 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1954 else if (*ownerDes == NULL) {
1955 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1956 des = *ownerDes;
1957 } else
1958 des = *ownerDes;
1959 if (message != NULL)
1960 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1961 else
1962 xmlSchemaPErr(ctxt, ownerElem, error,
1963 "%s: The attribute '%s' is required but missing.\n",
1964 BAD_CAST des, BAD_CAST name);
1965 if (ownerDes == NULL)
1966 FREE_AND_NULL(des);
1967}
1968
William M. Brack2f2a6632004-08-20 23:09:47 +00001969/**
1970 * xmlSchemaCompTypeToString:
1971 * @type: the type of the schema item
1972 *
1973 * Returns the component name of a schema item.
1974 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001975static const xmlChar *
Daniel Veillardc0826a72004-08-10 14:17:33 +00001976xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1977{
1978 switch (type) {
1979 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001980 return(BAD_CAST "simple type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001981 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001982 return(BAD_CAST "complex type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001983 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001984 return(BAD_CAST "element declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001985 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001986 return(BAD_CAST "attribute declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001987 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001988 return(BAD_CAST "model group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001989 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001990 return(BAD_CAST "attribute group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001991 case XML_SCHEMA_TYPE_NOTATION:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001992 return(BAD_CAST "notation declaration");
1993 case XML_SCHEMA_TYPE_SEQUENCE:
1994 return(BAD_CAST "model group (sequence)");
1995 case XML_SCHEMA_TYPE_CHOICE:
1996 return(BAD_CAST "model group (choice)");
1997 case XML_SCHEMA_TYPE_ALL:
1998 return(BAD_CAST "model group (all)");
1999 case XML_SCHEMA_TYPE_PARTICLE:
2000 return(BAD_CAST "particle");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002001 default:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002002 return(BAD_CAST "Not a schema component");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002003 }
2004}
2005/**
2006 * xmlSchemaPResCompAttrErr:
2007 * @ctxt: the schema validation context
2008 * @error: the error code
2009 * @ownerDes: the designation of the owner
2010 * @ownerItem: the owner as a schema object
2011 * @ownerElem: the owner as an element node
2012 * @name: the name of the attribute holding the QName
2013 * @refName: the referenced local name
2014 * @refURI: the referenced namespace URI
2015 * @message: optional message
2016 *
2017 * Used to report QName attribute values that failed to resolve
2018 * to schema components.
2019 */
2020static void
2021xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2022 xmlParserErrors error,
2023 xmlChar **ownerDes,
2024 xmlSchemaTypePtr ownerItem,
2025 xmlNodePtr ownerElem,
2026 const char *name,
2027 const xmlChar *refName,
2028 const xmlChar *refURI,
2029 xmlSchemaTypeType refType,
2030 const char *refTypeStr)
2031{
2032 xmlChar *des = NULL, *strA = NULL;
2033
2034 if (ownerDes == NULL)
2035 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2036 else if (*ownerDes == NULL) {
2037 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2038 des = *ownerDes;
2039 } else
2040 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002041 if (refTypeStr == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002042 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002043 xmlSchemaPErrExt(ctxt, ownerElem, error,
2044 NULL, NULL, NULL,
2045 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
2046 "%s.\n", BAD_CAST des, BAD_CAST name,
2047 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
2048 BAD_CAST refTypeStr, NULL);
2049 if (ownerDes == NULL)
2050 FREE_AND_NULL(des)
2051 FREE_AND_NULL(strA)
2052}
2053
William M. Brack2f2a6632004-08-20 23:09:47 +00002054/**
2055 * xmlSchemaPCustomAttrErr:
2056 * @ctxt: the schema parser context
2057 * @error: the error code
2058 * @ownerDes: the designation of the owner
2059 * @ownerItem: the owner as a schema object
2060 * @attr: the illegal attribute node
2061 *
2062 * Reports an illegal attribute during the parse.
2063 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002064static void
2065xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002066 xmlParserErrors error,
2067 xmlChar **ownerDes,
2068 xmlSchemaTypePtr ownerItem,
2069 xmlAttrPtr attr,
2070 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002071{
2072 xmlChar *des = NULL;
2073
2074 if (ownerDes == NULL)
2075 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2076 else if (*ownerDes == NULL) {
2077 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2078 des = *ownerDes;
2079 } else
2080 des = *ownerDes;
2081 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2082 "%s, attribute '%s': %s.\n",
2083 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2084 if (ownerDes == NULL)
2085 FREE_AND_NULL(des);
2086}
2087
2088/**
2089 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002090 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002091 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002092 * @ownerDes: the designation of the attribute's owner
2093 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00002094 * @attr: the illegal attribute node
2095 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002096 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002097 */
2098static void
2099xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2100 xmlParserErrors error,
2101 xmlChar **ownerDes,
2102 xmlSchemaTypePtr ownerItem,
2103 xmlAttrPtr attr)
2104{
2105 xmlChar *des = NULL, *strA = NULL;
2106
2107 if (ownerDes == NULL)
2108 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2109 else if (*ownerDes == NULL) {
2110 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2111 des = *ownerDes;
2112 } else
2113 des = *ownerDes;
2114 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2115 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2116 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2117 if (ownerDes == NULL)
2118 FREE_AND_NULL(des);
2119 FREE_AND_NULL(strA);
2120}
2121
William M. Brack2f2a6632004-08-20 23:09:47 +00002122/**
2123 * xmlSchemaPAquireDes:
2124 * @des: the first designation
2125 * @itemDes: the second designation
2126 * @item: the schema item
2127 * @itemElem: the node of the schema item
2128 *
2129 * Creates a designation for an item.
2130 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002131static void
2132xmlSchemaPAquireDes(xmlChar **des,
2133 xmlChar **itemDes,
2134 xmlSchemaTypePtr item,
2135 xmlNodePtr itemElem)
2136{
2137 if (itemDes == NULL)
2138 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
2139 else if (*itemDes == NULL) {
2140 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
2141 *des = *itemDes;
2142 } else
2143 *des = *itemDes;
2144}
2145
William M. Brack2f2a6632004-08-20 23:09:47 +00002146/**
2147 * xmlSchemaPCustomErr:
2148 * @ctxt: the schema parser context
2149 * @error: the error code
2150 * @itemDes: the designation of the schema item
2151 * @item: the schema item
2152 * @itemElem: the node of the schema item
2153 * @message: the error message
2154 * @str1: an optional param for the error message
2155 * @str2: an optional param for the error message
2156 * @str3: an optional param for the error message
2157 *
2158 * Reports an error during parsing.
2159 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002160static void
2161xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2162 xmlParserErrors error,
2163 xmlChar **itemDes,
2164 xmlSchemaTypePtr item,
2165 xmlNodePtr itemElem,
2166 const char *message,
2167 const xmlChar *str1,
2168 const xmlChar *str2,
2169 const xmlChar *str3)
2170{
2171 xmlChar *des = NULL, *msg = NULL;
2172
2173 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2174 msg = xmlStrdup(BAD_CAST "%s: ");
2175 msg = xmlStrcat(msg, (const xmlChar *) message);
2176 msg = xmlStrcat(msg, BAD_CAST ".\n");
2177 if ((itemElem == NULL) && (item != NULL))
2178 itemElem = item->node;
2179 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2180 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2181 if (itemDes == NULL)
2182 FREE_AND_NULL(des);
2183 FREE_AND_NULL(msg);
2184}
2185
William M. Brack2f2a6632004-08-20 23:09:47 +00002186/**
2187 * xmlSchemaPCustomErr:
2188 * @ctxt: the schema parser context
2189 * @error: the error code
2190 * @itemDes: the designation of the schema item
2191 * @item: the schema item
2192 * @itemElem: the node of the schema item
2193 * @message: the error message
2194 * @str1: the optional param for the error message
2195 *
2196 * Reports an error during parsing.
2197 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002198static void
2199xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2200 xmlParserErrors error,
2201 xmlChar **itemDes,
2202 xmlSchemaTypePtr item,
2203 xmlNodePtr itemElem,
2204 const char *message,
2205 const xmlChar *str1)
2206{
2207 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2208 str1, NULL, NULL);
2209}
2210
William M. Brack2f2a6632004-08-20 23:09:47 +00002211/**
2212 * xmlSchemaPAttrUseErr:
2213 * @ctxt: the schema parser context
2214 * @error: the error code
2215 * @itemDes: the designation of the schema type
2216 * @item: the schema type
2217 * @itemElem: the node of the schema type
2218 * @attr: the invalid schema attribute
2219 * @message: the error message
2220 * @str1: the optional param for the error message
2221 *
2222 * Reports an attribute use error during parsing.
2223 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002224static void
2225xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
2226 xmlParserErrors error,
2227 xmlChar **itemDes,
2228 xmlSchemaTypePtr item,
2229 xmlNodePtr itemElem,
2230 const xmlSchemaAttributePtr attr,
2231 const char *message,
2232 const xmlChar *str1)
2233{
2234 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
2235
2236 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2237 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
2238 xmlSchemaGetAttrName(attr));
2239 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
2240 msg = xmlStrcat(msg, (const xmlChar *) message);
2241 msg = xmlStrcat(msg, BAD_CAST ".\n");
2242 if ((itemElem == NULL) && (item != NULL))
2243 itemElem = item->node;
2244 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2245 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
2246 if (itemDes == NULL)
2247 FREE_AND_NULL(des);
2248 FREE_AND_NULL(strA);
2249 xmlFree(msg);
2250}
2251
William M. Brack2f2a6632004-08-20 23:09:47 +00002252/**
2253 * xmlSchemaPIllegalFacetAtomicErr:
2254 * @ctxt: the schema parser context
2255 * @error: the error code
2256 * @itemDes: the designation of the type
2257 * @item: the schema type
2258 * @baseItem: the base type of type
2259 * @facet: the illegal facet
2260 *
2261 * Reports an illegal facet for atomic simple types.
2262 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002263static void
2264xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2265 xmlParserErrors error,
2266 xmlChar **itemDes,
2267 xmlSchemaTypePtr item,
2268 xmlSchemaTypePtr baseItem,
2269 xmlSchemaFacetPtr facet)
2270{
2271 xmlChar *des = NULL, *strT = NULL;
2272
2273 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2274 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2275 "%s: The facet '%s' is not allowed on types derived from the "
2276 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002277 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002278 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
2279 NULL, NULL);
2280 if (itemDes == NULL)
2281 FREE_AND_NULL(des);
2282 FREE_AND_NULL(strT);
2283}
2284
William M. Brack2f2a6632004-08-20 23:09:47 +00002285/**
2286 * xmlSchemaPIllegalFacetListUnionErr:
2287 * @ctxt: the schema parser context
2288 * @error: the error code
2289 * @itemDes: the designation of the schema item involved
2290 * @item: the schema item involved
2291 * @facet: the illegal facet
2292 *
2293 * Reports an illegal facet for <list> and <union>.
2294 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002295static void
2296xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
2297 xmlParserErrors error,
2298 xmlChar **itemDes,
2299 xmlSchemaTypePtr item,
2300 xmlSchemaFacetPtr facet)
2301{
2302 xmlChar *des = NULL, *strT = NULL;
2303
2304 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2305 xmlSchemaPErr(ctxt, item->node, error,
2306 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002307 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002308 if (itemDes == NULL)
2309 FREE_AND_NULL(des);
2310 FREE_AND_NULL(strT);
2311}
2312
2313/**
2314 * xmlSchemaPMutualExclAttrErr:
2315 * @ctxt: the schema validation context
2316 * @error: the error code
2317 * @elemDes: the designation of the parent element node
2318 * @attr: the bad attribute node
2319 * @type: the corresponding type of the attribute node
2320 *
2321 * Reports an illegal attribute.
2322 */
2323static void
2324xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2325 xmlParserErrors error,
2326 xmlChar **ownerDes,
2327 xmlSchemaTypePtr ownerItem,
2328 xmlAttrPtr attr,
2329 const char *name1,
2330 const char *name2)
2331{
2332 xmlChar *des = NULL;
2333
2334 if (ownerDes == NULL)
2335 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2336 else if (*ownerDes == NULL) {
2337 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2338 des = *ownerDes;
2339 } else
2340 des = *ownerDes;
2341 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2342 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2343 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2344 if (ownerDes == NULL)
2345 FREE_AND_NULL(des)
2346}
2347
2348/**
2349 * xmlSchemaPSimpleTypeErr:
2350 * @ctxt: the schema validation context
2351 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002352 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002353 * @ownerDes: the designation of the owner
2354 * @ownerItem: the schema object if existent
2355 * @node: the validated node
2356 * @value: the validated value
2357 *
2358 * Reports a simple type validation error.
2359 * TODO: Should this report the value of an element as well?
2360 */
2361static void
2362xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2363 xmlParserErrors error,
2364 xmlChar **ownerDes,
2365 xmlSchemaTypePtr ownerItem,
2366 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002367 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002368 const char *typeDes,
2369 const xmlChar *value,
2370 const char *message,
2371 const xmlChar *str1,
2372 const xmlChar *str2)
2373{
William M. Brack2f2a6632004-08-20 23:09:47 +00002374 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002375
2376 if (ownerDes == NULL)
2377 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2378 else if (*ownerDes == NULL) {
2379 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2380 des = *ownerDes;
2381 } else
2382 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002383 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002384 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002385 if (message == NULL) {
2386 /*
2387 * Use default messages.
2388 */
2389 if (node->type == XML_ATTRIBUTE_NODE) {
2390 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2391 "%s, attribute '%s' [%s]: The value '%s' is not "
2392 "valid.\n",
2393 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2394 node->name), BAD_CAST typeDes, value, NULL);
2395 } else {
2396 xmlSchemaPErr(ctxt, node, error,
2397 "%s [%s]: The character content is not valid.\n",
2398 BAD_CAST des, BAD_CAST typeDes);
2399 }
2400 } else {
2401 xmlChar *msg;
2402
2403 msg = xmlStrdup(BAD_CAST "%s");
2404 if (node->type == XML_ATTRIBUTE_NODE)
2405 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2406 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2407 msg = xmlStrcat(msg, (const xmlChar *) message);
2408 msg = xmlStrcat(msg, BAD_CAST ".\n");
2409 if (node->type == XML_ATTRIBUTE_NODE) {
2410 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2411 (const char *) msg,
2412 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2413 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2414 } else {
2415 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2416 (const char *) msg,
2417 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2418 }
2419 xmlFree(msg);
2420 }
2421 /* Cleanup. */
2422 FREE_AND_NULL(strA)
2423 FREE_AND_NULL(strT)
2424 if (ownerDes == NULL)
2425 FREE_AND_NULL(des)
2426}
2427
William M. Brack2f2a6632004-08-20 23:09:47 +00002428/**
2429 * xmlSchemaPContentErr:
2430 * @ctxt: the schema parser context
2431 * @error: the error code
2432 * @onwerDes: the designation of the holder of the content
2433 * @ownerItem: the owner item of the holder of the content
2434 * @ownerElem: the node of the holder of the content
2435 * @child: the invalid child node
2436 * @message: the optional error message
2437 * @content: the optional string describing the correct content
2438 *
2439 * Reports an error concerning the content of a schema element.
2440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002441static void
2442xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2443 xmlParserErrors error,
2444 xmlChar **ownerDes,
2445 xmlSchemaTypePtr ownerItem,
2446 xmlNodePtr ownerElem,
2447 xmlNodePtr child,
2448 const char *message,
2449 const char *content)
2450{
2451 xmlChar *des = NULL;
2452
2453 if (ownerDes == NULL)
2454 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2455 else if (*ownerDes == NULL) {
2456 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2457 des = *ownerDes;
2458 } else
2459 des = *ownerDes;
2460 if (message != NULL)
2461 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2462 "%s: %s.\n",
2463 BAD_CAST des, BAD_CAST message);
2464 else {
2465 if (content != NULL) {
2466 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2467 "%s: The content is not valid. Expected is %s.\n",
2468 BAD_CAST des, BAD_CAST content);
2469 } else {
2470 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2471 "%s: The content is not valid.\n",
2472 BAD_CAST des, NULL);
2473 }
2474 }
2475 if (ownerDes == NULL)
2476 FREE_AND_NULL(des)
2477}
2478
2479/**
2480 * xmlSchemaVIllegalAttrErr:
2481 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002482 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002483 * @attr: the illegal attribute node
2484 *
2485 * Reports an illegal attribute.
2486 */
2487static void
2488xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002489 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002490 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002491{
2492 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002493
2494 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2495 error,
2496 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002497 "%s: The attribute '%s' is not allowed.\n",
2498 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2499 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2500 FREE_AND_NULL(strE)
2501 FREE_AND_NULL(strA)
2502}
2503
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002504
2505static int
2506xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2507{
2508 switch (item->type) {
2509 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002510 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002511 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2512 return(1);
2513 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002514 case XML_SCHEMA_TYPE_GROUP:
2515 return (1);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002516 case XML_SCHEMA_TYPE_ELEMENT:
2517 if ( ((xmlSchemaElementPtr) item)->flags &
2518 XML_SCHEMAS_ELEM_GLOBAL)
2519 return(1);
2520 break;
2521 case XML_SCHEMA_TYPE_ATTRIBUTE:
2522 if ( ((xmlSchemaAttributePtr) item)->flags &
2523 XML_SCHEMAS_ATTR_GLOBAL)
2524 return(1);
2525 break;
2526 /* Note that attribute groups are always global. */
2527 default:
2528 return(1);
2529 }
2530 return (0);
2531}
2532
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002533
2534static void
2535xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2536 xmlParserErrors error,
2537 xmlSchemaNodeInfoPtr nodeInfo,
2538 xmlSchemaTypePtr type,
2539 const char *message,
2540 const xmlChar *str1,
2541 const xmlChar *str2)
2542{
2543 xmlChar *msg = NULL, *str = NULL;
2544
2545 msg = xmlStrdup(BAD_CAST "Element '");
2546
2547 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2548 xmlSchemaNodeInfoPtr elemInfo;
2549 /*
2550 * The node info is an attribute info.
2551 */
2552 elemInfo = vctxt->elemInfos[vctxt->depth];
2553 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2554 elemInfo->namespaceName, elemInfo->localName));
2555 msg = xmlStrcat(msg, BAD_CAST "', ");
2556 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2557 }
2558 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2559 nodeInfo->namespaceName, nodeInfo->localName));
2560 msg = xmlStrcat(msg, BAD_CAST "'");
2561
2562 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2563 msg = xmlStrcat(msg, BAD_CAST " [");
2564 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2565 NULL, type, NULL, 0));
2566 msg = xmlStrcat(msg, BAD_CAST "]");
2567 }
2568 msg = xmlStrcat(msg, BAD_CAST ": ");
2569
2570 msg = xmlStrcat(msg, (const xmlChar *) message);
2571 msg = xmlStrcat(msg, BAD_CAST ".\n");
2572 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2573 str1, str2);
2574 FREE_AND_NULL(msg)
2575 FREE_AND_NULL(str)
2576}
2577
William M. Brack2f2a6632004-08-20 23:09:47 +00002578/**
2579 * xmlSchemaVCustomErr:
2580 * @ctxt: the schema validation context
2581 * @error: the error code
2582 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002583 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002584 * @message: the error message
2585 * @str1: the optional param for the message
2586 *
2587 * Reports a validation error.
2588 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002589static void
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002590xmlSchemaVCustomErrExt(xmlSchemaValidCtxtPtr ctxt,
2591 xmlParserErrors error,
2592 xmlNodePtr node,
2593 xmlSchemaTypePtr type,
2594 const char *message,
2595 const xmlChar *str1,
2596 const xmlChar *str2,
2597 const xmlChar *str3)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002598{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002599 xmlChar *msg = NULL, *str = NULL;
2600
2601 if (node == NULL) {
2602 xmlSchemaVErr(ctxt, NULL,
2603 XML_SCHEMAV_INTERNAL,
2604 "Internal error: xmlSchemaVCustomErr, no node "
2605 "given.\n", NULL, NULL);
2606 return;
2607 }
2608 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2609 if (node->type != XML_DOCUMENT_NODE) {
2610 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002611 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002612 msg = xmlStrcat(msg, BAD_CAST " [");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002613 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL,
2614 type, NULL, 0));
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002615 msg = xmlStrcat(msg, BAD_CAST "]");
2616 }
2617 msg = xmlStrcat(msg, BAD_CAST ": ");
2618 } else
2619 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002620 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002621 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002622 xmlSchemaVErrExt(ctxt, node, error, (const char *) msg, str1, str2,
2623 str3, NULL, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002624 FREE_AND_NULL(msg)
2625 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002626}
2627
William M. Brack2f2a6632004-08-20 23:09:47 +00002628/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002629 * xmlSchemaVCustomErr:
2630 * @ctxt: the schema validation context
2631 * @error: the error code
2632 * @node: the validated node
2633 * @type: the schema type of the validated node
2634 * @message: the error message
2635 * @str1: the optional param for the message
2636 *
2637 * Reports a validation error.
2638 */
2639static void
2640xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2641 xmlParserErrors error,
2642 xmlNodePtr node,
2643 xmlSchemaTypePtr type,
2644 const char *message,
2645 const xmlChar *str1)
2646{
2647 xmlSchemaVCustomErrExt(ctxt, error, node, type, message, str1, NULL, NULL);
2648}
2649
2650/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002651 * xmlSchemaVWildcardErr:
2652 * @ctxt: the schema validation context
2653 * @error: the error code
2654 * @node: the validated node
2655 * @wild: the wildcard used
2656 * @message: the error message
2657 *
2658 * Reports an validation-by-wildcard error.
2659 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002660static void
2661xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2662 xmlParserErrors error,
2663 xmlNodePtr node,
2664 xmlSchemaWildcardPtr wild,
2665 const char *message)
2666{
2667 xmlChar *des = NULL, *msg = NULL;
2668
2669 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002670 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002671 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002672 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002673 msg = xmlStrcat(msg, (const xmlChar *) message);
2674 msg = xmlStrcat(msg, BAD_CAST ".\n");
2675 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2676 FREE_AND_NULL(des);
2677 FREE_AND_NULL(msg);
2678}
2679
2680/**
2681 * xmlSchemaVMissingAttrErr:
2682 * @ctxt: the schema validation context
2683 * @node: the parent element node of the missing attribute node
2684 * @type: the corresponding type of the attribute node
2685 *
2686 * Reports an illegal attribute.
2687 */
2688static void
2689xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2690 xmlNodePtr elem,
2691 xmlSchemaAttributePtr type)
2692{
2693 const xmlChar *name, *uri;
2694 xmlChar *strE = NULL, *strA = NULL;
2695
2696 if (type->ref != NULL) {
2697 name = type->ref;
2698 uri = type->refNs;
2699 } else {
2700 name = type->name;
2701 uri = type->targetNamespace;
2702 }
2703 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002704 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2705 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002706 "%s: The attribute %s is required but missing.\n",
2707 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2708 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2709 FREE_AND_NULL(strE)
2710 FREE_AND_NULL(strA)
2711}
2712
Daniel Veillard4255d502002-04-16 15:50:10 +00002713/************************************************************************
2714 * *
2715 * Allocation functions *
2716 * *
2717 ************************************************************************/
2718
2719/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002720 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002721 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002722 *
2723 * Allocate a new Schema structure.
2724 *
2725 * Returns the newly allocated structure or NULL in case or error
2726 */
2727static xmlSchemaPtr
2728xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2729{
2730 xmlSchemaPtr ret;
2731
2732 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2733 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002734 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002735 return (NULL);
2736 }
2737 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002738 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002739 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002740
2741 return (ret);
2742}
2743
2744/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002745 * xmlSchemaNewSchema:
2746 * @ctxt: a schema validation context
2747 *
2748 * Allocate a new Schema structure.
2749 *
2750 * Returns the newly allocated structure or NULL in case or error
2751 */
2752static xmlSchemaAssemblePtr
2753xmlSchemaNewAssemble(void)
2754{
2755 xmlSchemaAssemblePtr ret;
2756
2757 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2758 if (ret == NULL) {
2759 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2760 return (NULL);
2761 }
2762 memset(ret, 0, sizeof(xmlSchemaAssemble));
2763 ret->items = NULL;
2764 return (ret);
2765}
2766
2767/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002768 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002769 *
2770 * Allocate a new Facet structure.
2771 *
2772 * Returns the newly allocated structure or NULL in case or error
2773 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002774xmlSchemaFacetPtr
2775xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002776{
2777 xmlSchemaFacetPtr ret;
2778
2779 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2780 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002781 return (NULL);
2782 }
2783 memset(ret, 0, sizeof(xmlSchemaFacet));
2784
2785 return (ret);
2786}
2787
2788/**
2789 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002790 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002791 * @node: a node
2792 *
2793 * Allocate a new annotation structure.
2794 *
2795 * Returns the newly allocated structure or NULL in case or error
2796 */
2797static xmlSchemaAnnotPtr
2798xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2799{
2800 xmlSchemaAnnotPtr ret;
2801
2802 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2803 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002804 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002805 return (NULL);
2806 }
2807 memset(ret, 0, sizeof(xmlSchemaAnnot));
2808 ret->content = node;
2809 return (ret);
2810}
2811
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002812static xmlSchemaItemListPtr
2813xmlSchemaNewItemList(void)
2814{
2815 xmlSchemaItemListPtr ret;
2816
2817 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2818 if (ret == NULL) {
2819 xmlSchemaPErrMemory(NULL,
2820 "allocating an item list structure", NULL);
2821 return (NULL);
2822 }
2823 memset(ret, 0, sizeof(xmlSchemaItemList));
2824 return (ret);
2825}
2826
2827/**
2828 * xmlSchemaAddElementSubstitutionMember:
2829 * @pctxt: a schema parser context
2830 * @head: the head of the substitution group
2831 * @member: the new member of the substitution group
2832 *
2833 * Allocate a new annotation structure.
2834 *
2835 * Returns the newly allocated structure or NULL in case or error
2836 */
2837static int
2838xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2839 xmlSchemaElementPtr head,
2840 xmlSchemaElementPtr member)
2841{
2842 xmlSchemaSubstGroupPtr substGroup;
2843
2844 if (pctxt == NULL)
2845 return (-1);
2846
2847 if (pctxt->substGroups == NULL) {
2848 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2849 if (pctxt->substGroups == NULL)
2850 return (-1);
2851 }
2852 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2853 head->targetNamespace);
2854 if (substGroup == NULL) {
2855 int res;
2856
2857 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2858 if (substGroup == NULL) {
2859 xmlSchemaPErrMemory(NULL,
2860 "xmlSchemaAddElementSubstitution, allocating a substitution "
2861 "group container",
2862 NULL);
2863 return (-1);
2864 }
2865 substGroup->members = xmlSchemaNewItemList();
2866 if (substGroup->members == NULL) {
2867 xmlFree(substGroup);
2868 return (-1);
2869 }
2870 substGroup->head = head;
2871
2872 res = xmlHashAddEntry2(pctxt->substGroups,
2873 head->name, head->targetNamespace, substGroup);
2874 if (res != 0) {
2875 xmlFree(substGroup->members);
2876 xmlFree(substGroup);
2877 xmlSchemaPErr(pctxt, member->node,
2878 XML_SCHEMAP_INTERNAL,
2879 "Internal error: xmlSchemaAddElementSubstitution, "
2880 "failed to add a new substitution group container for "
2881 "'%s'.\n", head->name, NULL);
2882 return (-1);
2883 }
2884 }
2885 if (substGroup->members->items == NULL) {
2886 substGroup->members->items = (void **) xmlMalloc(
2887 5 * sizeof(xmlSchemaElementPtr));
2888 if (substGroup->members->items == NULL) {
2889 xmlSchemaPErrMemory(NULL,
2890 "allocating list of substitution group members", NULL);
2891 return (-1);
2892 }
2893 substGroup->members->sizeItems = 5;
2894 } else if (substGroup->members->sizeItems <=
2895 substGroup->members->nbItems) {
2896 substGroup->members->sizeItems *= 2;
2897 substGroup->members->items = (void **) xmlRealloc(
2898 substGroup->members->items,
2899 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2900 if (substGroup->members->items == NULL) {
2901 xmlSchemaPErrMemory(NULL,
2902 "re-allocating list of substitution group members", NULL);
2903 substGroup->members->sizeItems = 0;
2904 return (-1);
2905 }
2906 }
2907 ((xmlSchemaElementPtr *) substGroup->members->items)
2908 [substGroup->members->nbItems++] = (void *) member;
2909 return (0);
2910}
2911
2912/**
2913 * xmlSchemaGetElementSubstitutionGroup:
2914 * @pctxt: a schema parser context
2915 * @head: the head of the substitution group
2916 * @member: the new member of the substitution group
2917 *
2918 * Allocate a new annotation structure.
2919 *
2920 * Returns the newly allocated structure or NULL in case or error
2921 */
2922static xmlSchemaSubstGroupPtr
2923xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2924 xmlSchemaElementPtr head)
2925{
2926 if (pctxt == NULL)
2927 return (NULL);
2928
2929 if (pctxt->substGroups == NULL)
2930 return (NULL);
2931
2932 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2933 head->name, head->targetNamespace));
2934}
2935
2936/**
2937 * xmlSchemaFreeItemList:
2938 * @annot: a schema type structure
2939 *
2940 * Deallocate a annotation structure
2941 */
2942static void
2943xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2944{
2945 if (list == NULL)
2946 return;
2947 if (list->items != NULL)
2948 xmlFree(list->items);
2949 xmlFree(list);
2950}
2951
Daniel Veillard4255d502002-04-16 15:50:10 +00002952/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002953 * xmlSchemaFreeAnnot:
2954 * @annot: a schema type structure
2955 *
2956 * Deallocate a annotation structure
2957 */
2958static void
2959xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2960{
2961 if (annot == NULL)
2962 return;
2963 xmlFree(annot);
2964}
2965
2966/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002967 * xmlSchemaFreeImport:
2968 * @import: a schema import structure
2969 *
2970 * Deallocate an import structure
2971 */
2972static void
2973xmlSchemaFreeImport(xmlSchemaImportPtr import)
2974{
2975 if (import == NULL)
2976 return;
2977
2978 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002979 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002980 xmlFree(import);
2981}
2982
2983/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002984 * xmlSchemaFreeInclude:
2985 * @include: a schema include structure
2986 *
2987 * Deallocate an include structure
2988 */
2989static void
2990xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2991{
2992 if (include == NULL)
2993 return;
2994
2995 xmlFreeDoc(include->doc);
2996 xmlFree(include);
2997}
2998
2999/**
3000 * xmlSchemaFreeIncludeList:
3001 * @includes: a schema include list
3002 *
3003 * Deallocate an include structure
3004 */
3005static void
3006xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
3007{
3008 xmlSchemaIncludePtr next;
3009
3010 while (includes != NULL) {
3011 next = includes->next;
3012 xmlSchemaFreeInclude(includes);
3013 includes = next;
3014 }
3015}
3016
3017/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003018 * xmlSchemaFreeNotation:
3019 * @schema: a schema notation structure
3020 *
3021 * Deallocate a Schema Notation structure.
3022 */
3023static void
3024xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3025{
3026 if (nota == NULL)
3027 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003028 xmlFree(nota);
3029}
3030
3031/**
3032 * xmlSchemaFreeAttribute:
3033 * @schema: a schema attribute structure
3034 *
3035 * Deallocate a Schema Attribute structure.
3036 */
3037static void
3038xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3039{
3040 if (attr == NULL)
3041 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003042 if (attr->annot != NULL)
3043 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003044 if (attr->defVal != NULL)
3045 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003046 xmlFree(attr);
3047}
3048
3049/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003050 * xmlSchemaFreeWildcardNsSet:
3051 * set: a schema wildcard namespace
3052 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003053 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003054 */
3055static void
3056xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3057{
3058 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059
Daniel Veillard3646d642004-06-02 19:19:14 +00003060 while (set != NULL) {
3061 next = set->next;
3062 xmlFree(set);
3063 set = next;
3064 }
3065}
3066
3067/**
3068 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003069 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003070 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003071 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003072 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003073void
Daniel Veillard3646d642004-06-02 19:19:14 +00003074xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3075{
3076 if (wildcard == NULL)
3077 return;
3078 if (wildcard->annot != NULL)
3079 xmlSchemaFreeAnnot(wildcard->annot);
3080 if (wildcard->nsSet != NULL)
3081 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3082 if (wildcard->negNsSet != NULL)
3083 xmlFree(wildcard->negNsSet);
3084 xmlFree(wildcard);
3085}
3086
3087/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003088 * xmlSchemaFreeAttributeGroup:
3089 * @schema: a schema attribute group structure
3090 *
3091 * Deallocate a Schema Attribute Group structure.
3092 */
3093static void
3094xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3095{
3096 if (attr == NULL)
3097 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003098 if (attr->annot != NULL)
3099 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003100 xmlFree(attr);
3101}
3102
3103/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003104 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003105 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003106 *
3107 * Deallocate a list of schema attribute uses.
3108 */
3109static void
3110xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3111{
3112 xmlSchemaAttributeLinkPtr next;
3113
3114 while (attrUse != NULL) {
3115 next = attrUse->next;
3116 xmlFree(attrUse);
3117 attrUse = next;
3118 }
3119}
3120
3121/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003122 * xmlSchemaFreeQNameRef:
3123 * @item: a QName reference structure
3124 *
3125 * Deallocatea a QName reference structure.
3126 */
3127static void
3128xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3129{
3130 xmlFree(item);
3131}
3132
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003133/**
3134 * xmlSchemaFreeQNameRef:
3135 * @item: a QName reference structure
3136 *
3137 * Deallocatea a QName reference structure.
3138 */
3139static void
3140xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3141{
3142 if (item == NULL)
3143 return;
3144 if (item->members != NULL)
3145 xmlSchemaFreeItemList(item->members);
3146 xmlFree(item);
3147}
3148
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003149static int
3150xmlSchemaAddVolatile(xmlSchemaPtr schema,
3151 xmlSchemaBasicItemPtr item)
3152{
3153 xmlSchemaItemListPtr list;
3154
3155 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003156 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003157 if (schema->volatiles == NULL) {
3158 xmlSchemaPErrMemory(NULL,
3159 "allocating list of volatiles", NULL);
3160 return (-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003161 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003162 }
3163 list = (xmlSchemaItemListPtr) schema->volatiles;
3164 if (list->items == NULL) {
3165 list->items = (void **) xmlMalloc(
3166 20 * sizeof(xmlSchemaBasicItemPtr));
3167 if (list->items == NULL) {
3168 xmlSchemaPErrMemory(NULL,
3169 "allocating new volatile item buffer", NULL);
3170 return (-1);
3171 }
3172 list->sizeItems = 20;
3173 } else if (list->sizeItems <= list->nbItems) {
3174 list->sizeItems *= 2;
3175 list->items = (void **) xmlRealloc(list->items,
3176 list->sizeItems * sizeof(xmlSchemaTypePtr));
3177 if (list->items == NULL) {
3178 xmlSchemaPErrMemory(NULL,
3179 "growing volatile item buffer", NULL);
3180 list->sizeItems = 0;
3181 return (-1);
3182 }
3183 }
3184 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3185 return (0);
3186}
3187
3188/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003189 * xmlSchemaFreeTypeLinkList:
3190 * @alink: a type link
3191 *
3192 * Deallocate a list of types.
3193 */
3194static void
3195xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3196{
3197 xmlSchemaTypeLinkPtr next;
3198
3199 while (link != NULL) {
3200 next = link->next;
3201 xmlFree(link);
3202 link = next;
3203 }
3204}
3205
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003206static void
3207xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3208{
3209 xmlSchemaIDCStateObjPtr next;
3210 while (sto != NULL) {
3211 next = sto->next;
3212 if (sto->history != NULL)
3213 xmlFree(sto->history);
3214 if (sto->xpathCtxt != NULL)
3215 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3216 xmlFree(sto);
3217 sto = next;
3218 }
3219}
3220
3221/**
3222 * xmlSchemaFreeIDC:
3223 * @idc: a identity-constraint definition
3224 *
3225 * Deallocates an identity-constraint definition.
3226 */
3227static void
3228xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3229{
3230 xmlSchemaIDCSelectPtr cur, prev;
3231
3232 if (idcDef == NULL)
3233 return;
3234 if (idcDef->annot != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003235 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003236 /* Selector */
3237 if (idcDef->selector != NULL) {
3238 if (idcDef->selector->xpathComp != NULL)
3239 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3240 xmlFree(idcDef->selector);
3241 }
3242 /* Fields */
3243 if (idcDef->fields != NULL) {
3244 cur = idcDef->fields;
3245 do {
3246 prev = cur;
3247 cur = cur->next;
3248 if (prev->xpathComp != NULL)
3249 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3250 xmlFree(prev);
3251 } while (cur != NULL);
3252 }
3253 xmlFree(idcDef);
3254}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003255
Daniel Veillard01fa6152004-06-29 17:04:39 +00003256/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003257 * xmlSchemaFreeElement:
3258 * @schema: a schema element structure
3259 *
3260 * Deallocate a Schema Element structure.
3261 */
3262static void
3263xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3264{
3265 if (elem == NULL)
3266 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003267 if (elem->annot != NULL)
3268 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003269 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003270 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003271 if (elem->defVal != NULL)
3272 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003273 xmlFree(elem);
3274}
3275
3276/**
3277 * xmlSchemaFreeFacet:
3278 * @facet: a schema facet structure
3279 *
3280 * Deallocate a Schema Facet structure.
3281 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003282void
Daniel Veillard4255d502002-04-16 15:50:10 +00003283xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3284{
3285 if (facet == NULL)
3286 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003287 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003288 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003289 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003290 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003291 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003292 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003293 xmlFree(facet);
3294}
3295
3296/**
3297 * xmlSchemaFreeType:
3298 * @type: a schema type structure
3299 *
3300 * Deallocate a Schema Type structure.
3301 */
3302void
3303xmlSchemaFreeType(xmlSchemaTypePtr type)
3304{
3305 if (type == NULL)
3306 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003307 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003308 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003309 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003310 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003311
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003312 facet = type->facets;
3313 while (facet != NULL) {
3314 next = facet->next;
3315 xmlSchemaFreeFacet(facet);
3316 facet = next;
3317 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003318 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003319 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3320 if (type->attributeUses != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003321 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003322 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003323 if (type->memberTypes != NULL)
3324 xmlSchemaFreeTypeLinkList(type->memberTypes);
3325 if (type->facetSet != NULL) {
3326 xmlSchemaFacetLinkPtr next, link;
3327
3328 link = type->facetSet;
3329 do {
3330 next = link->next;
3331 xmlFree(link);
3332 link = next;
3333 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003334 }
3335 if (type->contModel != NULL)
3336 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003337 xmlFree(type);
3338}
3339
3340/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003341 * xmlSchemaFreeModelGroupDef:
3342 * @item: a schema model group definition
3343 *
3344 * Deallocates a schema model group definition.
3345 */
3346static void
3347xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3348{
3349 if (item->annot != NULL)
3350 xmlSchemaFreeAnnot(item->annot);
3351 xmlFree(item);
3352}
3353
3354/**
3355 * xmlSchemaFreeModelGroup:
3356 * @item: a schema model group
3357 *
3358 * Deallocates a schema model group structure.
3359 */
3360static void
3361xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3362{
3363 if (item->annot != NULL)
3364 xmlSchemaFreeAnnot(item->annot);
3365 xmlFree(item);
3366}
3367
3368/**
3369 * xmlSchemaFreeParticle:
3370 * @type: a schema type structure
3371 *
3372 * Deallocate a Schema Type structure.
3373 */
3374static void
3375xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3376{
3377 if (item->annot != NULL)
3378 xmlSchemaFreeAnnot(item->annot);
3379 xmlFree(item);
3380}
3381
3382/**
3383 * xmlSchemaFreeMiscComponents:
3384 * @item: a schema component
3385 *
3386 * Deallocates misc. schema component structures.
3387 */
3388static void
3389xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3390{
3391 if (item == NULL)
3392 return;
3393 switch (item->type) {
3394 case XML_SCHEMA_TYPE_PARTICLE:
3395 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3396 return;
3397 case XML_SCHEMA_TYPE_SEQUENCE:
3398 case XML_SCHEMA_TYPE_CHOICE:
3399 case XML_SCHEMA_TYPE_ALL:
3400 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3401 return;
3402 case XML_SCHEMA_TYPE_ANY:
3403 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3404 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3405 break;
3406 default:
3407 /* TODO: This should never be hit. */
3408 TODO
3409 return;
3410 }
3411}
3412
3413static void
3414xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3415{
3416 if (schema->volatiles == NULL)
3417 return;
3418 {
3419 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3420 xmlSchemaTreeItemPtr item;
3421 int i;
3422
3423 for (i = 0; i < list->nbItems; i++) {
3424 if (list->items[i] != NULL) {
3425 item = (xmlSchemaTreeItemPtr) list->items[i];
3426 switch (item->type) {
3427 case XML_SCHEMA_EXTRA_QNAMEREF:
3428 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3429 break;
3430 default:
3431 xmlSchemaFreeMiscComponents(item);
3432 }
3433 }
3434 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003435 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003436 }
3437}
3438/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003439 * xmlSchemaFreeTypeList:
3440 * @type: a schema type structure
3441 *
3442 * Deallocate a Schema Type structure.
3443 */
3444static void
3445xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3446{
3447 xmlSchemaTypePtr next;
3448
3449 while (type != NULL) {
3450 next = type->redef;
3451 xmlSchemaFreeType(type);
3452 type = next;
3453 }
3454}
3455
3456/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003457 * xmlSchemaFree:
3458 * @schema: a schema structure
3459 *
3460 * Deallocate a Schema structure.
3461 */
3462void
3463xmlSchemaFree(xmlSchemaPtr schema)
3464{
3465 if (schema == NULL)
3466 return;
3467
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003468 if (schema->volatiles != NULL)
3469 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003470 if (schema->notaDecl != NULL)
3471 xmlHashFree(schema->notaDecl,
3472 (xmlHashDeallocator) xmlSchemaFreeNotation);
3473 if (schema->attrDecl != NULL)
3474 xmlHashFree(schema->attrDecl,
3475 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3476 if (schema->attrgrpDecl != NULL)
3477 xmlHashFree(schema->attrgrpDecl,
3478 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3479 if (schema->elemDecl != NULL)
3480 xmlHashFree(schema->elemDecl,
3481 (xmlHashDeallocator) xmlSchemaFreeElement);
3482 if (schema->typeDecl != NULL)
3483 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003484 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003485 if (schema->groupDecl != NULL)
3486 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003487 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003488 if (schema->idcDef != NULL)
3489 xmlHashFree(schema->idcDef,
3490 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003491 if (schema->schemasImports != NULL)
3492 xmlHashFree(schema->schemasImports,
3493 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003494 if (schema->includes != NULL) {
3495 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3496 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003497 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003498 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003499 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003500 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003501 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003502 xmlFree(schema);
3503}
3504
3505/************************************************************************
3506 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 * Debug functions *
3508 * *
3509 ************************************************************************/
3510
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003511#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003512
Daniel Veillard4255d502002-04-16 15:50:10 +00003513/**
3514 * xmlSchemaElementDump:
3515 * @elem: an element
3516 * @output: the file output
3517 *
3518 * Dump the element
3519 */
3520static void
3521xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003522 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003523 const xmlChar * namespace ATTRIBUTE_UNUSED,
3524 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003525{
3526 if (elem == NULL)
3527 return;
3528
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003529 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3530 fprintf(output, "Particle: %s", name);
3531 fprintf(output, ", term element: %s", elem->ref);
3532 if (elem->refNs != NULL)
3533 fprintf(output, " ns %s", elem->refNs);
3534 } else {
3535 fprintf(output, "Element");
3536 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3537 fprintf(output, " (global)");
3538 fprintf(output, ": %s ", elem->name);
3539 if (namespace != NULL)
3540 fprintf(output, "ns %s", namespace);
3541 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003542 fprintf(output, "\n");
3543 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003544 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003545 if (elem->maxOccurs >= UNBOUNDED)
3546 fprintf(output, "max: unbounded\n");
3547 else if (elem->maxOccurs != 1)
3548 fprintf(output, "max: %d\n", elem->maxOccurs);
3549 else
3550 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003551 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003552 /*
3553 * Misc other properties.
3554 */
3555 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3556 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3557 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3558 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3559 (elem->id != NULL)) {
3560 fprintf(output, " props: ");
3561 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3562 fprintf(output, "[fixed] ");
3563 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3564 fprintf(output, "[default] ");
3565 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3566 fprintf(output, "[abstract] ");
3567 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3568 fprintf(output, "[nillable] ");
3569 if (elem->id != NULL)
3570 fprintf(output, "[id: '%s'] ", elem->id);
3571 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003572 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003573 /*
3574 * Default/fixed value.
3575 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003576 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003577 fprintf(output, " value: '%s'\n", elem->value);
3578 /*
3579 * Type.
3580 */
3581 if (elem->namedType != NULL) {
3582 fprintf(output, " type: %s ", elem->namedType);
3583 if (elem->namedTypeNs != NULL)
3584 fprintf(output, "ns %s\n", elem->namedTypeNs);
3585 else
3586 fprintf(output, "\n");
3587 }
3588 /*
3589 * Substitution group.
3590 */
3591 if (elem->substGroup != NULL) {
3592 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3593 if (elem->substGroupNs != NULL)
3594 fprintf(output, "ns %s\n", elem->substGroupNs);
3595 else
3596 fprintf(output, "\n");
3597 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003598}
3599
3600/**
3601 * xmlSchemaAnnotDump:
3602 * @output: the file output
3603 * @annot: a annotation
3604 *
3605 * Dump the annotation
3606 */
3607static void
3608xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3609{
3610 xmlChar *content;
3611
3612 if (annot == NULL)
3613 return;
3614
3615 content = xmlNodeGetContent(annot->content);
3616 if (content != NULL) {
3617 fprintf(output, " Annot: %s\n", content);
3618 xmlFree(content);
3619 } else
3620 fprintf(output, " Annot: empty\n");
3621}
3622
3623/**
3624 * xmlSchemaTypeDump:
3625 * @output: the file output
3626 * @type: a type structure
3627 *
3628 * Dump a SchemaType structure
3629 */
3630static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003631xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3632{
3633 xmlChar *str = NULL;
3634 xmlSchemaTreeItemPtr term;
3635 char shift[100];
3636 int i;
3637
3638 if (particle == NULL)
3639 return;
3640 for (i = 0;((i < depth) && (i < 25));i++)
3641 shift[2 * i] = shift[2 * i + 1] = ' ';
3642 shift[2 * i] = shift[2 * i + 1] = 0;
3643 fprintf(output, shift);
3644 if (particle->children == NULL) {
3645 fprintf(output, "MISSING particle term\n");
3646 return;
3647 }
3648 term = particle->children;
3649 switch (term->type) {
3650 case XML_SCHEMA_TYPE_ELEMENT:
3651 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
3652 ((xmlSchemaElementPtr)term)->targetNamespace,
3653 ((xmlSchemaElementPtr)term)->name));
3654 break;
3655 case XML_SCHEMA_TYPE_SEQUENCE:
3656 fprintf(output, "SEQUENCE");
3657 break;
3658 case XML_SCHEMA_TYPE_CHOICE:
3659 fprintf(output, "CHOICE");
3660 break;
3661 case XML_SCHEMA_TYPE_ALL:
3662 fprintf(output, "ALL");
3663 break;
3664 case XML_SCHEMA_TYPE_ANY:
3665 fprintf(output, "ANY");
3666 break;
3667 default:
3668 fprintf(output, "UNKNOWN\n");
3669 return;
3670 }
3671 if (particle->minOccurs != 1)
3672 fprintf(output, " min: %d", particle->minOccurs);
3673 if (particle->maxOccurs >= UNBOUNDED)
3674 fprintf(output, " max: unbounded");
3675 else if (particle->maxOccurs != 1)
3676 fprintf(output, " max: %d", particle->maxOccurs);
3677 fprintf(output, "\n");
3678 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3679 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3680 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3681 (term->children != NULL)) {
3682 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3683 output, depth +1);
3684 }
3685 if (particle->next != NULL)
3686 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3687 output, depth);
3688}
3689/**
3690 * xmlSchemaTypeDump:
3691 * @output: the file output
3692 * @type: a type structure
3693 *
3694 * Dump a SchemaType structure
3695 */
3696static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003697xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3698{
3699 if (type == NULL) {
3700 fprintf(output, "Type: NULL\n");
3701 return;
3702 }
3703 fprintf(output, "Type: ");
3704 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003705 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003706 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003707 fprintf(output, "no name ");
3708 if (type->targetNamespace != NULL)
3709 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 switch (type->type) {
3711 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003712 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 break;
3714 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003715 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 break;
3717 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003718 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 break;
3720 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003721 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 break;
3723 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003724 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 break;
3726 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003727 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 break;
3729 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003730 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003731 break;
3732 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003733 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 break;
3735 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003736 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003737 break;
3738 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003739 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003740 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003741 }
3742 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003743 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003744 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003745 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003746 break;
3747 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003748 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003749 break;
3750 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003751 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003752 break;
3753 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003754 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003755 break;
3756 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003757 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003758 break;
3759 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003760 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003761 break;
3762 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003763 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003764 break;
3765 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003766 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003767 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 }
3769 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003770 if (type->base != NULL) {
3771 fprintf(output, " base type: %s", type->base);
3772 if (type->baseNs != NULL)
3773 fprintf(output, " ns %s\n", type->baseNs);
3774 else
3775 fprintf(output, "\n");
3776 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003777 if (type->annot != NULL)
3778 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003779#ifdef DUMP_CONTENT_MODEL
3780 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3781 (type->subtypes != NULL)) {
3782 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3783 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003785#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003786}
3787
3788/**
3789 * xmlSchemaDump:
3790 * @output: the file output
3791 * @schema: a schema structure
3792 *
3793 * Dump a Schema structure.
3794 */
3795void
3796xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3797{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003798 if (output == NULL)
3799 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003800 if (schema == NULL) {
3801 fprintf(output, "Schemas: NULL\n");
3802 return;
3803 }
3804 fprintf(output, "Schemas: ");
3805 if (schema->name != NULL)
3806 fprintf(output, "%s, ", schema->name);
3807 else
3808 fprintf(output, "no name, ");
3809 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003810 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003811 else
3812 fprintf(output, "no target namespace");
3813 fprintf(output, "\n");
3814 if (schema->annot != NULL)
3815 xmlSchemaAnnotDump(output, schema->annot);
3816
3817 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3818 output);
3819 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003820 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003821}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003822
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003823#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003824/**
3825 * xmlSchemaDebugDumpIDCTable:
3826 * @vctxt: the WXS validation context
3827 *
3828 * Displays the current IDC table for debug purposes.
3829 */
3830static void
3831xmlSchemaDebugDumpIDCTable(FILE * output,
3832 const xmlChar *namespaceName,
3833 const xmlChar *localName,
3834 xmlSchemaPSVIIDCBindingPtr bind)
3835{
3836 xmlChar *str = NULL, *value;
3837 xmlSchemaPSVIIDCNodePtr tab;
3838 xmlSchemaPSVIIDCKeyPtr key;
3839 int i, j, res;
3840
3841 fprintf(output, "IDC: TABLES on %s\n",
3842 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3843 FREE_AND_NULL(str)
3844
3845 if (bind == NULL)
3846 return;
3847 do {
3848 fprintf(output, "IDC: BINDING %s\n",
3849 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3850 bind->definition->name));
3851 FREE_AND_NULL(str)
3852 for (i = 0; i < bind->nbNodes; i++) {
3853 tab = bind->nodeTable[i];
3854 fprintf(output, " ( ");
3855 for (j = 0; j < bind->definition->nbFields; j++) {
3856 key = tab->keys[j];
3857 if ((key != NULL) && (key->compValue != NULL)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003858 res = xmlSchemaGetCanonValue(key->compValue, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003859 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003860 fprintf(output, "\"%s\" ", value);
3861 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003862 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003863 if (res == 0)
3864 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003865 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003866 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003867 else
3868 fprintf(output, "(key missing), ");
3869 }
3870 fprintf(output, ")\n");
3871 }
3872 bind = bind->next;
3873 } while (bind != NULL);
3874}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003875#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003876#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003877
3878/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003879 * *
3880 * Utilities *
3881 * *
3882 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003883
Daniel Veillardc0826a72004-08-10 14:17:33 +00003884/**
3885 * xmlSchemaGetPropNode:
3886 * @node: the element node
3887 * @name: the name of the attribute
3888 *
3889 * Seeks an attribute with a name of @name in
3890 * no namespace.
3891 *
3892 * Returns the attribute or NULL if not present.
3893 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003894static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003895xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003896{
3897 xmlAttrPtr prop;
3898
Daniel Veillardc0826a72004-08-10 14:17:33 +00003899 if ((node == NULL) || (name == NULL))
3900 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003901 prop = node->properties;
3902 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003903 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3904 return(prop);
3905 prop = prop->next;
3906 }
3907 return (NULL);
3908}
3909
3910/**
3911 * xmlSchemaGetPropNodeNs:
3912 * @node: the element node
3913 * @uri: the uri
3914 * @name: the name of the attribute
3915 *
3916 * Seeks an attribute with a local name of @name and
3917 * a namespace URI of @uri.
3918 *
3919 * Returns the attribute or NULL if not present.
3920 */
3921static xmlAttrPtr
3922xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3923{
3924 xmlAttrPtr prop;
3925
3926 if ((node == NULL) || (name == NULL))
3927 return(NULL);
3928 prop = node->properties;
3929 while (prop != NULL) {
3930 if ((prop->ns != NULL) &&
3931 xmlStrEqual(prop->name, BAD_CAST name) &&
3932 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003933 return(prop);
3934 prop = prop->next;
3935 }
3936 return (NULL);
3937}
3938
3939static const xmlChar *
3940xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3941{
3942 xmlChar *val;
3943 const xmlChar *ret;
3944
3945 val = xmlNodeGetContent(node);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003946 if (val == NULL)
3947 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003948 ret = xmlDictLookup(ctxt->dict, val, -1);
3949 xmlFree(val);
3950 return(ret);
3951}
3952
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003953/**
3954 * xmlSchemaGetProp:
3955 * @ctxt: the parser context
3956 * @node: the node
3957 * @name: the property name
3958 *
3959 * Read a attribute value and internalize the string
3960 *
3961 * Returns the string or NULL if not present.
3962 */
3963static const xmlChar *
3964xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3965 const char *name)
3966{
3967 xmlChar *val;
3968 const xmlChar *ret;
3969
3970 val = xmlGetProp(node, BAD_CAST name);
3971 if (val == NULL)
3972 return(NULL);
3973 ret = xmlDictLookup(ctxt->dict, val, -1);
3974 xmlFree(val);
3975 return(ret);
3976}
3977
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003978/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003979 * *
3980 * Parsing functions *
3981 * *
3982 ************************************************************************/
3983
3984/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003985 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003986 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003987 * @name: the element name
3988 * @ns: the element namespace
3989 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003990 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003991 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003992 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003993 */
3994static xmlSchemaElementPtr
3995xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003996 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003997{
3998 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003999
4000 if ((name == NULL) || (schema == NULL))
4001 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004002
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004003 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004004 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004005 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004006 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004007 } else
4008 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00004009 /*
4010 * This one was removed, since top level element declarations have
4011 * the target namespace specified in targetNamespace of the <schema>
4012 * information element, even if elementFormDefault is "unqualified".
4013 */
4014
4015 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004016 if (xmlStrEqual(namespace, schema->targetNamespace))
4017 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
4018 else
4019 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004020 if ((ret != NULL) &&
4021 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004022 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004023 }
William M. Bracke7091952004-05-11 15:09:58 +00004024 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004025
William M. Brack2f2a6632004-08-20 23:09:47 +00004026 /*
4027 * Removed since imported components will be hold by the main schema only.
4028 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004029 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004030 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004031 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004032 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004033 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00004034 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00004035 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
4036 return (ret);
4037 } else
4038 ret = NULL;
4039 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004040 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004041#ifdef DEBUG
4042 if (ret == NULL) {
4043 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004044 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004045 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004046 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004047 namespace);
4048 }
4049#endif
4050 return (ret);
4051}
4052
4053/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004054 * xmlSchemaGetType:
4055 * @schema: the schemas context
4056 * @name: the type name
4057 * @ns: the type namespace
4058 *
4059 * Lookup a type in the schemas or the predefined types
4060 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004061 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004062 */
4063static xmlSchemaTypePtr
4064xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 const xmlChar * namespace)
4066{
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 xmlSchemaTypePtr ret;
4068
4069 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004071 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004072 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004073 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004074 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004075 }
4076 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00004077 if (ret != NULL)
4078 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004079 /*
4080 * Removed, since the imported components will be grafted on the
4081 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004083 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004084 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004085 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004086 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004087 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004088 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4089 return (ret);
4090 } else
4091 ret = NULL;
4092 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004093 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004094#ifdef DEBUG
4095 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004096 if (namespace == NULL)
4097 fprintf(stderr, "Unable to lookup type %s", name);
4098 else
4099 fprintf(stderr, "Unable to lookup type %s:%s", name,
4100 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004101 }
4102#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004103 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004104}
4105
Daniel Veillard3646d642004-06-02 19:19:14 +00004106/**
4107 * xmlSchemaGetAttribute:
4108 * @schema: the context of the schema
4109 * @name: the name of the attribute
4110 * @ns: the target namespace of the attribute
4111 *
4112 * Lookup a an attribute in the schema or imported schemas
4113 *
4114 * Returns the attribute declaration or NULL if not found.
4115 */
4116static xmlSchemaAttributePtr
4117xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
4118 const xmlChar * namespace)
4119{
4120 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004121
4122 if ((name == NULL) || (schema == NULL))
4123 return (NULL);
4124
4125
4126 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4127 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
4128 return (ret);
4129 else
4130 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004131 /*
4132 * Removed, since imported components will be hold by the main schema only.
4133 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004134 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004135 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004136 else
4137 import = xmlHashLookup(schema->schemasImports, namespace);
4138 if (import != NULL) {
4139 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
4140 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4141 return (ret);
4142 } else
4143 ret = NULL;
4144 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004146#ifdef DEBUG
4147 if (ret == NULL) {
4148 if (namespace == NULL)
4149 fprintf(stderr, "Unable to lookup attribute %s", name);
4150 else
4151 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4152 namespace);
4153 }
4154#endif
4155 return (ret);
4156}
4157
4158/**
4159 * xmlSchemaGetAttributeGroup:
4160 * @schema: the context of the schema
4161 * @name: the name of the attribute group
4162 * @ns: the target namespace of the attribute group
4163 *
4164 * Lookup a an attribute group in the schema or imported schemas
4165 *
4166 * Returns the attribute group definition or NULL if not found.
4167 */
4168static xmlSchemaAttributeGroupPtr
4169xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4170 const xmlChar * namespace)
4171{
4172 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004173
4174 if ((name == NULL) || (schema == NULL))
4175 return (NULL);
4176
4177
4178 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4179 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4180 return (ret);
4181 else
4182 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004183 /*
4184 * Removed since imported components will be hold by the main schema only.
4185 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004186 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004187 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004188 else
4189 import = xmlHashLookup(schema->schemasImports, namespace);
4190 if (import != NULL) {
4191 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4192 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4193 return (ret);
4194 else
4195 ret = NULL;
4196 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004197 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004198#ifdef DEBUG
4199 if (ret == NULL) {
4200 if (namespace == NULL)
4201 fprintf(stderr, "Unable to lookup attribute group %s", name);
4202 else
4203 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4204 namespace);
4205 }
4206#endif
4207 return (ret);
4208}
4209
4210/**
4211 * xmlSchemaGetGroup:
4212 * @schema: the context of the schema
4213 * @name: the name of the group
4214 * @ns: the target namespace of the group
4215 *
4216 * Lookup a group in the schema or imported schemas
4217 *
4218 * Returns the group definition or NULL if not found.
4219 */
4220static xmlSchemaTypePtr
4221xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4222 const xmlChar * namespace)
4223{
4224 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004225
4226 if ((name == NULL) || (schema == NULL))
4227 return (NULL);
4228
Daniel Veillard3646d642004-06-02 19:19:14 +00004229 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004230 /*
4231 * Removed since imported components will be hold by the main schema only.
4232 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004233 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004234 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004235 else
4236 import = xmlHashLookup(schema->schemasImports, namespace);
4237 if (import != NULL) {
4238 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4239 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4240 return (ret);
4241 else
4242 ret = NULL;
4243 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004244 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004245#ifdef DEBUG
4246 if (ret == NULL) {
4247 if (namespace == NULL)
4248 fprintf(stderr, "Unable to lookup group %s", name);
4249 else
4250 fprintf(stderr, "Unable to lookup group %s:%s", name,
4251 namespace);
4252 }
4253#endif
4254 return (ret);
4255}
4256
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004257/**
4258 * xmlSchemaGetNamedComponent:
4259 * @schema: the schema
4260 * @name: the name of the group
4261 * @ns: the target namespace of the group
4262 *
4263 * Lookup a group in the schema or imported schemas
4264 *
4265 * Returns the group definition or NULL if not found.
4266 */
4267static xmlSchemaTreeItemPtr
4268xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4269 xmlSchemaTypeType itemType,
4270 const xmlChar *name,
4271 const xmlChar *targetNs)
4272{
4273 switch (itemType) {
4274 case XML_SCHEMA_TYPE_GROUP:
4275 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4276 name, targetNs));
4277 case XML_SCHEMA_TYPE_ELEMENT:
4278 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4279 name, targetNs));
4280 default:
4281 return (NULL);
4282 }
4283}
4284
Daniel Veillard4255d502002-04-16 15:50:10 +00004285/************************************************************************
4286 * *
4287 * Parsing functions *
4288 * *
4289 ************************************************************************/
4290
4291#define IS_BLANK_NODE(n) \
4292 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
4293
4294/**
4295 * xmlSchemaIsBlank:
4296 * @str: a string
4297 *
4298 * Check if a string is ignorable
4299 *
4300 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4301 */
4302static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004303xmlSchemaIsBlank(xmlChar * str)
4304{
Daniel Veillard4255d502002-04-16 15:50:10 +00004305 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00004308 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 return (0);
4310 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004311 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004313}
4314
4315/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004316 * xmlSchemaAddAssembledItem:
4317 * @ctxt: a schema parser context
4318 * @schema: the schema being built
4319 * @item: the item
4320 *
4321 * Add a item to the schema's list of current items.
4322 * This is used if the schema was already constructed and
4323 * new schemata need to be added to it.
4324 * *WARNING* this interface is highly subject to change.
4325 *
4326 * Returns 0 if suceeds and -1 if an internal error occurs.
4327 */
4328static int
4329xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4330 xmlSchemaTypePtr item)
4331{
4332 static int growSize = 100;
4333 xmlSchemaAssemblePtr ass;
4334
4335 ass = ctxt->assemble;
4336 if (ass->sizeItems < 0) {
4337 /* If disabled. */
4338 return (0);
4339 }
4340 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004341 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004342 if (ass->items == NULL) {
4343 xmlSchemaPErrMemory(ctxt,
4344 "allocating new item buffer", NULL);
4345 return (-1);
4346 }
4347 ass->sizeItems = growSize;
4348 } else if (ass->sizeItems <= ass->nbItems) {
4349 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004350 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004351 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4352 if (ass->items == NULL) {
4353 xmlSchemaPErrMemory(ctxt,
4354 "growing item buffer", NULL);
4355 ass->sizeItems = 0;
4356 return (-1);
4357 }
4358 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004359 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004360 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4361 return (0);
4362}
4363
4364/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004365 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004366 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 * @schema: the schema being built
4368 * @name: the item name
4369 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004370 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 * *WARNING* this interface is highly subject to change
4372 *
4373 * Returns the new struture or NULL in case of error
4374 */
4375static xmlSchemaNotationPtr
4376xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004377 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004378{
4379 xmlSchemaNotationPtr ret = NULL;
4380 int val;
4381
4382 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4383 return (NULL);
4384
4385 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004386 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 if (schema->notaDecl == NULL)
4388 return (NULL);
4389
4390 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4391 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004392 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004393 return (NULL);
4394 }
4395 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004396 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4398 ret);
4399 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004400 /*
4401 * TODO: This should never happen, since a unique name will be computed.
4402 * If it fails, then an other internal error must have occured.
4403 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4405 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004406 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004407 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 xmlFree(ret);
4409 return (NULL);
4410 }
4411 return (ret);
4412}
4413
4414
4415/**
4416 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004417 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 * @schema: the schema being built
4419 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004420 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004421 *
4422 * Add an XML schema Attrribute declaration
4423 * *WARNING* this interface is highly subject to change
4424 *
4425 * Returns the new struture or NULL in case of error
4426 */
4427static xmlSchemaAttributePtr
4428xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004429 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004430 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004431{
4432 xmlSchemaAttributePtr ret = NULL;
4433 int val;
4434
4435 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4436 return (NULL);
4437
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004438#ifdef DEBUG
4439 fprintf(stderr, "Adding attribute %s\n", name);
4440 if (namespace != NULL)
4441 fprintf(stderr, " target namespace %s\n", namespace);
4442#endif
4443
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004445 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 if (schema->attrDecl == NULL)
4447 return (NULL);
4448
4449 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4450 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004451 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 return (NULL);
4453 }
4454 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004455 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004456 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004457 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004458 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004459 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004460 if (topLevel) {
4461 xmlSchemaPCustomErr(ctxt,
4462 XML_SCHEMAP_REDEFINED_ATTR,
4463 NULL, NULL, node,
4464 "A global attribute declaration with the name '%s' does "
4465 "already exist", name);
4466 xmlFree(ret);
4467 return (NULL);
4468 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004469 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004470 /*
4471 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4472 * in the scenario:
4473 * 1. multiple top-level complex types have different target
4474 * namespaces but have the SAME NAME; this can happen if
4475 * schemata are imported
4476 * 2. those complex types contain attributes with an equal name
4477 * 3. those attributes are in no namespace
4478 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004479 */
4480 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004481 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004482 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004483
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004484 if (val != 0) {
4485 xmlSchemaPCustomErr(ctxt,
4486 XML_SCHEMAP_INTERNAL,
4487 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004488 "Internal error: xmlSchemaAddAttribute, "
4489 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004490 "could not be added to the hash.", name);
4491 xmlFree(ret);
4492 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004493 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004494 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004495 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004496 if (ctxt->assemble != NULL)
4497 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (ret);
4499}
4500
4501/**
4502 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004503 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 * @schema: the schema being built
4505 * @name: the item name
4506 *
4507 * Add an XML schema Attrribute Group declaration
4508 *
4509 * Returns the new struture or NULL in case of error
4510 */
4511static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004512xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004513 xmlSchemaPtr schema, const xmlChar * name,
4514 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004515{
4516 xmlSchemaAttributeGroupPtr ret = NULL;
4517 int val;
4518
4519 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4520 return (NULL);
4521
4522 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004523 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004524 if (schema->attrgrpDecl == NULL)
4525 return (NULL);
4526
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004527 ret =
4528 (xmlSchemaAttributeGroupPtr)
4529 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004530 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004531 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004532 return (NULL);
4533 }
4534 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004535 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004536 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004537 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004538 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004539 xmlSchemaPCustomErr(ctxt,
4540 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4541 NULL, NULL, node,
4542 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 xmlFree(ret);
4544 return (NULL);
4545 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004546 if (ctxt->assemble != NULL)
4547 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004548 return (ret);
4549}
4550
4551/**
4552 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004553 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004554 * @schema: the schema being built
4555 * @name: the type name
4556 * @namespace: the type namespace
4557 *
4558 * Add an XML schema Element declaration
4559 * *WARNING* this interface is highly subject to change
4560 *
4561 * Returns the new struture or NULL in case of error
4562 */
4563static xmlSchemaElementPtr
4564xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004565 const xmlChar * name, const xmlChar * namespace,
4566 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004567{
4568 xmlSchemaElementPtr ret = NULL;
4569 int val;
4570
4571 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4572 return (NULL);
4573
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004574#ifdef DEBUG
4575 fprintf(stderr, "Adding element %s\n", name);
4576 if (namespace != NULL)
4577 fprintf(stderr, " target namespace %s\n", namespace);
4578#endif
4579
Daniel Veillard4255d502002-04-16 15:50:10 +00004580 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004581 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004582 if (schema->elemDecl == NULL)
4583 return (NULL);
4584
4585 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4586 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004587 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004588 return (NULL);
4589 }
4590 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004591 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004593 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004594 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004595 if (topLevel) {
4596 xmlSchemaPCustomErr(ctxt,
4597 XML_SCHEMAP_REDEFINED_ELEMENT,
4598 NULL, NULL, node,
4599 "A global element declaration with the name '%s' does "
4600 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004601 xmlFree(ret);
4602 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004603 } else {
4604 char buf[30];
4605
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004606 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004607 val = xmlHashAddEntry3(schema->elemDecl, name,
4608 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004609 if (val != 0) {
4610 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004611 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004612 NULL, NULL, node,
4613 "Internal error: xmlSchemaAddElement, "
4614 "a dublicate element declaration with the name '%s' "
4615 "could not be added to the hash.", name);
4616 xmlFree(ret);
4617 return (NULL);
4618 }
4619 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004620
Daniel Veillard4255d502002-04-16 15:50:10 +00004621 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004622 if (ctxt->assemble != NULL)
4623 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 return (ret);
4625}
4626
4627/**
4628 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004629 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 * @schema: the schema being built
4631 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004632 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004633 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004634 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004635 * *WARNING* this interface is highly subject to change
4636 *
4637 * Returns the new struture or NULL in case of error
4638 */
4639static xmlSchemaTypePtr
4640xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004641 const xmlChar * name, const xmlChar * namespace,
4642 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004643{
4644 xmlSchemaTypePtr ret = NULL;
4645 int val;
4646
4647 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4648 return (NULL);
4649
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004650#ifdef DEBUG
4651 fprintf(stderr, "Adding type %s\n", name);
4652 if (namespace != NULL)
4653 fprintf(stderr, " target namespace %s\n", namespace);
4654#endif
4655
Daniel Veillard4255d502002-04-16 15:50:10 +00004656 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004657 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004658 if (schema->typeDecl == NULL)
4659 return (NULL);
4660
4661 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4662 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004663 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004664 return (NULL);
4665 }
4666 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004667 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004668 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004669 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004670 if (val != 0) {
4671 if (ctxt->includes == 0) {
4672 xmlSchemaPCustomErr(ctxt,
4673 XML_SCHEMAP_REDEFINED_TYPE,
4674 NULL, NULL, node,
4675 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004676 xmlFree(ret);
4677 return (NULL);
4678 } else {
4679 xmlSchemaTypePtr prev;
4680
4681 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4682 if (prev == NULL) {
4683 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004684 XML_ERR_INTERNAL_ERROR,
4685 "Internal error: xmlSchemaAddType, on type "
4686 "'%s'.\n",
4687 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004688 xmlFree(ret);
4689 return (NULL);
4690 }
4691 ret->redef = prev->redef;
4692 prev->redef = ret;
4693 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004694 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004695 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004696 ret->minOccurs = 1;
4697 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004698 ret->attributeUses = NULL;
4699 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004700 if (ctxt->assemble != NULL)
4701 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004702 return (ret);
4703}
4704
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004705static xmlSchemaQNameRefPtr
4706xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4707 xmlSchemaTypeType refType,
4708 const xmlChar *refName,
4709 const xmlChar *refNs)
4710{
4711 xmlSchemaQNameRefPtr ret;
4712
4713 ret = (xmlSchemaQNameRefPtr)
4714 xmlMalloc(sizeof(xmlSchemaQNameRef));
4715 if (ret == NULL) {
4716 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4717 NULL);
4718 return (NULL);
4719 }
4720 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4721 ret->name = refName;
4722 ret->targetNamespace = refNs;
4723 ret->item = NULL;
4724 ret->itemType = refType;
4725 /*
4726 * Store the reference item in the schema.
4727 */
4728 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4729 return (ret);
4730}
4731
4732/**
4733 * xmlSchemaAddModelGroup:
4734 * @ctxt: a schema parser context
4735 * @schema: the schema being built
4736 * @type: the "compositor" type of the model group
4737 * @container: the internal component name
4738 * @node: the node in the schema doc
4739 *
4740 * Adds a schema model group
4741 * *WARNING* this interface is highly subject to change
4742 *
4743 * Returns the new struture or NULL in case of error
4744 */
4745static xmlSchemaModelGroupPtr
4746xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4747 xmlSchemaTypeType type, const xmlChar **container,
4748 xmlNodePtr node)
4749{
4750 xmlSchemaModelGroupPtr ret = NULL;
4751 xmlChar buf[30];
4752
4753 if ((ctxt == NULL) || (schema == NULL))
4754 return (NULL);
4755
4756#ifdef DEBUG
4757 fprintf(stderr, "Adding model group component\n");
4758#endif
4759 ret = (xmlSchemaModelGroupPtr)
4760 xmlMalloc(sizeof(xmlSchemaModelGroup));
4761 if (ret == NULL) {
4762 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4763 NULL);
4764 return (NULL);
4765 }
4766 ret->type = type;
4767 ret->annot = NULL;
4768 ret->node = node;
4769 ret->children = NULL;
4770 ret->next = NULL;
4771 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4772 if (container != NULL)
4773 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4774 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
4775 if (container != NULL)
4776 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4777 } else {
4778 if (container != NULL)
4779 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4780 }
4781 if (container != NULL)
4782 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4783 /*
4784 * Add to volatile items.
4785 * TODO: this should be changed someday.
4786 */
4787 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4788 xmlFree(ret);
4789 return (NULL);
4790 }
4791 return (ret);
4792}
4793
4794
4795/**
4796 * xmlSchemaAddParticle:
4797 * @ctxt: a schema parser context
4798 * @schema: the schema being built
4799 * @node: the corresponding node in the schema doc
4800 * @min: the minOccurs
4801 * @max: the maxOccurs
4802 *
4803 * Adds an XML schema particle component.
4804 * *WARNING* this interface is highly subject to change
4805 *
4806 * Returns the new struture or NULL in case of error
4807 */
4808static xmlSchemaParticlePtr
4809xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4810 xmlNodePtr node, int min, int max)
4811{
4812 xmlSchemaParticlePtr ret = NULL;
4813 if ((ctxt == NULL) || (schema == NULL))
4814 return (NULL);
4815
4816#ifdef DEBUG
4817 fprintf(stderr, "Adding particle component\n");
4818#endif
4819 ret = (xmlSchemaParticlePtr)
4820 xmlMalloc(sizeof(xmlSchemaParticle));
4821 if (ret == NULL) {
4822 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4823 NULL);
4824 return (NULL);
4825 }
4826 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4827 ret->annot = NULL;
4828 ret->node = node;
4829 ret->minOccurs = min;
4830 ret->maxOccurs = max;
4831 ret->next = NULL;
4832 ret->children = NULL;
4833
4834 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4835 xmlFree(ret);
4836 return (NULL);
4837 }
4838 return (ret);
4839}
4840
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004841/**
4842 * xmlSchemaAddGroup:
4843 * @ctxt: a schema validation context
4844 * @schema: the schema being built
4845 * @name: the group name
4846 *
4847 * Add an XML schema Group definition
4848 *
4849 * Returns the new struture or NULL in case of error
4850 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004851static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004852xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004853 const xmlChar *name, const xmlChar *namespaceName,
4854 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004855{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004856 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004857 int val;
4858
4859 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4860 return (NULL);
4861
4862 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004863 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004864 if (schema->groupDecl == NULL)
4865 return (NULL);
4866
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004867 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004868 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004869 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004870 return (NULL);
4871 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004872 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004873 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004874 ret->type = XML_SCHEMA_TYPE_GROUP;
4875 ret->node = node;
4876 ret->targetNamespace = namespaceName;
4877 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004878 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004879 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004880 XML_SCHEMAP_REDEFINED_GROUP,
4881 NULL, NULL, node,
4882 "A global model group definition with the name '%s' does already "
4883 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004884 xmlFree(ret);
4885 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004886 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004887 if (ctxt->assemble != NULL)
4888 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004889 return (ret);
4890}
4891
Daniel Veillard3646d642004-06-02 19:19:14 +00004892/**
4893 * xmlSchemaNewWildcardNs:
4894 * @ctxt: a schema validation context
4895 *
4896 * Creates a new wildcard namespace constraint.
4897 *
4898 * Returns the new struture or NULL in case of error
4899 */
4900static xmlSchemaWildcardNsPtr
4901xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4902{
4903 xmlSchemaWildcardNsPtr ret;
4904
4905 ret = (xmlSchemaWildcardNsPtr)
4906 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4907 if (ret == NULL) {
4908 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4909 return (NULL);
4910 }
4911 ret->value = NULL;
4912 ret->next = NULL;
4913 return (ret);
4914}
4915
4916/**
4917 * xmlSchemaAddWildcard:
4918 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004919 * @schema: a schema
4920 *
4921 * Adds a wildcard.
4922 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004923 *
4924 * Returns the new struture or NULL in case of error
4925 */
4926static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004927xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4928 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004929{
4930 xmlSchemaWildcardPtr ret = NULL;
4931
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004932 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004933 return (NULL);
4934
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004935#ifdef DEBUG
4936 fprintf(stderr, "Adding wildcard component\n");
4937#endif
4938
Daniel Veillard3646d642004-06-02 19:19:14 +00004939 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4940 if (ret == NULL) {
4941 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4942 return (NULL);
4943 }
4944 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004945 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004946 ret->minOccurs = 1;
4947 ret->maxOccurs = 1;
4948
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004949 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4950 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4951 "Failed to add a wildcard component to the list", NULL);
4952 xmlFree(ret);
4953 return (NULL);
4954 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004955 return (ret);
4956}
4957
Daniel Veillard4255d502002-04-16 15:50:10 +00004958/************************************************************************
4959 * *
4960 * Utilities for parsing *
4961 * *
4962 ************************************************************************/
4963
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004964#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004965/**
4966 * xmlGetQNameProp:
4967 * @ctxt: a schema validation context
4968 * @node: a subtree containing XML Schema informations
4969 * @name: the attribute name
4970 * @namespace: the result namespace if any
4971 *
4972 * Extract a QName Attribute value
4973 *
4974 * Returns the NCName or NULL if not found, and also update @namespace
4975 * with the namespace URI
4976 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004977static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004978xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004979 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004980{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004981 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004983 const xmlChar *ret, *prefix;
4984 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004985 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004986
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004987 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004988 attr = xmlSchemaGetPropNode(node, name);
4989 if (attr == NULL)
4990 return (NULL);
4991 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004992
Daniel Veillard4255d502002-04-16 15:50:10 +00004993 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004994 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004995
Daniel Veillardba0153a2004-04-01 10:42:31 +00004996 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004997 ns = xmlSearchNs(node->doc, node, 0);
4998 if (ns) {
4999 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5000 return (val);
5001 }
5002 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005003 ret = xmlSplitQName3(val, &len);
5004 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005005 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005006 }
5007 ret = xmlDictLookup(ctxt->dict, ret, -1);
5008 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00005009
5010 ns = xmlSearchNs(node->doc, node, prefix);
5011 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005012 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
5013 NULL, NULL, (xmlNodePtr) attr,
5014 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005015 "The QName value '%s' has no corresponding namespace "
5016 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005017 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005018 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005019 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005020 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005021}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005022#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005023
5024/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005025 * xmlSchemaPValAttrNodeQNameValue:
5026 * @ctxt: a schema parser context
5027 * @schema: the schema context
5028 * @ownerDes: the designation of the parent element
5029 * @ownerItem: the parent as a schema object
5030 * @value: the QName value
5031 * @local: the resulting local part if found, the attribute value otherwise
5032 * @uri: the resulting namespace URI if found
5033 *
5034 * Extracts the local name and the URI of a QName value and validates it.
5035 * This one is intended to be used on attribute values that
5036 * should resolve to schema components.
5037 *
5038 * Returns 0, in case the QName is valid, a positive error code
5039 * if not valid and -1 if an internal error occurs.
5040 */
5041static int
5042xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5043 xmlSchemaPtr schema,
5044 xmlChar **ownerDes,
5045 xmlSchemaTypePtr ownerItem,
5046 xmlAttrPtr attr,
5047 const xmlChar *value,
5048 const xmlChar **uri,
5049 const xmlChar **prefix,
5050 const xmlChar **local)
5051{
5052 const xmlChar *pref;
5053 xmlNsPtr ns;
5054 int len, ret;
5055
5056 *uri = NULL;
5057 *local = NULL;
5058 if (prefix != 0)
5059 *prefix = NULL;
5060 ret = xmlValidateQName(value, 1);
5061 if (ret > 0) {
5062 xmlSchemaPSimpleTypeErr(ctxt,
5063 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5064 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005065 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5066 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 NULL, NULL, NULL);
5068 *local = value;
5069 return (ctxt->err);
5070 } else if (ret < 0)
5071 return (-1);
5072
5073 if (!strchr((char *) value, ':')) {
5074 ns = xmlSearchNs(attr->doc, attr->parent, 0);
5075 if (ns)
5076 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5077 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5078 /*
5079 * This one takes care of included schemas with no
5080 * target namespace.
5081 */
5082 *uri = schema->targetNamespace;
5083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005084 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005085 return (0);
5086 }
5087 /*
5088 * At this point xmlSplitQName3 has to return a local name.
5089 */
5090 *local = xmlSplitQName3(value, &len);
5091 *local = xmlDictLookup(ctxt->dict, *local, -1);
5092 pref = xmlDictLookup(ctxt->dict, value, len);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005093 if (prefix != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005094 *prefix = pref;
5095 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5096 if (ns == NULL) {
5097 xmlSchemaPSimpleTypeErr(ctxt,
5098 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5099 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005100 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
5101 "The QName value '%s' has no corresponding namespace "
5102 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005103 return (ctxt->err);
5104 } else {
5105 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5106 }
5107 return (0);
5108}
5109
5110/**
5111 * xmlSchemaPValAttrNodeQName:
5112 * @ctxt: a schema parser context
5113 * @schema: the schema context
5114 * @ownerDes: the designation of the owner element
5115 * @ownerItem: the owner as a schema object
5116 * @attr: the attribute node
5117 * @local: the resulting local part if found, the attribute value otherwise
5118 * @uri: the resulting namespace URI if found
5119 *
5120 * Extracts and validates the QName of an attribute value.
5121 * This one is intended to be used on attribute values that
5122 * should resolve to schema components.
5123 *
5124 * Returns 0, in case the QName is valid, a positive error code
5125 * if not valid and -1 if an internal error occurs.
5126 */
5127static int
5128xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5129 xmlSchemaPtr schema,
5130 xmlChar **ownerDes,
5131 xmlSchemaTypePtr ownerItem,
5132 xmlAttrPtr attr,
5133 const xmlChar **uri,
5134 const xmlChar **prefix,
5135 const xmlChar **local)
5136{
5137 const xmlChar *value;
5138
5139 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5140 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5141 ownerDes, ownerItem, attr, value, uri, prefix, local));
5142}
5143
5144/**
5145 * xmlSchemaPValAttrQName:
5146 * @ctxt: a schema parser context
5147 * @schema: the schema context
5148 * @ownerDes: the designation of the parent element
5149 * @ownerItem: the owner as a schema object
5150 * @ownerElem: the parent node of the attribute
5151 * @name: the name of the attribute
5152 * @local: the resulting local part if found, the attribute value otherwise
5153 * @uri: the resulting namespace URI if found
5154 *
5155 * Extracts and validates the QName of an attribute value.
5156 *
5157 * Returns 0, in case the QName is valid, a positive error code
5158 * if not valid and -1 if an internal error occurs.
5159 */
5160static int
5161xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5162 xmlSchemaPtr schema,
5163 xmlChar **ownerDes,
5164 xmlSchemaTypePtr ownerItem,
5165 xmlNodePtr ownerElem,
5166 const char *name,
5167 const xmlChar **uri,
5168 const xmlChar **prefix,
5169 const xmlChar **local)
5170{
5171 xmlAttrPtr attr;
5172
5173 attr = xmlSchemaGetPropNode(ownerElem, name);
5174 if (attr == NULL) {
5175 *local = NULL;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005176 if (prefix != NULL)
5177 *prefix = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005178 *uri = NULL;
5179 return (0);
5180 }
5181 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5182 ownerDes, ownerItem, attr, uri, prefix, local));
5183}
5184
5185/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005186 * xmlSchemaPValAttrID:
5187 * @ctxt: a schema parser context
5188 * @schema: the schema context
5189 * @ownerDes: the designation of the parent element
5190 * @ownerItem: the owner as a schema object
5191 * @ownerElem: the parent node of the attribute
5192 * @name: the name of the attribute
5193 *
5194 * Extracts and validates the ID of an attribute value.
5195 *
5196 * Returns 0, in case the ID is valid, a positive error code
5197 * if not valid and -1 if an internal error occurs.
5198 */
5199static int
5200xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5201 xmlChar **ownerDes,
5202 xmlSchemaTypePtr ownerItem,
5203 xmlNodePtr ownerElem,
5204 const xmlChar *name)
5205{
5206 int ret;
5207 xmlChar *value;
5208 xmlAttrPtr attr;
5209
5210 value = xmlGetNoNsProp(ownerElem, name);
5211 if (value == NULL)
5212 return (0);
5213
5214 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5215 if (attr == NULL)
5216 return (-1);
5217
5218 ret = xmlValidateNCName(BAD_CAST value, 1);
5219 if (ret == 0) {
5220 /*
5221 * NOTE: the IDness might have already be declared in the DTD
5222 */
5223 if (attr->atype != XML_ATTRIBUTE_ID) {
5224 xmlIDPtr res;
5225 xmlChar *strip;
5226
5227 /*
5228 * TODO: Use xmlSchemaStrip here; it's not exported at this
5229 * moment.
5230 */
5231 strip = xmlSchemaCollapseString(BAD_CAST value);
5232 if (strip != NULL)
5233 value = strip;
5234 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5235 if (res == NULL) {
5236 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5237 xmlSchemaPSimpleTypeErr(ctxt,
5238 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5239 ownerDes, ownerItem, (xmlNodePtr) attr,
5240 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005241 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005242 BAD_CAST value, NULL);
5243 } else
5244 attr->atype = XML_ATTRIBUTE_ID;
5245 if (strip != NULL)
5246 xmlFree(strip);
5247 }
5248 } else if (ret > 0) {
5249 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5250 xmlSchemaPSimpleTypeErr(ctxt,
5251 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5252 ownerDes, ownerItem, (xmlNodePtr) attr,
5253 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5254 NULL, BAD_CAST value, NULL, NULL, NULL);
5255 }
5256 xmlFree(value);
5257
5258 return (ret);
5259}
5260
5261/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005262 * xmlGetMaxOccurs:
5263 * @ctxt: a schema validation context
5264 * @node: a subtree containing XML Schema informations
5265 *
5266 * Get the maxOccurs property
5267 *
5268 * Returns the default if not found, or the value
5269 */
5270static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005271xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5272 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005273{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005274 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005276 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005277
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005278 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5279 if (attr == NULL)
5280 return (def);
5281 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005282
5283 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005284 if (max != UNBOUNDED) {
5285 xmlSchemaPSimpleTypeErr(ctxt,
5286 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5287 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5288 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5289 val, NULL, NULL, NULL);
5290 return (def);
5291 } else
5292 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005293 }
5294
5295 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005296 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005297 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005298 if (*cur == 0) {
5299 xmlSchemaPSimpleTypeErr(ctxt,
5300 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5301 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5302 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5303 val, NULL, NULL, NULL);
5304 return (def);
5305 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005307 ret = ret * 10 + (*cur - '0');
5308 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005309 }
William M. Brack76e95df2003-10-18 16:20:14 +00005310 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005311 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005312 /*
5313 * TODO: Restrict the maximal value to Integer.
5314 */
5315 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5316 xmlSchemaPSimpleTypeErr(ctxt,
5317 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5318 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5319 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5320 val, NULL, NULL, NULL);
5321 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005322 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005323 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005324}
5325
5326/**
5327 * xmlGetMinOccurs:
5328 * @ctxt: a schema validation context
5329 * @node: a subtree containing XML Schema informations
5330 *
5331 * Get the minOccurs property
5332 *
5333 * Returns the default if not found, or the value
5334 */
5335static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005336xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5337 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005338{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005339 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005340 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005341 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005342
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005343 attr = xmlSchemaGetPropNode(node, "minOccurs");
5344 if (attr == NULL)
5345 return (def);
5346 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005347 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005348 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005349 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005350 if (*cur == 0) {
5351 xmlSchemaPSimpleTypeErr(ctxt,
5352 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5353 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5354 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5355 val, NULL, NULL, NULL);
5356 return (def);
5357 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005358 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005359 ret = ret * 10 + (*cur - '0');
5360 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005361 }
William M. Brack76e95df2003-10-18 16:20:14 +00005362 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005363 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005364 /*
5365 * TODO: Restrict the maximal value to Integer.
5366 */
5367 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5368 xmlSchemaPSimpleTypeErr(ctxt,
5369 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5370 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5371 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5372 val, NULL, NULL, NULL);
5373 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005374 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005375 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005376}
5377
5378/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005379 * xmlSchemaPGetBoolNodeValue:
5380 * @ctxt: a schema validation context
5381 * @ownerDes: owner designation
5382 * @ownerItem: the owner as a schema item
5383 * @node: the node holding the value
5384 *
5385 * Converts a boolean string value into 1 or 0.
5386 *
5387 * Returns 0 or 1.
5388 */
5389static int
5390xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5391 xmlChar **ownerDes,
5392 xmlSchemaTypePtr ownerItem,
5393 xmlNodePtr node)
5394{
5395 xmlChar *value = NULL;
5396 int res = 0;
5397
5398 value = xmlNodeGetContent(node);
5399 /*
5400 * 3.2.2.1 Lexical representation
5401 * An instance of a datatype that is defined as ·boolean·
5402 * can have the following legal literals {true, false, 1, 0}.
5403 */
5404 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5405 res = 1;
5406 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5407 res = 0;
5408 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5409 res = 1;
5410 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
5411 res = 0;
5412 else {
5413 xmlSchemaPSimpleTypeErr(ctxt,
5414 XML_SCHEMAP_INVALID_BOOLEAN,
5415 ownerDes, ownerItem, node,
5416 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5417 "(1 | 0 | true | false)", BAD_CAST value,
5418 NULL, NULL, NULL);
5419 }
5420 if (value != NULL)
5421 xmlFree(value);
5422 return (res);
5423}
5424
5425/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005426 * xmlGetBooleanProp:
5427 * @ctxt: a schema validation context
5428 * @node: a subtree containing XML Schema informations
5429 * @name: the attribute name
5430 * @def: the default value
5431 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005432 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005433 *
5434 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 */
5437static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005438xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5439 xmlChar **ownerDes,
5440 xmlSchemaTypePtr ownerItem,
5441 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005442 const char *name, int def)
5443{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005444 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005445
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005446 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005447 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005448 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005449 /*
5450 * 3.2.2.1 Lexical representation
5451 * An instance of a datatype that is defined as ·boolean·
5452 * can have the following legal literals {true, false, 1, 0}.
5453 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005454 if (xmlStrEqual(val, BAD_CAST "true"))
5455 def = 1;
5456 else if (xmlStrEqual(val, BAD_CAST "false"))
5457 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005458 else if (xmlStrEqual(val, BAD_CAST "1"))
5459 def = 1;
5460 else if (xmlStrEqual(val, BAD_CAST "0"))
5461 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005462 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005463 xmlSchemaPSimpleTypeErr(ctxt,
5464 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005465 ownerDes, ownerItem,
5466 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00005467 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5468 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005469 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005470 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005471}
5472
5473/************************************************************************
5474 * *
5475 * Shema extraction from an Infoset *
5476 * *
5477 ************************************************************************/
5478static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5479 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005480 xmlNodePtr node,
5481 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005482static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5483 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005484 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005485 xmlNodePtr node,
5486 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005487static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5488 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005489 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005490 xmlNodePtr node,
5491 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005492static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5493 ctxt,
5494 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005495 xmlNodePtr node,
5496 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005497static xmlSchemaAttributeGroupPtr
5498xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005499 xmlSchemaPtr schema, xmlNodePtr node,
5500 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005501static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5502 xmlSchemaPtr schema,
5503 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005504static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005505xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5506 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005507
5508/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005509 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005510 *
5511 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005512 * @ownerDes: the designation of the parent element
5513 * @ownerItem: the schema object owner if existent
5514 * @attr: the schema attribute node being validated
5515 * @value: the value
5516 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005517 *
5518 * Validates a value against the given built-in type.
5519 * This one is intended to be used internally for validation
5520 * of schema attribute values during parsing of the schema.
5521 *
5522 * Returns 0 if the value is valid, a positive error code
5523 * number otherwise and -1 in case of an internal or API error.
5524 */
5525static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005526xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
5527 xmlChar **ownerDes,
5528 xmlSchemaTypePtr ownerItem,
5529 xmlAttrPtr attr,
5530 const xmlChar *value,
5531 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005532{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005533
Daniel Veillardc0826a72004-08-10 14:17:33 +00005534 int ret = 0;
5535
5536 /*
5537 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5538 * one is really meant to be used internally, so better not.
5539 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005540 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005541 return (-1);
5542 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5543 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005544 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005545 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 "type '%s' is not a built-in type.\n",
5547 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005548 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005549 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005550 switch (type->builtInType) {
5551 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005552 case XML_SCHEMAS_QNAME:
5553 case XML_SCHEMAS_ANYURI:
5554 case XML_SCHEMAS_TOKEN:
5555 case XML_SCHEMAS_LANGUAGE:
5556 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
5557 break;
5558
5559 /*
5560 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005561 ret = xmlValidateNCName(value, 1);
5562 break;
5563 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00005564 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005565 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005566 "Internal error: xmlSchemaPvalueAttrNode, use "
5567 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
5568 "for extracting QName valueues instead.\n",
5569 NULL, NULL);
5570 return (-1);
5571 case XML_SCHEMAS_ANYURI:
5572 if (value != NULL) {
5573 xmlURIPtr uri = xmlParseURI((const char *) value);
5574 if (uri == NULL)
5575 ret = 1;
5576 else
5577 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005578 }
5579 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005580 case XML_SCHEMAS_TOKEN: {
5581 const xmlChar *cur = value;
5582
5583 if (IS_BLANK_CH(*cur)) {
5584 ret = 1;
5585 } else while (*cur != 0) {
5586 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
5587 ret = 1;
5588 break;
5589 } else if (*cur == ' ') {
5590 cur++;
5591 if ((*cur == 0) || (*cur == ' ')) {
5592 ret = 1;
5593 break;
5594 }
5595 } else {
5596 cur++;
5597 }
5598 }
5599 }
5600 break;
5601 case XML_SCHEMAS_LANGUAGE:
5602 if (xmlCheckLanguageID(value) != 1)
5603 ret = 1;
5604 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005605 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005606 default: {
5607 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005608 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005609 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005610 "valueidation using the type '%s' is not implemented "
5611 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00005612 type->name, NULL);
5613 return (-1);
5614 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005615 }
5616 /*
5617 * TODO: Should we use the S4S error codes instead?
5618 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005619 if (ret < 0) {
5620 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
5621 XML_SCHEMAP_INTERNAL,
5622 "Internal error: xmlSchemaPValAttrNodeValue, "
5623 "failed to validate a schema attribute value.\n",
5624 NULL, NULL);
5625 return (-1);
5626 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005627 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
5628 xmlSchemaPSimpleTypeErr(ctxt,
5629 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
5630 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005631 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005632 NULL, NULL, NULL);
5633 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
5634 } else {
5635 xmlSchemaPSimpleTypeErr(ctxt,
5636 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
5637 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005638 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005639 NULL, NULL, NULL);
5640 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
5641 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005642 }
5643 return (ret);
5644}
5645
5646/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005647 * xmlSchemaPValAttrNode:
5648 *
5649 * @ctxt: a schema parser context
5650 * @ownerDes: the designation of the parent element
5651 * @ownerItem: the schema object owner if existent
5652 * @attr: the schema attribute node being validated
5653 * @type: the built-in type to be validated against
5654 * @value: the resulting value if any
5655 *
5656 * Extracts and validates a value against the given built-in type.
5657 * This one is intended to be used internally for validation
5658 * of schema attribute values during parsing of the schema.
5659 *
5660 * Returns 0 if the value is valid, a positive error code
5661 * number otherwise and -1 in case of an internal or API error.
5662 */
5663static int
5664xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5665 xmlChar **ownerDes,
5666 xmlSchemaTypePtr ownerItem,
5667 xmlAttrPtr attr,
5668 xmlSchemaTypePtr type,
5669 const xmlChar **value)
5670{
5671 const xmlChar *val;
5672
5673 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
5674 return (-1);
5675
5676 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5677 if (value != NULL)
5678 *value = val;
5679
5680 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
5681 val, type));
5682}
5683
5684/**
5685 * xmlSchemaPValAttr:
5686 *
5687 * @ctxt: a schema parser context
5688 * @node: the element node of the attribute
5689 * @ownerDes: the designation of the parent element
5690 * @ownerItem: the schema object owner if existent
5691 * @ownerElem: the owner element node
5692 * @name: the name of the schema attribute node
5693 * @type: the built-in type to be validated against
5694 * @value: the resulting value if any
5695 *
5696 * Extracts and validates a value against the given built-in type.
5697 * This one is intended to be used internally for validation
5698 * of schema attribute values during parsing of the schema.
5699 *
5700 * Returns 0 if the value is valid, a positive error code
5701 * number otherwise and -1 in case of an internal or API error.
5702 */
5703static int
5704xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
5705 xmlChar **ownerDes,
5706 xmlSchemaTypePtr ownerItem,
5707 xmlNodePtr ownerElem,
5708 const char *name,
5709 xmlSchemaTypePtr type,
5710 const xmlChar **value)
5711{
5712 xmlAttrPtr attr;
5713
5714 if ((ctxt == NULL) || (type == NULL)) {
5715 if (value != NULL)
5716 *value = NULL;
5717 return (-1);
5718 }
5719 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5720 if (value != NULL)
5721 *value = NULL;
5722 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005723 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 "Internal error: xmlSchemaPValAttr, the given "
5725 "type '%s' is not a built-in type.\n",
5726 type->name, NULL);
5727 return (-1);
5728 }
5729 attr = xmlSchemaGetPropNode(ownerElem, name);
5730 if (attr == NULL) {
5731 if (value != NULL)
5732 *value = NULL;
5733 return (0);
5734 }
5735 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
5736 type, value));
5737}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005738
5739static int
5740xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5741 xmlSchemaPtr schema,
5742 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005743 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005744 const xmlChar *namespaceName)
5745{
5746 if (xmlStrEqual(schema->targetNamespace, namespaceName))
5747 return (1);
5748 if (pctxt->localImports != NULL) {
5749 int i;
5750 for (i = 0; i < pctxt->nbLocalImports; i++)
5751 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5752 return (1);
5753 }
5754 if (namespaceName == NULL)
5755 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005756 NULL, (xmlSchemaTypePtr) item, node,
5757 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005758 "namespace are not valid, since not indicated by an import "
5759 "statement", NULL);
5760 else
5761 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005762 NULL, (xmlSchemaTypePtr) item, node,
5763 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005764 "namespace '%s' are not valid, since not indicated by an import "
5765 "statement", namespaceName);
5766 return (0);
5767}
5768
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 * xmlSchemaParseAttrDecls:
5771 * @ctxt: a schema validation context
5772 * @schema: the schema being built
5773 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005774 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005775 *
5776 * parse a XML schema attrDecls declaration corresponding to
5777 * <!ENTITY % attrDecls
5778 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5779 */
5780static xmlNodePtr
5781xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5782 xmlNodePtr child, xmlSchemaTypePtr type)
5783{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005784 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005785
Daniel Veillard4255d502002-04-16 15:50:10 +00005786 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005787 (IS_SCHEMA(child, "attributeGroup"))) {
5788 attr = NULL;
5789 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005790 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005791 } else if (IS_SCHEMA(child, "attributeGroup")) {
5792 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005793 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005794 }
5795 if (attr != NULL) {
5796 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005797 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5798 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5799 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005800 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005801 lastattr = attr;
5802 } else {
5803 lastattr->next = attr;
5804 lastattr = attr;
5805 }
5806 }
5807 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005808 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005809 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005810}
5811
5812/**
5813 * xmlSchemaParseAnnotation:
5814 * @ctxt: a schema validation context
5815 * @schema: the schema being built
5816 * @node: a subtree containing XML Schema informations
5817 *
5818 * parse a XML schema Attrribute declaration
5819 * *WARNING* this interface is highly subject to change
5820 *
William M. Bracke7091952004-05-11 15:09:58 +00005821 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005822 * 1 in case of success.
5823 */
5824static xmlSchemaAnnotPtr
5825xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5826 xmlNodePtr node)
5827{
5828 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005829 xmlNodePtr child = NULL;
5830 xmlAttrPtr attr;
5831 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005832
Daniel Veillardc0826a72004-08-10 14:17:33 +00005833 /*
5834 * INFO: S4S completed.
5835 */
5836 /*
5837 * id = ID
5838 * {any attributes with non-schema namespace . . .}>
5839 * Content: (appinfo | documentation)*
5840 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005841 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5842 return (NULL);
5843 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005844 attr = node->properties;
5845 while (attr != NULL) {
5846 if (((attr->ns == NULL) &&
5847 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5848 ((attr->ns != NULL) &&
5849 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5850
5851 xmlSchemaPIllegalAttrErr(ctxt,
5852 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5853 NULL, NULL, attr);
5854 }
5855 attr = attr->next;
5856 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005857 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 /*
5859 * And now for the children...
5860 */
5861 child = node->children;
5862 while (child != NULL) {
5863 if (IS_SCHEMA(child, "appinfo")) {
5864 /* TODO: make available the content of "appinfo". */
5865 /*
5866 * source = anyURI
5867 * {any attributes with non-schema namespace . . .}>
5868 * Content: ({any})*
5869 */
5870 attr = child->properties;
5871 while (attr != NULL) {
5872 if (((attr->ns == NULL) &&
5873 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5874 ((attr->ns != NULL) &&
5875 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005876
Daniel Veillardc0826a72004-08-10 14:17:33 +00005877 xmlSchemaPIllegalAttrErr(ctxt,
5878 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5879 NULL, NULL, attr);
5880 }
5881 attr = attr->next;
5882 }
5883 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5884 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5885 child = child->next;
5886 } else if (IS_SCHEMA(child, "documentation")) {
5887 /* TODO: make available the content of "documentation". */
5888 /*
5889 * source = anyURI
5890 * {any attributes with non-schema namespace . . .}>
5891 * Content: ({any})*
5892 */
5893 attr = child->properties;
5894 while (attr != NULL) {
5895 if (attr->ns == NULL) {
5896 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5897 xmlSchemaPIllegalAttrErr(ctxt,
5898 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5899 NULL, NULL, attr);
5900 }
5901 } else {
5902 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5903 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5904 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5905
5906 xmlSchemaPIllegalAttrErr(ctxt,
5907 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5908 NULL, NULL, attr);
5909 }
5910 }
5911 attr = attr->next;
5912 }
5913 /*
5914 * Attribute "xml:lang".
5915 */
5916 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5917 if (attr != NULL)
5918 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5919 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5920 child = child->next;
5921 } else {
5922 if (!barked)
5923 xmlSchemaPContentErr(ctxt,
5924 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5925 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5926 barked = 1;
5927 child = child->next;
5928 }
5929 }
5930
Daniel Veillard4255d502002-04-16 15:50:10 +00005931 return (ret);
5932}
5933
5934/**
5935 * xmlSchemaParseFacet:
5936 * @ctxt: a schema validation context
5937 * @schema: the schema being built
5938 * @node: a subtree containing XML Schema informations
5939 *
5940 * parse a XML schema Facet declaration
5941 * *WARNING* this interface is highly subject to change
5942 *
5943 * Returns the new type structure or NULL in case of error
5944 */
5945static xmlSchemaFacetPtr
5946xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005947 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005948{
5949 xmlSchemaFacetPtr facet;
5950 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005951 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005952
5953 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5954 return (NULL);
5955
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005956 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005957 if (facet == NULL) {
5958 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5959 return (NULL);
5960 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005961 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005962 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005963 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005964 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5965 "Facet %s has no value\n", node->name, NULL);
5966 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005967 return (NULL);
5968 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005969 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005970 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005971 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005972 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005973 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005974 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005975 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005976 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005977 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005978 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005981 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005982 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005983 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005985 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005986 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005987 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005989 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005990 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5991 } else if (IS_SCHEMA(node, "minLength")) {
5992 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5993 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005994 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5995 "Unknown facet type %s\n", node->name, NULL);
5996 xmlSchemaFreeFacet(facet);
5997 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005999 xmlSchemaPValAttrID(ctxt, NULL,
6000 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006001 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006002 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6003 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6004 const xmlChar *fixed;
6005
6006 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6007 if (fixed != NULL) {
6008 if (xmlStrEqual(fixed, BAD_CAST "true"))
6009 facet->fixed = 1;
6010 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006011 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006012 child = node->children;
6013
6014 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006015 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6016 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006017 }
6018 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006019 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6020 "Facet %s has unexpected child content\n",
6021 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006022 }
6023 return (facet);
6024}
6025
6026/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006027 * xmlSchemaParseWildcardNs:
6028 * @ctxt: a schema parser context
6029 * @wildc: the wildcard, already created
6030 * @node: a subtree containing XML Schema informations
6031 *
6032 * Parses the attribute "processContents" and "namespace"
6033 * of a xsd:anyAttribute and xsd:any.
6034 * *WARNING* this interface is highly subject to change
6035 *
6036 * Returns 0 if everything goes fine, a positive error code
6037 * if something is not valid and -1 if an internal error occurs.
6038 */
6039static int
6040xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6041 xmlSchemaPtr schema,
6042 xmlSchemaWildcardPtr wildc,
6043 xmlNodePtr node)
6044{
6045 const xmlChar *pc, *ns, *dictnsItem;
6046 int ret = 0;
6047 xmlChar *nsItem;
6048 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6049 xmlAttrPtr attr;
6050
6051 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6052 if ((pc == NULL)
6053 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6054 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6055 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6056 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6057 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6058 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6059 } else {
6060 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006061 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006062 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00006063 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006064 NULL, NULL, NULL);
6065 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006066 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006067 }
6068 /*
6069 * Build the namespace constraints.
6070 */
6071 attr = xmlSchemaGetPropNode(node, "namespace");
6072 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006073 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006074 wildc->any = 1;
6075 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6076 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6077 if (wildc->negNsSet == NULL) {
6078 return (-1);
6079 }
6080 wildc->negNsSet->value = schema->targetNamespace;
6081 } else {
6082 const xmlChar *end, *cur;
6083
6084 cur = ns;
6085 do {
6086 while (IS_BLANK_CH(*cur))
6087 cur++;
6088 end = cur;
6089 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6090 end++;
6091 if (end == cur)
6092 break;
6093 nsItem = xmlStrndup(cur, end - cur);
6094 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6095 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6096 xmlSchemaPSimpleTypeErr(ctxt,
6097 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6098 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006099 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006100 "((##any | ##other) | List of (anyURI | "
6101 "(##targetNamespace | ##local)))",
6102 nsItem, NULL, NULL, NULL);
6103 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6104 } else {
6105 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6106 dictnsItem = schema->targetNamespace;
6107 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6108 dictnsItem = NULL;
6109 } else {
6110 /*
6111 * Validate the item (anyURI).
6112 */
6113 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
6114 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6115 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6116 }
6117 /*
6118 * Avoid dublicate namespaces.
6119 */
6120 tmp = wildc->nsSet;
6121 while (tmp != NULL) {
6122 if (dictnsItem == tmp->value)
6123 break;
6124 tmp = tmp->next;
6125 }
6126 if (tmp == NULL) {
6127 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6128 if (tmp == NULL) {
6129 xmlFree(nsItem);
6130 return (-1);
6131 }
6132 tmp->value = dictnsItem;
6133 tmp->next = NULL;
6134 if (wildc->nsSet == NULL)
6135 wildc->nsSet = tmp;
6136 else
6137 lastNs->next = tmp;
6138 lastNs = tmp;
6139 }
6140
6141 }
6142 xmlFree(nsItem);
6143 cur = end;
6144 } while (*cur != 0);
6145 }
6146 return (ret);
6147}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006148
6149static int
6150xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006151 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006152 xmlNodePtr node,
6153 int minOccurs,
6154 int maxOccurs) {
6155
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006156 if ((maxOccurs == 0) && ( minOccurs == 0))
6157 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006158 if (maxOccurs != UNBOUNDED) {
6159 /*
6160 * TODO: Maby we should better not create the particle,
6161 * if min/max is invalid, since it could confuse the build of the
6162 * content model.
6163 */
6164 /*
6165 * 3.9.6 Schema Component Constraint: Particle Correct
6166 *
6167 */
6168 if (maxOccurs < 1) {
6169 /*
6170 * 2.2 {max occurs} must be greater than or equal to 1.
6171 */
6172 xmlSchemaPCustomAttrErr(ctxt,
6173 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006174 NULL, NULL,
6175 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006176 "The value must be greater than or equal to 1");
6177 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6178 } else if (minOccurs > maxOccurs) {
6179 /*
6180 * 2.1 {min occurs} must not be greater than {max occurs}.
6181 */
6182 xmlSchemaPCustomAttrErr(ctxt,
6183 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006184 NULL, NULL,
6185 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006186 "The value must not be greater than the value of 'maxOccurs'");
6187 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6188 }
6189 }
6190 return (0);
6191}
6192
Daniel Veillardc0826a72004-08-10 14:17:33 +00006193/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006194 * xmlSchemaParseAny:
6195 * @ctxt: a schema validation context
6196 * @schema: the schema being built
6197 * @node: a subtree containing XML Schema informations
6198 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006199 * Parsea a XML schema <any> element. A particle and wildcard
6200 * will be created (except if minOccurs==maxOccurs==0, in this case
6201 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 * *WARNING* this interface is highly subject to change
6203 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006204 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006205 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006206static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006207xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6208 xmlNodePtr node)
6209{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006210 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006211 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006212 xmlSchemaWildcardPtr wild;
6213 int min, max;
6214 xmlAttrPtr attr;
6215 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006216
6217 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6218 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006219 /*
6220 * Check for illegal attributes.
6221 */
6222 attr = node->properties;
6223 while (attr != NULL) {
6224 if (attr->ns == NULL) {
6225 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6226 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6227 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6228 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6229 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6230 xmlSchemaPIllegalAttrErr(ctxt,
6231 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6232 NULL, NULL, attr);
6233 }
6234 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6235 xmlSchemaPIllegalAttrErr(ctxt,
6236 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6237 NULL, NULL, attr);
6238 }
6239 attr = attr->next;
6240 }
6241 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6242 /*
6243 * minOccurs/maxOccurs.
6244 */
6245 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006246 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006247 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6248 "nonNegativeInteger");
6249 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6250 /*
6251 * Create & parse the wildcard.
6252 */
6253 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6254 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006255 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006256 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006257 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006258 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006259 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006260 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006261 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006262 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006263 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006264 }
6265 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006266 xmlSchemaPContentErr(ctxt,
6267 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6268 NULL, NULL, node, child,
6269 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006270 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006271 /*
6272 * No component if minOccurs==maxOccurs==0.
6273 */
6274 if ((min == 0) && (max == 0)) {
6275 /* Don't free the wildcard, since it's already on the list. */
6276 return (NULL);
6277 }
6278 /*
6279 * Create the particle.
6280 */
6281 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6282 if (particle == NULL)
6283 return (NULL);
6284 particle->annot = annot;
6285 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006286
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006287 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006288}
6289
6290/**
6291 * xmlSchemaParseNotation:
6292 * @ctxt: a schema validation context
6293 * @schema: the schema being built
6294 * @node: a subtree containing XML Schema informations
6295 *
6296 * parse a XML schema Notation declaration
6297 *
6298 * Returns the new structure or NULL in case of error
6299 */
6300static xmlSchemaNotationPtr
6301xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006302 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006303{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006304 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006305 xmlSchemaNotationPtr ret;
6306 xmlNodePtr child = NULL;
6307
6308 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6309 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006310 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006311 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006312 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6313 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006314 return (NULL);
6315 }
6316 ret = xmlSchemaAddNotation(ctxt, schema, name);
6317 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006318 return (NULL);
6319 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006320 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006321
6322 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6323 node, BAD_CAST "id");
6324
6325 if (IS_SCHEMA(child, "annotation")) {
6326 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6327 child = child->next;
6328 }
6329
Daniel Veillard4255d502002-04-16 15:50:10 +00006330 child = node->children;
6331 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006332 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6333 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006334 }
6335 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006336 xmlSchemaPContentErr(ctxt,
6337 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6338 NULL, NULL, node, child,
6339 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006340 }
6341
6342 return (ret);
6343}
6344
6345/**
6346 * xmlSchemaParseAnyAttribute:
6347 * @ctxt: a schema validation context
6348 * @schema: the schema being built
6349 * @node: a subtree containing XML Schema informations
6350 *
6351 * parse a XML schema AnyAttrribute declaration
6352 * *WARNING* this interface is highly subject to change
6353 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006354 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006355 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006356static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006357xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6358 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006359{
Daniel Veillard3646d642004-06-02 19:19:14 +00006360 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006361 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006362 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006363
6364 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6365 return (NULL);
6366
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006367 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6368 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006369 if (ret == NULL) {
6370 return (NULL);
6371 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006372 /*
6373 * Check for illegal attributes.
6374 */
6375 attr = node->properties;
6376 while (attr != NULL) {
6377 if (attr->ns == NULL) {
6378 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6379 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6380 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6381 xmlSchemaPIllegalAttrErr(ctxt,
6382 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6383 NULL, NULL, attr);
6384 }
6385 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6386 xmlSchemaPIllegalAttrErr(ctxt,
6387 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6388 NULL, NULL, attr);
6389 }
6390 attr = attr->next;
6391 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006392 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6393 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006394 /*
6395 * Parse the namespace list.
6396 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006397 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006398 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006399 /*
6400 * And now for the children...
6401 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006402 child = node->children;
6403 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006404 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6405 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006406 }
6407 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006408 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006409 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6410 NULL, NULL, node, child,
6411 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006412 }
6413
6414 return (ret);
6415}
6416
6417
6418/**
6419 * xmlSchemaParseAttribute:
6420 * @ctxt: a schema validation context
6421 * @schema: the schema being built
6422 * @node: a subtree containing XML Schema informations
6423 *
6424 * parse a XML schema Attrribute declaration
6425 * *WARNING* this interface is highly subject to change
6426 *
William M. Bracke7091952004-05-11 15:09:58 +00006427 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006428 */
6429static xmlSchemaAttributePtr
6430xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006431 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006432{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006433 const xmlChar *name, *attrValue;
6434 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006435 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 xmlNodePtr child = NULL;
6437 xmlAttrPtr attr, nameAttr;
6438 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006439
6440 /*
6441 * Note that the w3c spec assumes the schema to be validated with schema
6442 * for schemas beforehand.
6443 *
6444 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006445 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006446
6447 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6448 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006449 attr = xmlSchemaGetPropNode(node, "ref");
6450 nameAttr = xmlSchemaGetPropNode(node, "name");
6451
6452 if ((attr == NULL) && (nameAttr == NULL)) {
6453 /*
6454 * 3.2.3 : 3.1
6455 * One of ref or name must be present, but not both
6456 */
6457 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6458 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
6459 "One of the attributes 'ref' or 'name' must be present");
6460 return (NULL);
6461 }
6462 if ((topLevel) || (attr == NULL)) {
6463 if (nameAttr == NULL) {
6464 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6465 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
6466 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006467 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006468 }
6469 } else
6470 isRef = 1;
6471
6472 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006473 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
6475
6476 /*
6477 * Parse as attribute reference.
6478 */
6479 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6480 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6481 &refPrefix, &ref) != 0) {
6482 return (NULL);
6483 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006484 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006486 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 if (ret == NULL) {
6488 if (repName != NULL)
6489 xmlFree(repName);
6490 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006491 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6493 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006494 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006496 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006497 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6498 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006499 /*
6500 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6501 */
6502 if (nameAttr != NULL)
6503 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6504 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6505 "ref", "name");
6506 /*
6507 * Check for illegal attributes.
6508 */
6509 attr = node->properties;
6510 while (attr != NULL) {
6511 if (attr->ns == NULL) {
6512 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6513 xmlStrEqual(attr->name, BAD_CAST "form")) {
6514 /*
6515 * 3.2.3 : 3.2
6516 * If ref is present, then all of <simpleType>,
6517 * form and type must be absent.
6518 */
6519 xmlSchemaPIllegalAttrErr(ctxt,
6520 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
6521 (xmlSchemaTypePtr) ret, attr);
6522 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6523 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6524 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6525 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6526 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6527 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
6528 xmlSchemaPIllegalAttrErr(ctxt,
6529 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6530 &repName, (xmlSchemaTypePtr) ret, attr);
6531 }
6532 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6533 xmlSchemaPIllegalAttrErr(ctxt,
6534 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6535 &repName, (xmlSchemaTypePtr) ret, attr);
6536 }
6537 attr = attr->next;
6538 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006539 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006540 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541
6542 /*
6543 * Parse as attribute declaration.
6544 */
6545 if (xmlSchemaPValAttrNode(ctxt,
6546 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
6547 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6548 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006549 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006550 /*
6551 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6552 */
6553 /*
6554 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6555 */
6556 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
6557 xmlSchemaPSimpleTypeErr(ctxt,
6558 XML_SCHEMAP_NO_XMLNS,
6559 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006560 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006561 "The value must not match 'xmlns'",
6562 NULL, NULL);
6563 if (repName != NULL)
6564 xmlFree(repName);
6565 return (NULL);
6566 }
6567 /*
6568 * Evaluate the target namespace
6569 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006570 if (topLevel) {
6571 ns = schema->targetNamespace;
6572 } else {
6573 attr = xmlSchemaGetPropNode(node, "form");
6574 if (attr != NULL) {
6575 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6576 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6577 ns = schema->targetNamespace;
6578 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6579 xmlSchemaPSimpleTypeErr(ctxt,
6580 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6581 &repName, NULL, (xmlNodePtr) attr,
6582 NULL, "(qualified | unqualified)",
6583 attrValue, NULL, NULL, NULL);
6584 }
6585 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6586 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006587 }
6588 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006589 if (ret == NULL) {
6590 if (repName != NULL)
6591 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006592 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006593 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006594 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006595 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006596 if (topLevel)
6597 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
6598 /*
6599 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6600 */
6601 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
6602 xmlSchemaPCustomErr(ctxt,
6603 XML_SCHEMAP_NO_XSI,
6604 &repName, (xmlSchemaTypePtr) ret, node,
6605 "The target namespace must not match '%s'",
6606 xmlSchemaInstanceNs);
6607 }
6608 /*
6609 * Check for illegal attributes.
6610 */
6611 attr = node->properties;
6612 while (attr != NULL) {
6613 if (attr->ns == NULL) {
6614 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6615 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6616 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6617 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6618 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
6619 if ((topLevel) ||
6620 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6621 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
6622 xmlSchemaPIllegalAttrErr(ctxt,
6623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6624 &repName, (xmlSchemaTypePtr) ret, attr);
6625 }
6626 }
6627 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6628 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6629 &repName, (xmlSchemaTypePtr) ret, attr);
6630 }
6631 attr = attr->next;
6632 }
6633 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
6634 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006635 }
6636 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6637 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006638 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006639 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006640 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006641 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6642 if (ret->defValue != NULL)
6643 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
6644 /*
6645 * Attribute "default".
6646 */
6647 attr = xmlSchemaGetPropNode(node, "default");
6648 if (attr != NULL) {
6649 /*
6650 * 3.2.3 : 1
6651 * default and fixed must not both be present.
6652 */
6653 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6654 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6655 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6656 } else
6657 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6658 }
6659 if (topLevel == 0) {
6660 /*
6661 * Attribute "use".
6662 */
6663 attr = xmlSchemaGetPropNode(node, "use");
6664 if (attr != NULL) {
6665 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6666 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6667 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6668 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6669 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6670 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6671 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6672 else
6673 xmlSchemaPSimpleTypeErr(ctxt,
6674 XML_SCHEMAP_INVALID_ATTR_USE,
6675 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006676 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006677 attrValue, NULL, NULL, NULL);
6678 } else
6679 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6680 /*
6681 * 3.2.3 : 2
6682 * If default and use are both present, use must have
6683 * the actual value optional.
6684 */
6685 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6686 (ret->defValue != NULL) &&
6687 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
6688 xmlSchemaPSimpleTypeErr(ctxt,
6689 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6690 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006691 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006692 "The value must be 'optional' if the attribute "
6693 "'default' is present as well", NULL, NULL);
6694 }
6695 }
6696 /*
6697 * And now for the children...
6698 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006699 child = node->children;
6700 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006701 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6702 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006703 }
6704 if (isRef) {
6705 if (child != NULL) {
6706 if (IS_SCHEMA(child, "simpleType"))
6707 /*
6708 * 3.2.3 : 3.2
6709 * If ref is present, then all of <simpleType>,
6710 * form and type must be absent.
6711 */
6712 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6713 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6714 "(annotation?)");
6715 else
6716 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6717 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6718 "(annotation?)");
6719 }
6720 } else {
6721 if (IS_SCHEMA(child, "simpleType")) {
6722 if (ret->typeName != NULL) {
6723 /*
6724 * 3.2.3 : 4
6725 * type and <simpleType> must not both be present.
6726 */
6727 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6728 &repName, (xmlSchemaTypePtr) ret, node, child,
6729 "The attribute 'type' and the <simpleType> child "
6730 "are mutually exclusive", NULL);
6731 } else
6732 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6733 child = child->next;
6734 }
6735 if (child != NULL)
6736 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6737 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6738 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006739 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 /*
6741 * Cleanup.
6742 */
6743 if (repName != NULL)
6744 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006745 return (ret);
6746}
6747
6748/**
6749 * xmlSchemaParseAttributeGroup:
6750 * @ctxt: a schema validation context
6751 * @schema: the schema being built
6752 * @node: a subtree containing XML Schema informations
6753 *
6754 * parse a XML schema Attribute Group declaration
6755 * *WARNING* this interface is highly subject to change
6756 *
6757 * Returns the attribute group or NULL in case of error.
6758 */
6759static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006760xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006761 xmlSchemaPtr schema, xmlNodePtr node,
6762 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006763{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006764 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006765 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006766 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006767 const xmlChar *oldcontainer;
6768 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006769
6770 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6771 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006772
6773 nameAttr = xmlSchemaGetPropNode(node, "name");
6774 attr = xmlSchemaGetPropNode(node, "ref");
6775 if ((topLevel) || (attr == NULL)) {
6776 /*
6777 * Parse as an attribute group definition.
6778 * Note that those are allowed at top level only.
6779 */
6780 if (nameAttr == NULL) {
6781 xmlSchemaPMissingAttrErr(ctxt,
6782 XML_SCHEMAP_S4S_ATTR_MISSING,
6783 NULL, NULL, node, "name", NULL);
6784 return (NULL);
6785 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006786 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
6787 * (xmlNodePtr) nameAttr);
6788 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006789 /*
6790 * The name is crucial, exit if invalid.
6791 */
6792 if (xmlSchemaPValAttrNode(ctxt,
6793 NULL, NULL, nameAttr,
6794 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6795 return (NULL);
6796 }
6797 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6798 if (ret == NULL)
6799 return (NULL);
6800 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6801 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6802 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006803 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006804 } else {
6805 char buf[50];
6806 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6807
6808 /*
6809 * Parse as an attribute group definition reference.
6810 */
6811 if (attr == NULL) {
6812 xmlSchemaPMissingAttrErr(ctxt,
6813 XML_SCHEMAP_S4S_ATTR_MISSING,
6814 NULL, NULL, node, "ref", NULL);
6815 }
6816 xmlSchemaPValAttrNodeQName(ctxt, schema,
6817 NULL, NULL, attr, &refNs, &refPrefix, &ref);
6818
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006819 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006820 name = (const xmlChar *) buf;
6821 if (name == NULL) {
6822 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6823 "attribute group definition reference", node);
6824 return (NULL);
6825 }
6826 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6827 if (ret == NULL)
6828 return (NULL);
6829 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6830 ret->ref = ref;
6831 ret->refNs = refNs;
6832 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006833 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006834 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006835 xmlSchemaCheckReference(ctxt, schema, node,
6836 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006837 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006838 /*
6839 * Check for illegal attributes.
6840 */
6841 attr = node->properties;
6842 while (attr != NULL) {
6843 if (attr->ns == NULL) {
6844 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6845 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
6846 (!xmlStrEqual(attr->name, BAD_CAST "id")))
6847 {
6848 xmlSchemaPIllegalAttrErr(ctxt,
6849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6850 NULL, NULL, attr);
6851 }
6852 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6853 xmlSchemaPIllegalAttrErr(ctxt,
6854 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6855 NULL, NULL, attr);
6856 }
6857 attr = attr->next;
6858 }
6859 /* TODO: Validate "id" ? */
6860 /*
6861 * And now for the children...
6862 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006863 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006864 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006865 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006866 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006867 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6868 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006869 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006870 if (topLevel) {
6871 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6872 if (IS_SCHEMA(child, "anyAttribute")) {
6873 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6874 child = child->next;
6875 }
6876 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006877 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006878 xmlSchemaPContentErr(ctxt,
6879 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6880 NULL, NULL, node, child, NULL,
6881 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006882 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006883 ctxt->container = oldcontainer;
6884 return (ret);
6885}
6886
6887/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006888 * xmlSchemaPValAttrFormDefault:
6889 * @value: the value
6890 * @flags: the flags to be modified
6891 * @flagQualified: the specific flag for "qualified"
6892 *
6893 * Returns 0 if the value is valid, 1 otherwise.
6894 */
6895static int
6896xmlSchemaPValAttrFormDefault(const xmlChar *value,
6897 int *flags,
6898 int flagQualified)
6899{
6900 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6901 if ((*flags & flagQualified) == 0)
6902 *flags |= flagQualified;
6903 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6904 return (1);
6905
6906 return (0);
6907}
6908
6909/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006910 * xmlSchemaPValAttrBlockFinal:
6911 * @value: the value
6912 * @flags: the flags to be modified
6913 * @flagAll: the specific flag for "#all"
6914 * @flagExtension: the specific flag for "extension"
6915 * @flagRestriction: the specific flag for "restriction"
6916 * @flagSubstitution: the specific flag for "substitution"
6917 * @flagList: the specific flag for "list"
6918 * @flagUnion: the specific flag for "union"
6919 *
6920 * Validates the value of the attribute "final" and "block". The value
6921 * is converted into the specified flag values and returned in @flags.
6922 *
6923 * Returns 0 if the value is valid, 1 otherwise.
6924 */
6925
6926static int
6927xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6928 int *flags,
6929 int flagAll,
6930 int flagExtension,
6931 int flagRestriction,
6932 int flagSubstitution,
6933 int flagList,
6934 int flagUnion)
6935{
6936 int ret = 0;
6937
6938 /*
6939 * TODO: This does not check for dublicate entries.
6940 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006941 if ((flags == NULL) || (value == NULL))
6942 return (-1);
6943 if (value[0] == 0)
6944 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006945 if (xmlStrEqual(value, BAD_CAST "#all")) {
6946 if (flagAll != -1)
6947 *flags |= flagAll;
6948 else {
6949 if (flagExtension != -1)
6950 *flags |= flagExtension;
6951 if (flagRestriction != -1)
6952 *flags |= flagRestriction;
6953 if (flagSubstitution != -1)
6954 *flags |= flagSubstitution;
6955 if (flagList != -1)
6956 *flags |= flagList;
6957 if (flagUnion != -1)
6958 *flags |= flagUnion;
6959 }
6960 } else {
6961 const xmlChar *end, *cur = value;
6962 xmlChar *item;
6963
6964 do {
6965 while (IS_BLANK_CH(*cur))
6966 cur++;
6967 end = cur;
6968 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6969 end++;
6970 if (end == cur)
6971 break;
6972 item = xmlStrndup(cur, end - cur);
6973 if (xmlStrEqual(item, BAD_CAST "extension")) {
6974 if (flagExtension != -1) {
6975 if ((*flags & flagExtension) == 0)
6976 *flags |= flagExtension;
6977 } else
6978 ret = 1;
6979 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6980 if (flagRestriction != -1) {
6981 if ((*flags & flagRestriction) == 0)
6982 *flags |= flagRestriction;
6983 } else
6984 ret = 1;
6985 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6986 if (flagSubstitution != -1) {
6987 if ((*flags & flagSubstitution) == 0)
6988 *flags |= flagSubstitution;
6989 } else
6990 ret = 1;
6991 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6992 if (flagList != -1) {
6993 if ((*flags & flagList) == 0)
6994 *flags |= flagList;
6995 } else
6996 ret = 1;
6997 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6998 if (flagUnion != -1) {
6999 if ((*flags & flagUnion) == 0)
7000 *flags |= flagUnion;
7001 } else
7002 ret = 1;
7003 } else
7004 ret = 1;
7005 if (item != NULL)
7006 xmlFree(item);
7007 cur = end;
7008 } while ((ret == 0) && (*cur != 0));
7009 }
7010
7011 return (ret);
7012}
7013
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007014static int
7015xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007016 xmlSchemaIDCPtr idc,
7017 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007018 xmlAttrPtr attr,
7019 int isField)
7020{
7021 xmlNodePtr node;
7022
7023 /*
7024 * c-selector-xpath:
7025 * Schema Component Constraint: Selector Value OK
7026 *
7027 * TODO: 1 The {selector} must be a valid XPath expression, as defined
7028 * in [XPath].
7029 */
7030 if (selector == NULL) {
7031 xmlSchemaPErr(ctxt, idc->node,
7032 XML_SCHEMAP_INTERNAL,
7033 "Internal error: xmlSchemaCheckCSelectorXPath, "
7034 "the selector is not specified.\n", NULL, NULL);
7035 return (-1);
7036 }
7037 if (attr == NULL)
7038 node = idc->node;
7039 else
7040 node = (xmlNodePtr) attr;
7041 if (selector->xpath == NULL) {
7042 xmlSchemaPCustomErr(ctxt,
7043 /* TODO: Adjust error code. */
7044 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7045 NULL, NULL, node,
7046 "The XPath expression of the selector is not valid", NULL);
7047 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7048 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007049 const xmlChar **nsArray = NULL;
7050 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007051 /*
7052 * Compile the XPath expression.
7053 */
7054 /*
7055 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007056 * TODO: Call xmlPatterncompile with different options for selector/
7057 * field.
7058 */
7059 nsList = xmlGetNsList(attr->doc, attr->parent);
7060 /*
7061 * Build an array of prefixes and namespaces.
7062 */
7063 if (nsList != NULL) {
7064 int i, count = 0;
7065 xmlNsPtr ns;
7066
7067 for (i = 0; nsList[i] != NULL; i++)
7068 count++;
7069
7070 nsArray = (const xmlChar **) xmlMalloc(
7071 (count * 2 + 1) * sizeof(const xmlChar *));
7072 if (nsArray == NULL) {
7073 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7074 NULL);
7075 return (-1);
7076 }
7077 for (i = 0; i < count; i++) {
7078 ns = nsList[i];
7079 nsArray[2 * i] = nsList[i]->href;
7080 nsArray[2 * i + 1] = nsList[i]->prefix;
7081 }
7082 nsArray[count * 2] = NULL;
7083 xmlFree(nsList);
7084 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007085 /*
7086 * TODO: Differentiate between "selector" and "field".
7087 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007088 if (isField)
7089 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00007090 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007091 else
7092 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00007093 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007094 if (nsArray != NULL)
7095 xmlFree((xmlChar **) nsArray);
7096
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007097 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007098 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007099 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007100 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7101 NULL, NULL, node,
7102 "The XPath expression '%s' could not be "
7103 "compiled", selector->xpath);
7104 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007105 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007106 }
7107 return (0);
7108}
7109
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007110#define ADD_ANNOTATION(annot) \
7111 xmlSchemaAnnotPtr cur = item->annot; \
7112 if (item->annot == NULL) { \
7113 item->annot = annot; \
7114 return (annot); \
7115 } \
7116 cur = item->annot; \
7117 if (cur->next != NULL) { \
7118 cur = cur->next; \
7119 } \
7120 cur->next = annot;
7121
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007122/**
7123 * xmlSchemaAssignAnnotation:
7124 * @item: the schema component
7125 * @annot: the annotation
7126 *
7127 * Adds the annotation to the given schema component.
7128 *
7129 * Returns the given annotaion.
7130 */
7131static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007132xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7133 xmlSchemaAnnotPtr annot)
7134{
7135 if ((annItem == NULL) || (annot == NULL))
7136 return (NULL);
7137 switch (annItem->type) {
7138 case XML_SCHEMA_TYPE_ELEMENT: {
7139 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7140 ADD_ANNOTATION(annot)
7141 }
7142 break;
7143 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7144 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7145 ADD_ANNOTATION(annot)
7146 }
7147 break;
7148 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7149 case XML_SCHEMA_TYPE_ANY: {
7150 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7151 ADD_ANNOTATION(annot)
7152 }
7153 break;
7154 case XML_SCHEMA_TYPE_PARTICLE:
7155 case XML_SCHEMA_TYPE_IDC_KEY:
7156 case XML_SCHEMA_TYPE_IDC_KEYREF:
7157 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
7158 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7159 ADD_ANNOTATION(annot)
7160 }
7161 break;
7162 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7163 xmlSchemaAttributeGroupPtr item =
7164 (xmlSchemaAttributeGroupPtr) annItem;
7165 ADD_ANNOTATION(annot)
7166 }
7167 break;
7168 case XML_SCHEMA_TYPE_NOTATION: {
7169 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7170 ADD_ANNOTATION(annot)
7171 }
7172 break;
7173 case XML_SCHEMA_FACET_MININCLUSIVE:
7174 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7175 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7176 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7177 case XML_SCHEMA_FACET_TOTALDIGITS:
7178 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7179 case XML_SCHEMA_FACET_PATTERN:
7180 case XML_SCHEMA_FACET_ENUMERATION:
7181 case XML_SCHEMA_FACET_WHITESPACE:
7182 case XML_SCHEMA_FACET_LENGTH:
7183 case XML_SCHEMA_FACET_MAXLENGTH:
7184 case XML_SCHEMA_FACET_MINLENGTH: {
7185 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7186 ADD_ANNOTATION(annot)
7187 }
7188 break;
7189 case XML_SCHEMA_TYPE_SIMPLE:
7190 case XML_SCHEMA_TYPE_COMPLEX: {
7191 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7192 ADD_ANNOTATION(annot)
7193 }
7194 break;
7195 case XML_SCHEMA_TYPE_GROUP: {
7196 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7197 ADD_ANNOTATION(annot)
7198 }
7199 break;
7200 case XML_SCHEMA_TYPE_SEQUENCE:
7201 case XML_SCHEMA_TYPE_CHOICE:
7202 case XML_SCHEMA_TYPE_ALL: {
7203 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7204 ADD_ANNOTATION(annot)
7205 }
7206 break;
7207 default:
7208 xmlSchemaPCustomErr(NULL,
7209 XML_SCHEMAP_INTERNAL,
7210 NULL, NULL, NULL,
7211 "Internal error: xmlSchemaAddAnnotation, "
7212 "The item is not a annotated schema component", NULL);
7213 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007214 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 return (annot);
7216}
7217
7218/**
7219 * xmlSchemaParseIDCSelectorAndField:
7220 * @ctxt: a schema validation context
7221 * @schema: the schema being built
7222 * @node: a subtree containing XML Schema informations
7223 *
7224 * Parses a XML Schema identity-contraint definition's
7225 * <selector> and <field> elements.
7226 *
7227 * Returns the parsed identity-constraint definition.
7228 */
7229static xmlSchemaIDCSelectPtr
7230xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
7231 xmlSchemaPtr schema,
7232 xmlSchemaIDCPtr idc,
7233 xmlNodePtr node,
7234 int isField)
7235{
7236 xmlSchemaIDCSelectPtr item;
7237 xmlNodePtr child = NULL;
7238 xmlAttrPtr attr;
7239
7240 /*
7241 * Check for illegal attributes.
7242 */
7243 attr = node->properties;
7244 while (attr != NULL) {
7245 if (attr->ns == NULL) {
7246 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7247 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
7248 xmlSchemaPIllegalAttrErr(ctxt,
7249 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7250 NULL, NULL, attr);
7251 }
7252 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7253 xmlSchemaPIllegalAttrErr(ctxt,
7254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7255 NULL, NULL, attr);
7256 }
7257 attr = attr->next;
7258 }
7259 /*
7260 * Create the item.
7261 */
7262 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7263 if (item == NULL) {
7264 xmlSchemaPErrMemory(ctxt,
7265 "allocating a 'selector' of an identity-constraint definition",
7266 NULL);
7267 return (NULL);
7268 }
7269 memset(item, 0, sizeof(xmlSchemaIDCSelect));
7270 /*
7271 * Attribute "xpath" (mandatory).
7272 */
7273 attr = xmlSchemaGetPropNode(node, "xpath");
7274 if (attr == NULL) {
7275 xmlSchemaPMissingAttrErr(ctxt,
7276 XML_SCHEMAP_S4S_ATTR_MISSING,
7277 NULL, NULL, node,
7278 "name", NULL);
7279 } else {
7280 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7281 /*
7282 * URGENT TODO: "field"s have an other syntax than "selector"s.
7283 */
7284
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007285 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7286 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007287 xmlSchemaPErr(ctxt,
7288 (xmlNodePtr) attr,
7289 XML_SCHEMAP_INTERNAL,
7290 "Internal error: xmlSchemaParseIDCSelectorAndField, "
7291 "validating the XPath expression of a IDC selector.\n",
7292 NULL, NULL);
7293 }
7294
7295 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007296 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007297 /*
7298 * And now for the children...
7299 */
7300 child = node->children;
7301 if (IS_SCHEMA(child, "annotation")) {
7302 /*
7303 * Add the annotation to the parent IDC.
7304 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007305 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007306 xmlSchemaParseAnnotation(ctxt, schema, child));
7307 child = child->next;
7308 }
7309 if (child != NULL) {
7310 xmlSchemaPContentErr(ctxt,
7311 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7312 NULL, NULL, node, child,
7313 NULL, "(annotation?)");
7314 }
7315
7316 return (item);
7317}
7318
7319/**
7320 * xmlSchemaParseIDC:
7321 * @ctxt: a schema validation context
7322 * @schema: the schema being built
7323 * @node: a subtree containing XML Schema informations
7324 *
7325 * Parses a XML Schema identity-contraint definition.
7326 *
7327 * Returns the parsed identity-constraint definition.
7328 */
7329static xmlSchemaIDCPtr
7330xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
7331 xmlSchemaPtr schema,
7332 xmlNodePtr node,
7333 xmlSchemaTypeType idcCategory,
7334 const xmlChar *targetNamespace)
7335{
7336 xmlSchemaIDCPtr item = NULL;
7337 xmlNodePtr child = NULL;
7338 xmlAttrPtr attr;
7339 const xmlChar *name = NULL;
7340 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7341 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007342
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007343 /*
7344 * Check for illegal attributes.
7345 */
7346 attr = node->properties;
7347 while (attr != NULL) {
7348 if (attr->ns == NULL) {
7349 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7350 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7351 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7352 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
7353 xmlSchemaPIllegalAttrErr(ctxt,
7354 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7355 NULL, NULL, attr);
7356 }
7357 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7358 xmlSchemaPIllegalAttrErr(ctxt,
7359 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7360 NULL, NULL, attr);
7361 }
7362 attr = attr->next;
7363 }
7364 /*
7365 * Attribute "name" (mandatory).
7366 */
7367 attr = xmlSchemaGetPropNode(node, "name");
7368 if (attr == NULL) {
7369 xmlSchemaPMissingAttrErr(ctxt,
7370 XML_SCHEMAP_S4S_ATTR_MISSING,
7371 NULL, NULL, node,
7372 "name", NULL);
7373 return (NULL);
7374 } else if (xmlSchemaPValAttrNode(ctxt,
7375 NULL, NULL, attr,
7376 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7377 return (NULL);
7378 }
7379 /*
7380 * Create the component.
7381 */
7382 if (schema->idcDef == NULL)
7383 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
7384 if (schema->idcDef == NULL)
7385 return (NULL);
7386
7387 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7388 if (item == NULL) {
7389 xmlSchemaPErrMemory(ctxt,
7390 "allocating an identity-constraint definition", NULL);
7391 return (NULL);
7392 }
7393 /*
7394 * Add the IDC to the list of IDCs on the schema component.
7395 */
7396 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
7397 if (resAdd != 0) {
7398 xmlSchemaPCustomErrExt(ctxt,
7399 XML_SCHEMAP_REDEFINED_TYPE,
7400 NULL, NULL, node,
7401 "An identity-constraint definition with the name '%s' "
7402 "and targetNamespace '%s' does already exist",
7403 name, targetNamespace, NULL);
7404 xmlFree(item);
7405 return (NULL);
7406 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007407 memset(item, 0, sizeof(xmlSchemaIDC));
7408 item->name = name;
7409 item->type = idcCategory;
7410 item->node = node;
7411 /*
7412 * The target namespace of the parent element declaration.
7413 */
7414 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007415 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7416 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007417 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7418 /*
7419 * Attribute "refer" (mandatory).
7420 */
7421 attr = xmlSchemaGetPropNode(node, "refer");
7422 if (attr == NULL) {
7423 xmlSchemaPMissingAttrErr(ctxt,
7424 XML_SCHEMAP_S4S_ATTR_MISSING,
7425 NULL, NULL, node,
7426 "refer", NULL);
7427 } else {
7428 /*
7429 * Create a reference item.
7430 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007431 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
7432 NULL, NULL);
7433 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007434 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007435 xmlSchemaPValAttrNodeQName(ctxt, schema,
7436 NULL, NULL, attr,
7437 &(item->ref->targetNamespace), 0,
7438 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007439 xmlSchemaCheckReference(ctxt, schema, node,
7440 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007441 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007442 }
7443 }
7444 /*
7445 * And now for the children...
7446 */
7447 child = node->children;
7448 if (IS_SCHEMA(child, "annotation")) {
7449 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7450 child = child->next;
7451 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007452 if (child == NULL) {
7453 xmlSchemaPContentErr(ctxt,
7454 XML_SCHEMAP_S4S_ELEM_MISSING,
7455 NULL, NULL, node, child,
7456 "A child element is missing",
7457 "(annotation?, (selector, field+))");
7458 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007459 /*
7460 * Child element <selector>.
7461 */
7462 if (IS_SCHEMA(child, "selector")) {
7463 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7464 item, child, 0);
7465 child = child->next;
7466 /*
7467 * Child elements <field>.
7468 */
7469 if (IS_SCHEMA(child, "field")) {
7470 do {
7471 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7472 item, child, 1);
7473 if (field != NULL) {
7474 field->index = item->nbFields;
7475 item->nbFields++;
7476 if (lastField != NULL)
7477 lastField->next = field;
7478 else
7479 item->fields = field;
7480 lastField = field;
7481 }
7482 child = child->next;
7483 } while (IS_SCHEMA(child, "field"));
7484 } else {
7485 xmlSchemaPContentErr(ctxt,
7486 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7487 NULL, NULL, node, child,
7488 NULL, "(annotation?, (selector, field+))");
7489 }
7490 }
7491 if (child != NULL) {
7492 xmlSchemaPContentErr(ctxt,
7493 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7494 NULL, NULL, node, child,
7495 NULL, "(annotation?, (selector, field+))");
7496 }
7497
7498 return (item);
7499}
7500
Daniel Veillardc0826a72004-08-10 14:17:33 +00007501/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007502 * xmlSchemaParseElement:
7503 * @ctxt: a schema validation context
7504 * @schema: the schema being built
7505 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007506 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007507 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007508 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007509 * *WARNING* this interface is highly subject to change
7510 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007511 * Returns the element declaration or a particle; NULL in case
7512 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007513 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007514static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007515xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007516 xmlNodePtr node, int topLevel)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007517{
7518 xmlSchemaElementPtr decl = NULL;
7519 xmlSchemaParticlePtr particle = NULL;
7520 xmlSchemaAnnotPtr annot = NULL;
7521 xmlNodePtr child = NULL;
7522 xmlAttrPtr attr, nameAttr;
7523 int min, max, isRef = 0;
7524 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007525
7526 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7527 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007528
Daniel Veillard4255d502002-04-16 15:50:10 +00007529 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007530 return (NULL);
7531 /*
7532 * If we get a "ref" attribute on a local <element> we will assume it's
7533 * a reference - even if there's a "name" attribute; this seems to be more
7534 * robust.
7535 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007536 nameAttr = xmlSchemaGetPropNode(node, "name");
7537 attr = xmlSchemaGetPropNode(node, "ref");
7538 if ((topLevel) || (attr == NULL)) {
7539 if (nameAttr == NULL) {
7540 xmlSchemaPMissingAttrErr(ctxt,
7541 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007542 NULL, NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007544 }
7545 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007548 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7549 child = node->children;
7550 if (IS_SCHEMA(child, "annotation")) {
7551 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7552 child = child->next;
7553 }
7554 /*
7555 * Skip particle part if a global declaration.
7556 */
7557 if (topLevel)
7558 goto declaration_part;
7559 /*
7560 * The particle part ==================================================
7561 */
7562 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7563 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7564 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7565 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7566 if (particle == NULL)
7567 goto return_null;
7568
7569 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7570
7571 if (isRef) {
7572 const xmlChar *refNs = NULL, *ref = NULL;
7573 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007574 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007575 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007576 */
7577 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007578 NULL, NULL, attr, &refNs, NULL, &ref);
7579 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007580 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007581 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007582 */
7583 if (nameAttr != NULL) {
7584 xmlSchemaPMutualExclAttrErr(ctxt,
7585 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007586 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007588 /*
7589 * Check for illegal attributes.
7590 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 attr = node->properties;
7592 while (attr != NULL) {
7593 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007594 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7595 xmlStrEqual(attr->name, BAD_CAST "name") ||
7596 xmlStrEqual(attr->name, BAD_CAST "id") ||
7597 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7598 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7599 {
7600 attr = attr->next;
7601 continue;
7602 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007603 /* SPEC (3.3.3 : 2.2) */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007604 xmlSchemaPCustomAttrErr(ctxt,
7605 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007606 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007607 "Only the attributes 'minOccurs', 'maxOccurs' and "
7608 "'id' are allowed in addition to 'ref'");
7609 break;
7610 }
7611 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7612 xmlSchemaPIllegalAttrErr(ctxt,
7613 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007614 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007615 }
7616 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007617 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007618 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007619 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007620 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007621 if (child != NULL) {
7622 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7623 NULL, NULL, node, child, NULL, "(annotation?)");
7624 }
7625 if ((min == 0) && (max == 0))
7626 goto return_null;
7627 /*
7628 * Create the reference item.
7629 */
7630 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7631 ref, refNs);
7632 if (refer == NULL)
7633 goto return_null;
7634 particle->children = (xmlSchemaTreeItemPtr) refer;
7635 particle->annot = annot;
7636 /*
7637 * Add to assembled items; the reference need to be resolved.
7638 */
7639 if (ctxt->assemble != NULL)
7640 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7641
7642 return ((xmlSchemaBasicItemPtr) particle);
7643 }
7644 /*
7645 * The declaration part ===============================================
7646 */
7647declaration_part:
7648 {
7649 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7650 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7651
7652 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007653 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007654 goto return_null;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 /*
7656 * Evaluate the target namespace.
7657 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007658 if (topLevel) {
7659 ns = schema->targetNamespace;
7660 } else {
7661 attr = xmlSchemaGetPropNode(node, "form");
7662 if (attr != NULL) {
7663 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7664 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007665 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007666 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
7667 xmlSchemaPSimpleTypeErr(ctxt,
7668 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007669 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007670 NULL, "(qualified | unqualified)",
7671 attrValue, NULL, NULL, NULL);
7672 }
7673 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7674 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00007675 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007676 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
7677 if (decl == NULL) {
7678 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007679 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007680 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7681 decl->node = node;
7682 decl->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007683 /*
7684 * Check for illegal attributes.
7685 */
William M. Bracke7091952004-05-11 15:09:58 +00007686 attr = node->properties;
7687 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 if (attr->ns == NULL) {
7689 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7690 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7691 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7692 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7693 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7694 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007695 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7696 {
7697 if (topLevel == 0) {
7698 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007699 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007700 (!xmlStrEqual(attr->name, BAD_CAST "form")))
7701 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007702 xmlSchemaPIllegalAttrErr(ctxt,
7703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7704 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007705 }
7706 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7707 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
7708 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7709
7710 xmlSchemaPIllegalAttrErr(ctxt,
7711 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007712 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007713 }
7714 }
7715 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7716
7717 xmlSchemaPIllegalAttrErr(ctxt,
7718 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007719 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007720 }
7721 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007722 }
William M. Bracke7091952004-05-11 15:09:58 +00007723 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007724 * Extract/validate attributes.
7725 */
7726 if (topLevel) {
7727 /*
7728 * Process top attributes of global element declarations here.
7729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007730 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7731 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
7732 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7733 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7734 &(decl->substGroupNs), NULL, &(decl->substGroup));
7735 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007736 node, "abstract", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007737 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007738 /*
7739 * Attribute "final".
7740 */
7741 attr = xmlSchemaGetPropNode(node, "final");
7742 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007743 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7744 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7745 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7746 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007747 } else {
7748 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007749 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007750 -1,
7751 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7752 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
7753 xmlSchemaPSimpleTypeErr(ctxt,
7754 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007755 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007756 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007757 attrValue, NULL, NULL, NULL);
7758 }
7759 }
7760 }
7761 /*
7762 * Attribute "block".
7763 */
7764 attr = xmlSchemaGetPropNode(node, "block");
7765 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007766 /*
7767 * Apply default "block" values.
7768 */
7769 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7770 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7771 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7772 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7773 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7774 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007775 } else {
7776 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007777 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007778 -1,
7779 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
7780 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
7781 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7782 xmlSchemaPSimpleTypeErr(ctxt,
7783 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007784 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007785 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00007786 "restriction | substitution))", attrValue,
7787 NULL, NULL, NULL);
7788 }
7789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007790 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007791 node, "nillable", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007792 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007793
Daniel Veillardc0826a72004-08-10 14:17:33 +00007794 xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007795 NULL, (xmlSchemaTypePtr) decl, node,
7796 "type", &(decl->namedTypeNs), NULL, &(decl->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00007797
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007798 decl->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007799 attr = xmlSchemaGetPropNode(node, "fixed");
7800 if (attr != NULL) {
7801 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007802 if (decl->value != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007803 /*
7804 * 3.3.3 : 1
7805 * default and fixed must not both be present.
7806 */
7807 xmlSchemaPMutualExclAttrErr(ctxt,
7808 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007809 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007810 "default", "fixed");
7811 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007812 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7813 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007814 }
William M. Bracke7091952004-05-11 15:09:58 +00007815 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007816 /*
7817 * And now for the children...
7818 */
7819 oldcontainer = ctxt->container;
7820 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007821 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007822 /*
7823 * 3.3.3 : 3
7824 * "type" and either <simpleType> or <complexType> are mutually
7825 * exclusive
7826 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007827 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007828 xmlSchemaPContentErr(ctxt,
7829 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007830 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007831 "The attribute 'type' and the <complexType> child are "
7832 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007833 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007834 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007835 child = child->next;
7836 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007837 /*
7838 * 3.3.3 : 3
7839 * "type" and either <simpleType> or <complexType> are
7840 * mutually exclusive
7841 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007842 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007843 xmlSchemaPContentErr(ctxt,
7844 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007845 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007846 "The attribute 'type' and the <simpleType> child are "
7847 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007848 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007849 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007850 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007851 }
William M. Bracke7091952004-05-11 15:09:58 +00007852 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007853 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007854 if (IS_SCHEMA(child, "unique")) {
7855 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007856 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007857 } else if (IS_SCHEMA(child, "key")) {
7858 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007859 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007860 } else if (IS_SCHEMA(child, "keyref")) {
7861 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007862 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007863 }
7864 if (lastIDC != NULL)
7865 lastIDC->next = curIDC;
7866 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007867 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007868 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007869 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007870 }
7871 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007872 xmlSchemaPContentErr(ctxt,
7873 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007874 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007875 NULL, "(annotation?, ((simpleType | complexType)?, "
7876 "(unique | key | keyref)*))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007877 }
7878 ctxt->container = oldcontainer;
7879 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007880 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007881 /*
7882 * NOTE: Element Declaration Representation OK 4. will be checked at a
7883 * different layer.
7884 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007885 FREE_AND_NULL(des)
7886 if (topLevel)
7887 return ((xmlSchemaBasicItemPtr) decl);
7888 else {
7889 particle->children = (xmlSchemaTreeItemPtr) decl;
7890 return ((xmlSchemaBasicItemPtr) particle);
7891 }
7892
7893return_null:
7894 FREE_AND_NULL(des)
7895 if (annot != NULL)
7896 xmlSchemaFreeAnnot(annot);
7897 if (particle != NULL)
7898 xmlSchemaFreeParticle(particle);
7899 if (decl != NULL)
7900 xmlSchemaFreeElement(decl);
7901 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007902}
7903
7904/**
7905 * xmlSchemaParseUnion:
7906 * @ctxt: a schema validation context
7907 * @schema: the schema being built
7908 * @node: a subtree containing XML Schema informations
7909 *
7910 * parse a XML schema Union definition
7911 * *WARNING* this interface is highly subject to change
7912 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007913 * Returns -1 in case of internal error, 0 in case of success and a positive
7914 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007915 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007916static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007917xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007918 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007919{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007920 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007921 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007922 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007924
7925 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007926 return (-1);
7927 /* Not a component, don't create it. */
7928 type = ctxt->ctxtType;
7929 /*
7930 * Mark the simple type as being of variety "union".
7931 */
7932 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007933 /*
7934 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7935 * then the ·simple ur-type definition·."
7936 */
7937 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007938 /*
7939 * Check for illegal attributes.
7940 */
7941 attr = node->properties;
7942 while (attr != NULL) {
7943 if (attr->ns == NULL) {
7944 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7945 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7946 xmlSchemaPIllegalAttrErr(ctxt,
7947 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007948 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007949 }
7950 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7951 xmlSchemaPIllegalAttrErr(ctxt,
7952 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007953 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007954 }
7955 attr = attr->next;
7956 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007957 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007958 /*
7959 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007960 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007961 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007962 attr = xmlSchemaGetPropNode(node, "memberTypes");
7963 if (attr != NULL) {
7964 const xmlChar *end;
7965 xmlChar *tmp;
7966 const xmlChar *localName, *nsName;
7967 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7968 xmlSchemaQNameRefPtr ref;
7969
7970 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7971 type->ref = cur;
7972 do {
7973 while (IS_BLANK_CH(*cur))
7974 cur++;
7975 end = cur;
7976 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7977 end++;
7978 if (end == cur)
7979 break;
7980 tmp = xmlStrndup(cur, end - cur);
7981 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7982 NULL, attr, BAD_CAST tmp, &nsName, NULL, &localName) == 0) {
7983 /*
7984 * Create the member type link.
7985 */
7986 link = (xmlSchemaTypeLinkPtr)
7987 xmlMalloc(sizeof(xmlSchemaTypeLink));
7988 if (link == NULL) {
7989 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7990 "allocating a type link", NULL);
7991 return (-1);
7992 }
7993 link->type = NULL;
7994 link->next = NULL;
7995 if (lastLink == NULL)
7996 type->memberTypes = link;
7997 else
7998 lastLink->next = link;
7999 lastLink = link;
8000 /*
8001 * Create a reference item.
8002 */
8003 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
8004 localName, nsName);
8005 if (ref == NULL) {
8006 FREE_AND_NULL(tmp)
8007 return (-1);
8008 }
8009 /*
8010 * Assign the reference to the link, it will be resolved
8011 * later during fixup of the union simple type.
8012 */
8013 link->type = (xmlSchemaTypePtr) ref;
8014 }
8015 FREE_AND_NULL(tmp)
8016 cur = end;
8017 } while (*cur != 0);
8018
8019 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008020 /*
8021 * And now for the children...
8022 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008023 child = node->children;
8024 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008025 /*
8026 * Add the annotation to the simple type ancestor.
8027 */
8028 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8029 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008031 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008032 if (IS_SCHEMA(child, "simpleType")) {
8033 xmlSchemaTypePtr subtype, last = NULL;
8034
8035 /*
8036 * Anchor the member types in the "subtypes" field of the
8037 * simple type.
8038 */
8039 while (IS_SCHEMA(child, "simpleType")) {
8040 subtype = (xmlSchemaTypePtr)
8041 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8042 if (subtype != NULL) {
8043 if (last == NULL) {
8044 type->subtypes = subtype;
8045 last = subtype;
8046 } else {
8047 last->next = subtype;
8048 last = subtype;
8049 }
8050 last->next = NULL;
8051 }
8052 child = child->next;
8053 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008054 }
8055 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008056 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008057 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8058 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
8059 }
8060 if ((attr == NULL) && (type->subtypes == NULL)) {
8061 /*
8062 * src-union-memberTypes-or-simpleTypes
8063 * Either the memberTypes [attribute] of the <union> element must
8064 * be non-empty or there must be at least one simpleType [child].
8065 */
8066 xmlSchemaPCustomErr(ctxt,
8067 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8068 NULL, NULL, node,
8069 "Either the attribute 'memberTypes' or "
8070 "at least one <simpleType> child must be present", NULL);
8071 }
8072 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008073}
8074
8075/**
8076 * xmlSchemaParseList:
8077 * @ctxt: a schema validation context
8078 * @schema: the schema being built
8079 * @node: a subtree containing XML Schema informations
8080 *
8081 * parse a XML schema List definition
8082 * *WARNING* this interface is highly subject to change
8083 *
William M. Bracke7091952004-05-11 15:09:58 +00008084 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008085 * 1 in case of success.
8086 */
8087static xmlSchemaTypePtr
8088xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008089 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008090{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008091 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008092 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008093 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008094
8095 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8096 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008097 /* Not a component, don't create it. */
8098 type = ctxt->ctxtType;
8099 /*
8100 * Mark the type as being of variety "list".
8101 */
8102 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008103 /*
8104 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8105 * then the ·simple ur-type definition·."
8106 */
8107 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008108 /*
8109 * Check for illegal attributes.
8110 */
8111 attr = node->properties;
8112 while (attr != NULL) {
8113 if (attr->ns == NULL) {
8114 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8115 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
8116 xmlSchemaPIllegalAttrErr(ctxt,
8117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008118 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008119 }
8120 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8121 xmlSchemaPIllegalAttrErr(ctxt,
8122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008123 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008124 }
8125 attr = attr->next;
8126 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008127
8128 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8129
William M. Brack2f2a6632004-08-20 23:09:47 +00008130 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008131 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8132 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008133 */
8134 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008135 node, "itemType", &(type->refNs), NULL, &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008136 /*
8137 * And now for the children...
8138 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008139 child = node->children;
8140 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008141 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8142 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008143 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008144 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008145 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008146 /*
8147 * src-list-itemType-or-simpleType
8148 * Either the itemType [attribute] or the <simpleType> [child] of
8149 * the <list> element must be present, but not both.
8150 */
8151 if (type->ref != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008152 xmlSchemaPCustomErr(ctxt,
8153 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008154 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008155 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008156 "are mutually exclusive", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008157 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008158 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008159 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008160 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008161 } else if (type->ref == NULL) {
8162 xmlSchemaPCustomErr(ctxt,
8163 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8164 NULL, NULL, node,
8165 "Either the attribute 'itemType' or the <simpleType> child "
8166 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008167 }
8168 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008169 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008170 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8171 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008172 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008173 if ((type->ref == NULL) &&
8174 (type->subtypes == NULL) &&
8175 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
8176 xmlSchemaPCustomErr(ctxt,
8177 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8178 NULL, NULL, node,
8179 "Either the attribute 'itemType' or the <simpleType> child "
8180 "must be present", NULL);
8181 }
8182 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008183}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008184
Daniel Veillard4255d502002-04-16 15:50:10 +00008185/**
8186 * xmlSchemaParseSimpleType:
8187 * @ctxt: a schema validation context
8188 * @schema: the schema being built
8189 * @node: a subtree containing XML Schema informations
8190 *
8191 * parse a XML schema Simple Type definition
8192 * *WARNING* this interface is highly subject to change
8193 *
William M. Bracke7091952004-05-11 15:09:58 +00008194 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008195 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008196 */
8197static xmlSchemaTypePtr
8198xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008199 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008200{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008201 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008202 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008203 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008204 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008205
8206 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8207 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008208
Daniel Veillardc0826a72004-08-10 14:17:33 +00008209 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008210 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008211 if (attr == NULL) {
8212 xmlSchemaPMissingAttrErr(ctxt,
8213 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008214 NULL, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008215 "name", NULL);
8216 return (NULL);
8217 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008218 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008219 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008220 return (NULL);
8221 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008222 }
8223
8224 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008225 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008226
Daniel Veillard01fa6152004-06-29 17:04:39 +00008227 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008228 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008229 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008230 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008231 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008232 if (type == NULL)
8233 return (NULL);
8234 type->node = node;
8235 type->type = XML_SCHEMA_TYPE_SIMPLE;
8236 /*
8237 * Check for illegal attributes.
8238 */
8239 attr = node->properties;
8240 while (attr != NULL) {
8241 if (attr->ns == NULL) {
8242 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
8243 xmlSchemaPIllegalAttrErr(ctxt,
8244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008245 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008246 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008247 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8248 xmlSchemaPIllegalAttrErr(ctxt,
8249 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008250 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008251 }
8252 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008253 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008254 } else {
8255 /*
8256 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008257 *
8258 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008259 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008260 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008261 if (type == NULL)
8262 return (NULL);
8263 type->node = node;
8264 type->type = XML_SCHEMA_TYPE_SIMPLE;
8265 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8266 /*
8267 * Check for illegal attributes.
8268 */
8269 attr = node->properties;
8270 while (attr != NULL) {
8271 if (attr->ns == NULL) {
8272 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8273 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008274 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008275 xmlSchemaPIllegalAttrErr(ctxt,
8276 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008277 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008278 }
8279 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8280 xmlSchemaPIllegalAttrErr(ctxt,
8281 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008282 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008283 }
8284 attr = attr->next;
8285 }
8286 /*
8287 * Attribute "final".
8288 */
8289 attr = xmlSchemaGetPropNode(node, "final");
8290 if (attr == NULL) {
8291 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8292 } else {
8293 attrValue = xmlSchemaGetProp(ctxt, node, "final");
8294 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8295 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
8296 XML_SCHEMAS_TYPE_FINAL_LIST,
8297 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8298
8299 xmlSchemaPSimpleTypeErr(ctxt,
8300 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008301 NULL, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008302 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008303 attrValue, NULL, NULL, NULL);
8304 }
8305 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008306 }
8307 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008308 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008309 /*
8310 * And now for the children...
8311 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008312 oldCtxtType = ctxt->ctxtType;
8313 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008314 ctxt->ctxtType = type;
8315 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008316 child = node->children;
8317 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008318 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8319 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008320 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008321 if (child == NULL) {
8322 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8323 NULL, type, node, child, NULL,
8324 "(annotation?, (restriction | list | union))");
8325 } else if (IS_SCHEMA(child, "restriction")) {
8326 xmlSchemaParseRestriction(ctxt, schema, child,
8327 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008328 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 } else if (IS_SCHEMA(child, "list")) {
8330 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008331 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008332 } else if (IS_SCHEMA(child, "union")) {
8333 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008334 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008335 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008336 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008337 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008338 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008339 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008340 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008341 ctxt->parentItem = oldParentItem;
8342 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008343
Daniel Veillard4255d502002-04-16 15:50:10 +00008344 return (type);
8345}
8346
Daniel Veillard4255d502002-04-16 15:50:10 +00008347/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008348 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008349 * @ctxt: a schema validation context
8350 * @schema: the schema being built
8351 * @node: a subtree containing XML Schema informations
8352 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008353 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008354 * *WARNING* this interface is highly subject to change
8355 *
William M. Bracke7091952004-05-11 15:09:58 +00008356 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008357 * 1 in case of success.
8358 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008359static xmlSchemaTreeItemPtr
8360xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8361 xmlSchemaPtr schema,
8362 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008363{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 xmlSchemaParticlePtr item;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008365 xmlNodePtr child = NULL;
8366 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008367 const xmlChar *ref = NULL, *refNs = NULL;
8368 int min, max;
8369
8370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8371 return (NULL);
8372
8373 attr = xmlSchemaGetPropNode(node, "ref");
8374 if (attr == NULL) {
8375 xmlSchemaPMissingAttrErr(ctxt,
8376 XML_SCHEMAP_S4S_ATTR_MISSING,
8377 NULL, NULL, node,
8378 "ref", NULL);
8379 return (NULL);
8380 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
8381 attr, &refNs, NULL, &ref) != 0) {
8382 return (NULL);
8383 }
8384 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8385 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8386 "(nonNegativeInteger | unbounded)");
8387 /*
8388 * Check for illegal attributes.
8389 */
8390 attr = node->properties;
8391 while (attr != NULL) {
8392 if (attr->ns == NULL) {
8393 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
8394 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8395 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8396 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
8397 xmlSchemaPIllegalAttrErr(ctxt,
8398 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8399 NULL, NULL, attr);
8400 }
8401 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8402 xmlSchemaPIllegalAttrErr(ctxt,
8403 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8404 NULL, NULL, attr);
8405 }
8406 attr = attr->next;
8407 }
8408 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8409 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8410 if (item == NULL)
8411 return (NULL);
8412 /*
8413 * Create a reference item as the term; it will be substituted for
8414 * the model group after the reference has been resolved.
8415 */
8416 item->children = (xmlSchemaTreeItemPtr)
8417 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8418 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8419 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8420 /*
8421 * And now for the children...
8422 */
8423 child = node->children;
8424 /* TODO: Is annotation even allowed for a model group reference? */
8425 if (IS_SCHEMA(child, "annotation")) {
8426 /*
8427 * TODO: What to do exactly with the annotation?
8428 */
8429 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8430 child = child->next;
8431 }
8432 if (child != NULL) {
8433 xmlSchemaPContentErr(ctxt,
8434 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8435 NULL, NULL, node, child, NULL,
8436 "(annotation?)");
8437 }
8438 /*
8439 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8440 */
8441 if ((min == 0) && (max == 0))
8442 return (NULL);
8443 if (ctxt->assemble != NULL)
8444 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8445 return ((xmlSchemaTreeItemPtr) item);
8446}
8447
8448/**
8449 * xmlSchemaParseModelGroupDefinition:
8450 * @ctxt: a schema validation context
8451 * @schema: the schema being built
8452 * @node: a subtree containing XML Schema informations
8453 *
8454 * Parses a XML schema model group definition.
8455 * *WARNING* this interface is highly subject to change
8456 *
8457 * Returns -1 in case of error, 0 if the declaration is improper and
8458 * 1 in case of success.
8459 */
8460static xmlSchemaModelGroupDefPtr
8461xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8462 xmlSchemaPtr schema,
8463 xmlNodePtr node)
8464{
8465 xmlSchemaModelGroupDefPtr item;
8466 xmlNodePtr child = NULL;
8467 xmlAttrPtr attr;
8468 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008469
8470 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008471 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008472
8473 attr = xmlSchemaGetPropNode(node, "name");
8474 if (attr == NULL) {
8475 xmlSchemaPMissingAttrErr(ctxt,
8476 XML_SCHEMAP_S4S_ATTR_MISSING,
8477 NULL, NULL, node,
8478 "name", NULL);
8479 return (NULL);
8480 } else if (xmlSchemaPValAttrNode(ctxt,
8481 NULL, NULL, attr,
8482 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8483 return (NULL);
8484 }
8485 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8486 if (item == NULL)
8487 return (NULL);
8488 /*
8489 * Check for illegal attributes.
8490 */
8491 attr = node->properties;
8492 while (attr != NULL) {
8493 if (attr->ns == NULL) {
8494 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8495 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
8496 xmlSchemaPIllegalAttrErr(ctxt,
8497 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8498 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008499 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008500 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8501 xmlSchemaPIllegalAttrErr(ctxt,
8502 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8503 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008504 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008505 attr = attr->next;
8506 }
8507 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8508 /*
8509 * And now for the children...
8510 */
8511 child = node->children;
8512 if (IS_SCHEMA(child, "annotation")) {
8513 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8514 child = child->next;
8515 }
8516 if (IS_SCHEMA(child, "all")) {
8517 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8518 XML_SCHEMA_TYPE_ALL, 0);
8519 child = child->next;
8520 } else if (IS_SCHEMA(child, "choice")) {
8521 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8522 XML_SCHEMA_TYPE_CHOICE, 0);
8523 child = child->next;
8524 } else if (IS_SCHEMA(child, "sequence")) {
8525 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8526 XML_SCHEMA_TYPE_SEQUENCE, 0);
8527 child = child->next;
8528 }
8529 if (child != NULL) {
8530 xmlSchemaPContentErr(ctxt,
8531 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8532 NULL, NULL, node, child, NULL,
8533 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008534 }
8535
8536 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008537}
8538
8539/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008540 * xmlSchemaCleanupDoc:
8541 * @ctxt: a schema validation context
8542 * @node: the root of the document.
8543 *
8544 * removes unwanted nodes in a schemas document tree
8545 */
8546static void
8547xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8548{
8549 xmlNodePtr delete, cur;
8550
8551 if ((ctxt == NULL) || (root == NULL)) return;
8552
8553 /*
8554 * Remove all the blank text nodes
8555 */
8556 delete = NULL;
8557 cur = root;
8558 while (cur != NULL) {
8559 if (delete != NULL) {
8560 xmlUnlinkNode(delete);
8561 xmlFreeNode(delete);
8562 delete = NULL;
8563 }
8564 if (cur->type == XML_TEXT_NODE) {
8565 if (IS_BLANK_NODE(cur)) {
8566 if (xmlNodeGetSpacePreserve(cur) != 1) {
8567 delete = cur;
8568 }
8569 }
8570 } else if ((cur->type != XML_ELEMENT_NODE) &&
8571 (cur->type != XML_CDATA_SECTION_NODE)) {
8572 delete = cur;
8573 goto skip_children;
8574 }
8575
8576 /*
8577 * Skip to next node
8578 */
8579 if (cur->children != NULL) {
8580 if ((cur->children->type != XML_ENTITY_DECL) &&
8581 (cur->children->type != XML_ENTITY_REF_NODE) &&
8582 (cur->children->type != XML_ENTITY_NODE)) {
8583 cur = cur->children;
8584 continue;
8585 }
8586 }
8587 skip_children:
8588 if (cur->next != NULL) {
8589 cur = cur->next;
8590 continue;
8591 }
8592
8593 do {
8594 cur = cur->parent;
8595 if (cur == NULL)
8596 break;
8597 if (cur == root) {
8598 cur = NULL;
8599 break;
8600 }
8601 if (cur->next != NULL) {
8602 cur = cur->next;
8603 break;
8604 }
8605 } while (cur != NULL);
8606 }
8607 if (delete != NULL) {
8608 xmlUnlinkNode(delete);
8609 xmlFreeNode(delete);
8610 delete = NULL;
8611 }
8612}
8613
William M. Brack2f2a6632004-08-20 23:09:47 +00008614
8615/**
8616 * xmlSchemaImportSchema
8617 *
8618 * @ctxt: a schema validation context
8619 * @schemaLocation: an URI defining where to find the imported schema
8620 *
8621 * import a XML schema
8622 * *WARNING* this interface is highly subject to change
8623 *
8624 * Returns -1 in case of error and 1 in case of success.
8625 */
8626#if 0
8627static xmlSchemaImportPtr
8628xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8629 const xmlChar *schemaLocation)
8630{
8631 xmlSchemaImportPtr import;
8632 xmlSchemaParserCtxtPtr newctxt;
8633
8634 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8635 if (newctxt == NULL) {
8636 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8637 NULL);
8638 return (NULL);
8639 }
8640 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8641 /* Keep the same dictionnary for parsing, really */
8642 xmlDictReference(ctxt->dict);
8643 newctxt->dict = ctxt->dict;
8644 newctxt->includes = 0;
8645 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8646
8647 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8648 ctxt->userData);
8649
8650 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8651 if (import == NULL) {
8652 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8653 NULL);
8654 xmlSchemaFreeParserCtxt(newctxt);
8655 return (NULL);
8656 }
8657
8658 memset(import, 0, sizeof(xmlSchemaImport));
8659 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8660 import->schema = xmlSchemaParse(newctxt);
8661
8662 if (import->schema == NULL) {
8663 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008664 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008665 "Failed to import schema from location \"%s\".\n",
8666 schemaLocation, NULL);
8667
8668 xmlSchemaFreeParserCtxt(newctxt);
8669 /* The schemaLocation is held by the dictionary.
8670 if (import->schemaLocation != NULL)
8671 xmlFree((xmlChar *)import->schemaLocation);
8672 */
8673 xmlFree(import);
8674 return NULL;
8675 }
8676
8677 xmlSchemaFreeParserCtxt(newctxt);
8678 return import;
8679}
8680#endif
8681
8682static void
8683xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8684{
8685 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8686 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8687
8688 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8689 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8690
8691 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8692 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8693 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8694 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8695 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8696 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8697 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8698 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8699
8700 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8701 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8702 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8703 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8704 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8705 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8706}
8707
8708static void
8709xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
8710 xmlSchemaPtr schema,
8711 xmlNodePtr node)
8712{
8713 xmlAttrPtr attr;
8714 const xmlChar *val;
8715
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008716 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8717 if (schema->version == NULL)
8718 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8719 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8720 else
8721 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8722 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8723
William M. Brack2f2a6632004-08-20 23:09:47 +00008724 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
8725 if (attr != NULL) {
8726 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8727 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8728 XML_SCHEMAS_QUALIF_ELEM) != 0) {
8729 xmlSchemaPSimpleTypeErr(ctxt,
8730 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
8731 NULL, NULL, (xmlNodePtr) attr, NULL,
8732 "(qualified | unqualified)", val, NULL, NULL, NULL);
8733 }
8734 }
8735
8736 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
8737 if (attr != NULL) {
8738 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8739 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8740 XML_SCHEMAS_QUALIF_ATTR) != 0) {
8741 xmlSchemaPSimpleTypeErr(ctxt,
8742 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
8743 NULL, NULL, (xmlNodePtr) attr, NULL,
8744 "(qualified | unqualified)", val, NULL, NULL, NULL);
8745 }
8746 }
8747
8748 attr = xmlSchemaGetPropNode(node, "finalDefault");
8749 if (attr != NULL) {
8750 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8751 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8752 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8753 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8754 -1,
8755 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8756 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8757 xmlSchemaPSimpleTypeErr(ctxt,
8758 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8759 NULL, NULL, (xmlNodePtr) attr, NULL,
8760 "(#all | List of (extension | restriction | list | union))",
8761 val, NULL, NULL, NULL);
8762 }
8763 }
8764
8765 attr = xmlSchemaGetPropNode(node, "blockDefault");
8766 if (attr != NULL) {
8767 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8768 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8769 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8770 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8771 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8772 xmlSchemaPSimpleTypeErr(ctxt,
8773 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8774 NULL, NULL, (xmlNodePtr) attr, NULL,
8775 "(#all | List of (extension | restriction | substitution))",
8776 val, NULL, NULL, NULL);
8777 }
8778 }
8779}
8780
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008781/**
8782 * xmlSchemaParseSchemaTopLevel:
8783 * @ctxt: a schema validation context
8784 * @schema: the schemas
8785 * @nodes: the list of top level nodes
8786 *
8787 * Returns the internal XML Schema structure built from the resource or
8788 * NULL in case of error
8789 */
8790static void
8791xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8792 xmlSchemaPtr schema, xmlNodePtr nodes)
8793{
8794 xmlNodePtr child;
8795 xmlSchemaAnnotPtr annot;
8796
8797 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8798 return;
8799
8800 child = nodes;
8801 while ((IS_SCHEMA(child, "include")) ||
8802 (IS_SCHEMA(child, "import")) ||
8803 (IS_SCHEMA(child, "redefine")) ||
8804 (IS_SCHEMA(child, "annotation"))) {
8805 if (IS_SCHEMA(child, "annotation")) {
8806 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8807 if (schema->annot == NULL)
8808 schema->annot = annot;
8809 else
8810 xmlSchemaFreeAnnot(annot);
8811 } else if (IS_SCHEMA(child, "import")) {
8812 xmlSchemaParseImport(ctxt, schema, child);
8813 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008814 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008815 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008816 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008817 } else if (IS_SCHEMA(child, "redefine")) {
8818 TODO
8819 }
8820 child = child->next;
8821 }
8822 while (child != NULL) {
8823 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008824 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008825 child = child->next;
8826 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008827 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008828 child = child->next;
8829 } else if (IS_SCHEMA(child, "element")) {
8830 xmlSchemaParseElement(ctxt, schema, child, 1);
8831 child = child->next;
8832 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008833 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008834 child = child->next;
8835 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008836 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008837 child = child->next;
8838 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008839 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008840 child = child->next;
8841 } else if (IS_SCHEMA(child, "notation")) {
8842 xmlSchemaParseNotation(ctxt, schema, child);
8843 child = child->next;
8844 } else {
8845 xmlSchemaPErr2(ctxt, NULL, child,
8846 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008847 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008848 child->name, NULL);
8849 child = child->next;
8850 }
8851 while (IS_SCHEMA(child, "annotation")) {
8852 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8853 if (schema->annot == NULL)
8854 schema->annot = annot;
8855 else
8856 xmlSchemaFreeAnnot(annot);
8857 child = child->next;
8858 }
8859 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008860 ctxt->parentItem = NULL;
8861 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008862}
8863
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864static xmlSchemaImportPtr
8865xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
8866 xmlHashTablePtr *imports,
8867 const xmlChar *nsName)
8868{
8869 xmlSchemaImportPtr ret;
8870
8871 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008872 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008873 if (*imports == NULL) {
8874 xmlSchemaPCustomErr(ctxt,
8875 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8876 NULL, NULL, (xmlNodePtr) ctxt->doc,
8877 "Internal error: failed to build the import table",
8878 NULL);
8879 return (NULL);
8880 }
8881 }
8882 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8883 if (ret == NULL) {
8884 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8885 return (NULL);
8886 }
8887 memset(ret, 0, sizeof(xmlSchemaImport));
8888 if (nsName == NULL)
8889 nsName = XML_SCHEMAS_NO_NAMESPACE;
8890 xmlHashAddEntry(*imports, nsName, ret);
8891
8892 return (ret);
8893}
8894
8895static int
8896xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008897 xmlSchemaPtr schema,
8898 xmlNodePtr node,
8899 const xmlChar *nsName,
8900 const xmlChar *location,
8901 xmlDocPtr *doc,
8902 const xmlChar **targetNamespace,
8903 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904{
8905 xmlParserCtxtPtr parserCtxt;
8906 xmlSchemaImportPtr import;
8907 const xmlChar *ns;
8908 xmlNodePtr root;
8909
8910 /*
8911 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8912 * <xsi:noNamespaceSchemaLocation>.
8913 */
8914 *doc = NULL;
8915 /*
8916 * Given that the schemaLocation [attribute] is only a hint, it is open
8917 * to applications to ignore all but the first <import> for a given
8918 * namespace, regardless of the ·actual value· of schemaLocation, but
8919 * such a strategy risks missing useful information when new
8920 * schemaLocations are offered.
8921 *
8922 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8923 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8924 * valid or not.
8925 * We will follow XSV here.
8926 */
8927 if (location == NULL) {
8928 /*
8929 * Schema Document Location Strategy:
8930 *
8931 * 3 Based on the namespace name, identify an existing schema document,
8932 * either as a resource which is an XML document or a <schema> element
8933 * information item, in some local schema repository;
8934 *
8935 * 5 Attempt to resolve the namespace name to locate such a resource.
8936 *
8937 * NOTE: Those stategies are not supported, so we will skip.
8938 */
8939 return (0);
8940 }
8941 if (nsName == NULL)
8942 ns = XML_SCHEMAS_NO_NAMESPACE;
8943 else
8944 ns = nsName;
8945
8946 import = xmlHashLookup(schema->schemasImports, ns);
8947 if (import != NULL) {
8948 /*
8949 * There was a valid resource for the specified namespace already
8950 * defined, so skip.
8951 * TODO: This might be changed someday to allow import of
8952 * components from multiple documents for a single target namespace.
8953 */
8954 return (0);
8955 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008956
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008957 /*
8958 * Schema Document Location Strategy:
8959 *
8960 * 2 Based on the location URI, identify an existing schema document,
8961 * either as a resource which is an XML document or a <schema> element
8962 * information item, in some local schema repository;
8963 *
8964 * 4 Attempt to resolve the location URI, to locate a resource on the
8965 * web which is or contains or references a <schema> element;
8966 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8967 *
8968 */
8969 if ((absolute == 0) && (node != NULL)) {
8970 xmlChar *base, *URI;
8971
8972 base = xmlNodeGetBase(node->doc, node);
8973 if (base == NULL) {
8974 URI = xmlBuildURI(location, node->doc->URL);
8975 } else {
8976 URI = xmlBuildURI(location, base);
8977 xmlFree(base);
8978 }
8979 if (URI != NULL) {
8980 location = xmlDictLookup(ctxt->dict, URI, -1);
8981 xmlFree(URI);
8982 }
8983 }
8984 parserCtxt = xmlNewParserCtxt();
8985 if (parserCtxt == NULL) {
8986 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8987 "allocating a parser context", NULL);
8988 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008989 }
8990
8991 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8992 xmlDictFree(parserCtxt->dict);
8993 parserCtxt->dict = ctxt->dict;
8994 xmlDictReference(parserCtxt->dict);
8995 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008996
8997 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8998 NULL, SCHEMAS_PARSE_OPTIONS);
8999
9000 /*
9001 * 2.1 The referent is (a fragment of) a resource which is an
9002 * XML document (see clause 1.1), which in turn corresponds to
9003 * a <schema> element information item in a well-formed information
9004 * set, which in turn corresponds to a valid schema.
9005 * TODO: What to do with the "fragment" stuff?
9006 *
9007 * 2.2 The referent is a <schema> element information item in
9008 * a well-formed information set, which in turn corresponds
9009 * to a valid schema.
9010 * NOTE: 2.2 won't apply, since only XML documents will be processed
9011 * here.
9012 */
9013 if (*doc == NULL) {
9014 xmlErrorPtr lerr;
9015 /*
9016 * It is *not* an error for the application schema reference
9017 * strategy to fail.
9018 *
9019 * If the doc is NULL and the parser error is an IO error we
9020 * will assume that the resource could not be located or accessed.
9021 *
9022 * TODO: Try to find specific error codes to react only on
9023 * localisation failures.
9024 *
9025 * TODO, FIXME: Check the spec: is a namespace added to the imported
9026 * namespaces, even if the schemaLocation did not provide
9027 * a resource? I guess so, since omitting the "schemaLocation"
9028 * attribute, imports a namespace as well.
9029 */
9030 lerr = xmlGetLastError();
9031 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
9032 xmlFreeParserCtxt(parserCtxt);
9033 return(0);
9034 }
9035
9036 xmlSchemaPCustomErr(ctxt,
9037 XML_SCHEMAP_SRC_IMPORT_2_1,
9038 NULL, NULL, node,
9039 "Failed to parse the resource '%s' for import",
9040 location);
9041 xmlFreeParserCtxt(parserCtxt);
9042 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9043 }
9044 xmlFreeParserCtxt(parserCtxt);
9045
9046 root = xmlDocGetRootElement(*doc);
9047 if (root == NULL) {
9048 xmlSchemaPCustomErr(ctxt,
9049 XML_SCHEMAP_SRC_IMPORT_2_1,
9050 NULL, NULL, node,
9051 "The XML document '%s' to be imported has no document "
9052 "element", location);
9053 xmlFreeDoc(*doc);
9054 *doc = NULL;
9055 return (XML_SCHEMAP_SRC_IMPORT_2_1);
9056 }
9057
9058 xmlSchemaCleanupDoc(ctxt, root);
9059
9060 if (!IS_SCHEMA(root, "schema")) {
9061 xmlSchemaPCustomErr(ctxt,
9062 XML_SCHEMAP_SRC_IMPORT_2_1,
9063 NULL, NULL, node,
9064 "The XML document '%s' to be imported is not a XML schema document",
9065 location);
9066 xmlFreeDoc(*doc);
9067 *doc = NULL;
9068 return (XML_SCHEMAP_SRC_IMPORT_2_1);
9069 }
9070 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
9071 /*
9072 * Schema Representation Constraint: Import Constraints and Semantics
9073 */
9074 if (nsName == NULL) {
9075 if (*targetNamespace != NULL) {
9076 xmlSchemaPCustomErr(ctxt,
9077 XML_SCHEMAP_SRC_IMPORT_3_2,
9078 NULL, NULL, node,
9079 "The XML schema to be imported is not expected "
9080 "to have a target namespace; this differs from "
9081 "its target namespace of '%s'", *targetNamespace);
9082 xmlFreeDoc(*doc);
9083 *doc = NULL;
9084 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9085 }
9086 } else {
9087 if (*targetNamespace == NULL) {
9088 xmlSchemaPCustomErr(ctxt,
9089 XML_SCHEMAP_SRC_IMPORT_3_1,
9090 NULL, NULL, node,
9091 "The XML schema to be imported is expected to have a target "
9092 "namespace of '%s'", nsName);
9093 xmlFreeDoc(*doc);
9094 *doc = NULL;
9095 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9096 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
9097 xmlSchemaPCustomErrExt(ctxt,
9098 XML_SCHEMAP_SRC_IMPORT_3_1,
9099 NULL, NULL, node,
9100 "The XML schema to be imported is expected to have a "
9101 "target namespace of '%s'; this differs from "
9102 "its target namespace of '%s'",
9103 nsName, *targetNamespace, NULL);
9104 xmlFreeDoc(*doc);
9105 *doc = NULL;
9106 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9107 }
9108 }
9109
9110 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
9111 if (import == NULL) {
9112 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9113 NULL, NULL, NULL,
9114 "Internal error: xmlSchemaAcquireSchemaDoc, "
9115 "failed to build import table", NULL);
9116 xmlFreeDoc(*doc);
9117 *doc = NULL;
9118 return (-1);
9119 }
9120 import->schemaLocation = location;
9121 import->doc = *doc;
9122 return (0);
9123}
William M. Brack2f2a6632004-08-20 23:09:47 +00009124
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009125static void
9126xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9127 xmlSchemaPtr schema,
9128 const xmlChar *targetNamespace,
9129 xmlNodePtr node)
9130{
9131 const xmlChar *oldURL, **oldLocImps, *oldTNS;
9132 int oldFlags, oldNumLocImps, oldSizeLocImps;
9133
9134 /*
9135 * Save and reset the context & schema.
9136 */
9137 oldURL = pctxt->URL;
9138 /* TODO: Is using the doc->URL here correct? */
9139 pctxt->URL = node->doc->URL;
9140 oldLocImps = pctxt->localImports;
9141 pctxt->localImports = NULL;
9142 oldNumLocImps = pctxt->nbLocalImports;
9143 pctxt->nbLocalImports = 0;
9144 oldSizeLocImps = pctxt->sizeLocalImports;
9145 pctxt->sizeLocalImports = 0;
9146 oldFlags = schema->flags;
9147 xmlSchemaClearSchemaDefaults(schema);
9148 oldTNS = schema->targetNamespace;
9149 schema->targetNamespace = targetNamespace;
9150 /*
9151 * Parse the schema.
9152 */
9153 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9154 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9155 /*
9156 * Restore the context & schema.
9157 */
9158 schema->flags = oldFlags;
9159 schema->targetNamespace = oldTNS;
9160 if (pctxt->localImports != NULL)
9161 xmlFree((xmlChar *) pctxt->localImports);
9162 pctxt->localImports = oldLocImps;
9163 pctxt->nbLocalImports = oldNumLocImps;
9164 pctxt->sizeLocalImports = oldSizeLocImps;
9165 pctxt->URL = oldURL;
9166}
9167
William M. Brack2f2a6632004-08-20 23:09:47 +00009168/**
9169 * xmlSchemaParseImport:
9170 * @ctxt: a schema validation context
9171 * @schema: the schema being built
9172 * @node: a subtree containing XML Schema informations
9173 *
9174 * parse a XML schema Import definition
9175 * *WARNING* this interface is highly subject to change
9176 *
9177 * Returns 0 in case of success, a positive error code if
9178 * not valid and -1 in case of an internal error.
9179 */
9180static int
9181xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9182 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009183{
9184 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009185 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009186 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009187 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 xmlAttrPtr attr;
9189 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009190 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009191
9192 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9193 return (-1);
9194
9195 /*
9196 * Check for illegal attributes.
9197 */
9198 attr = node->properties;
9199 while (attr != NULL) {
9200 if (attr->ns == NULL) {
9201 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9202 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9203 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9204 xmlSchemaPIllegalAttrErr(ctxt,
9205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9206 NULL, NULL, attr);
9207 }
9208 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9209 xmlSchemaPIllegalAttrErr(ctxt,
9210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9211 NULL, NULL, attr);
9212 }
9213 attr = attr->next;
9214 }
9215 /*
9216 * Extract and validate attributes.
9217 */
9218 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9219 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009220 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009221 xmlSchemaPSimpleTypeErr(ctxt,
9222 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9223 NULL, NULL, node,
9224 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009225 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009226 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9227 }
9228
9229 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9230 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9231 &schemaLocation) != 0) {
9232 xmlSchemaPSimpleTypeErr(ctxt,
9233 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9234 NULL, NULL, node,
9235 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009236 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009237 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
9238 }
9239 /*
9240 * And now for the children...
9241 */
9242 child = node->children;
9243 if (IS_SCHEMA(child, "annotation")) {
9244 /*
9245 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009246 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009247 */
9248 child = child->next;
9249 }
9250 if (child != NULL) {
9251 xmlSchemaPContentErr(ctxt,
9252 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9253 NULL, NULL, node, child, NULL,
9254 "(annotation?)");
9255 }
9256 /*
9257 * Apply additional constraints.
9258 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009259 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009260 /*
9261 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9262 * must not match the ·actual value· of the enclosing <schema>'s
9263 * targetNamespace [attribute].
9264 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009265 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009266 xmlSchemaPCustomErr(ctxt,
9267 XML_SCHEMAP_SRC_IMPORT_1_1,
9268 NULL, NULL, node,
9269 "The value of the attribute 'namespace' must not match "
9270 "the target namespace '%s' of the importing schema",
9271 schema->targetNamespace);
9272 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9273 }
9274 } else {
9275 /*
9276 * 1.2 If the namespace [attribute] is not present, then the enclosing
9277 * <schema> must have a targetNamespace [attribute].
9278 */
9279 if (schema->targetNamespace == NULL) {
9280 xmlSchemaPCustomErr(ctxt,
9281 XML_SCHEMAP_SRC_IMPORT_1_2,
9282 NULL, NULL, node,
9283 "The attribute 'namespace' must be existent if "
9284 "the importing schema has no target namespace",
9285 NULL);
9286 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9287 }
9288 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009289 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009290 * Add the namespace to the list of locally imported namespace.
9291 */
9292 if (ctxt->localImports == NULL) {
9293 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
9294 sizeof(const xmlChar*));
9295 ctxt->sizeLocalImports = 10;
9296 ctxt->nbLocalImports = 0;
9297 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9298 ctxt->sizeLocalImports *= 2;
9299 ctxt->localImports = (const xmlChar **) xmlRealloc(
9300 (xmlChar **) ctxt->localImports,
9301 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9302 }
9303 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9304 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009305 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009306 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009307 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009308 schemaLocation, &doc, &targetNamespace, 0);
9309 if (ret != 0) {
9310 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009311 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009312 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009313 } else if (doc != NULL) {
9314 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9315 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009316 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009317
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009318 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009319}
9320
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009321/**
9322 * xmlSchemaParseInclude:
9323 * @ctxt: a schema validation context
9324 * @schema: the schema being built
9325 * @node: a subtree containing XML Schema informations
9326 *
9327 * parse a XML schema Include definition
9328 *
William M. Bracke7091952004-05-11 15:09:58 +00009329 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009330 * 1 in case of success.
9331 */
9332static int
9333xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9334 xmlNodePtr node)
9335{
9336 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009337 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009338 xmlDocPtr doc = NULL;
9339 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009340 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009341 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009342 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009343 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009344
9345
9346 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9347 return (-1);
9348
9349 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009350 * Check for illegal attributes.
9351 */
9352 attr = node->properties;
9353 while (attr != NULL) {
9354 if (attr->ns == NULL) {
9355 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9356 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9357 xmlSchemaPIllegalAttrErr(ctxt,
9358 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9359 NULL, NULL, attr);
9360 }
9361 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9362 xmlSchemaPIllegalAttrErr(ctxt,
9363 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9364 NULL, NULL, attr);
9365 }
9366 attr = attr->next;
9367 }
9368 /*
9369 * Extract and validate attributes.
9370 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009371 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009372 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009373 * Preliminary step, extract the URI-Reference for the include and
9374 * make an URI from the base.
9375 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009376 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9377 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009378 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009379 xmlChar *uri = NULL;
9380
9381 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9382 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009383 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009384 base = xmlNodeGetBase(node->doc, node);
9385 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009386 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009387 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009388 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009389 xmlFree(base);
9390 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009391 if (uri == NULL) {
9392 xmlSchemaPErr(ctxt,
9393 node,
9394 XML_SCHEMAP_INTERNAL,
9395 "Internal error: xmlSchemaParseInclude, "
9396 "could not build an URI from the schemaLocation.\n",
9397 NULL, NULL);
9398 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009399 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009400 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9401 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009402 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009403 xmlSchemaPMissingAttrErr(ctxt,
9404 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9405 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009406 goto exit_invalid;
9407 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009408 /*
9409 * And now for the children...
9410 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009411 child = node->children;
9412 while (IS_SCHEMA(child, "annotation")) {
9413 /*
9414 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009415 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009416 */
9417 child = child->next;
9418 }
9419 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009420 xmlSchemaPContentErr(ctxt,
9421 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9422 NULL, NULL, node, child, NULL,
9423 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009424 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009425 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009426 * Report self-inclusion.
9427 */
9428 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9429 xmlSchemaPCustomErr(ctxt,
9430 XML_SCHEMAP_SRC_INCLUDE,
9431 NULL, NULL, node,
9432 "The schema document '%s' cannot include itself.",
9433 schemaLocation);
9434 return (XML_SCHEMAP_SRC_INCLUDE);
9435 }
9436 /*
9437 * Check if this one was already processed to avoid incorrect
9438 * duplicate component errors and infinite circular inclusion.
9439 */
9440 include = schema->includes;
9441 while (include != NULL) {
9442 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9443 targetNamespace = include->origTargetNamespace;
9444 if (targetNamespace == NULL) {
9445 /*
9446 * Chameleon include: skip only if it was build for
9447 * the targetNamespace of the including schema.
9448 */
9449 if (xmlStrEqual(schema->targetNamespace,
9450 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009451 goto check_targetNamespace;
9452 }
9453 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009454 goto check_targetNamespace;
9455 }
9456 }
9457 include = include->next;
9458 }
9459 /*
9460 * First step is to parse the input document into an DOM/Infoset
9461 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009462 */
9463 parserCtxt = xmlNewParserCtxt();
9464 if (parserCtxt == NULL) {
9465 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9466 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009467 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009468 }
9469
9470 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9471 xmlDictFree(parserCtxt->dict);
9472 parserCtxt->dict = ctxt->dict;
9473 xmlDictReference(parserCtxt->dict);
9474 }
9475
9476 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
9477 NULL, SCHEMAS_PARSE_OPTIONS);
9478 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009479 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009480 /*
9481 * TODO: It is not an error for the ·actual value· of the
9482 * schemaLocation [attribute] to fail to resolve it all, in which
9483 * case no corresponding inclusion is performed.
9484 * So do we need a warning report here?
9485 */
9486 xmlSchemaPCustomErr(ctxt,
9487 XML_SCHEMAP_FAILED_LOAD,
9488 NULL, NULL, node,
9489 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009490 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009491 }
9492
9493 /*
9494 * Then extract the root of the schema
9495 */
9496 root = xmlDocGetRootElement(doc);
9497 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009498 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009499 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009500 NULL, NULL, node,
9501 "The included document '%s' has no document "
9502 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009503 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009504 }
9505
9506 /*
9507 * Remove all the blank text nodes
9508 */
9509 xmlSchemaCleanupDoc(ctxt, root);
9510
9511 /*
9512 * Check the schemas top level element
9513 */
9514 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009515 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009516 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009517 NULL, NULL, node,
9518 "The document '%s' to be included is not a schema document",
9519 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009520 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009521 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009522
William M. Brack2f2a6632004-08-20 23:09:47 +00009523 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009524 /*
9525 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9526 * value· is identical to the ·actual value· of the targetNamespace
9527 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9528 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009530 if (targetNamespace != NULL) {
9531 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009532 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009533 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009534 NULL, NULL, node,
9535 "The target namespace of the included schema "
9536 "'%s' has to be absent, since the including schema "
9537 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009538 schemaLocation);
9539 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009540 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9541 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009542 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009543 NULL, NULL, node,
9544 "The target namespace '%s' of the included schema '%s' "
9545 "differs from '%s' of the including schema",
9546 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009547 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009548 }
9549 } else if (schema->targetNamespace != NULL) {
9550 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
9551 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
9552 } else
9553 wasConvertingNs = 1;
9554 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009555
9556 if (include != NULL)
9557 goto exit;
9558
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009559 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009560 * URGENT TODO: If the schema is a chameleon-include then copy the
9561 * components into the including schema and modify the targetNamespace
9562 * of those components, do nothing otherwise.
9563 * NOTE: This is currently worked-around by compiling the chameleon
9564 * for every destinct including targetNamespace; thus not performant at
9565 * the moment.
9566 * TODO: Check when the namespace in wildcards for chameleons needs
9567 * to be converted: before we built wildcard intersections or after.
9568 */
9569 /*
9570 * Register the include.
9571 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009572 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9573 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009574 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9575 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009576 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009577 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009578 include->next = schema->includes;
9579 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009580 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009581 * TODO: Use the resolved URI for the this location, since it might
9582 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009583 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009584 include->schemaLocation = schemaLocation;
9585 include->doc = doc;
9586 /*
9587 * In case of chameleons, the original target namespace will differ
9588 * from the resulting namespace.
9589 */
9590 include->origTargetNamespace = targetNamespace;
9591 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009592#ifdef DEBUG_INCLUDES
9593 if (targetNamespace != schema->targetNamespace)
9594 xmlGenericError(xmlGenericErrorContext,
9595 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9596 " into TNS '%s'\n", schemaLocation,
9597 targetNamespace, schema->targetNamespace);
9598 else
9599 xmlGenericError(xmlGenericErrorContext,
9600 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9601 targetNamespace);
9602#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009603 /*
9604 * Compile the included schema.
9605 */
9606 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9607
9608exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009609 /*
9610 * Remove the converting flag.
9611 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009612 if ((wasConvertingNs == 0) &&
9613 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009614 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009615 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009616
9617exit_invalid:
9618 if (doc != NULL) {
9619 if (include != NULL)
9620 include->doc = NULL;
9621 xmlFreeDoc(doc);
9622 }
9623 return (ctxt->err);
9624
9625exit_failure:
9626 if (doc != NULL) {
9627 if (include != NULL)
9628 include->doc = NULL;
9629 xmlFreeDoc(doc);
9630 }
9631 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009632}
9633
9634/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009635 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009636 * @ctxt: a schema validation context
9637 * @schema: the schema being built
9638 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009639 * @type: the "compositor" type
9640 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009641 *
9642 * parse a XML schema Sequence definition
9643 * *WARNING* this interface is highly subject to change
9644 *
William M. Bracke7091952004-05-11 15:09:58 +00009645 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009646 * 1 in case of success.
9647 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009648static xmlSchemaTreeItemPtr
9649xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9650 xmlNodePtr node, xmlSchemaTypeType type,
9651 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009652{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009653 xmlSchemaModelGroupPtr item;
9654 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009655 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009656 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009657 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009658 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009659
9660 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009661 return (NULL);
9662 /*
9663 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009665 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9666 if (item == NULL)
9667 return (NULL);
9668
9669 if (withParticle) {
9670 if (type == XML_SCHEMA_TYPE_ALL) {
9671 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
9672 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
9673 } else {
9674 /* choice + sequence */
9675 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
9676 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9677 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009678 }
9679 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009680 /*
9681 * Create a particle
9682 */
9683 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9684 if (particle == NULL)
9685 return (NULL);
9686 particle->children = (xmlSchemaTreeItemPtr) item;
9687 /*
9688 * Check for illegal attributes.
9689 */
9690 attr = node->properties;
9691 while (attr != NULL) {
9692 if (attr->ns == NULL) {
9693 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9694 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9695 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
9696 xmlSchemaPIllegalAttrErr(ctxt,
9697 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9698 NULL, NULL, attr);
9699 }
9700 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009701 xmlSchemaPIllegalAttrErr(ctxt,
9702 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009703 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009704 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009705 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009706 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009707 } else {
9708 /*
9709 * Check for illegal attributes.
9710 */
9711 attr = node->properties;
9712 while (attr != NULL) {
9713 if (attr->ns == NULL) {
9714 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9715 xmlSchemaPIllegalAttrErr(ctxt,
9716 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9717 NULL, NULL, attr);
9718 }
9719 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9720 xmlSchemaPIllegalAttrErr(ctxt,
9721 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9722 NULL, NULL, attr);
9723 }
9724 attr = attr->next;
9725 }
9726
William M. Brack2f2a6632004-08-20 23:09:47 +00009727 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009728
William M. Brack2f2a6632004-08-20 23:09:47 +00009729 /*
9730 * Extract and validate attributes.
9731 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009732 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009733 /*
9734 * And now for the children...
9735 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009736 child = node->children;
9737 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009738 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009739 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009740 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009741 oldcontainer = ctxt->container;
9742 ctxt->container = container;
9743 if (type == XML_SCHEMA_TYPE_ALL) {
9744 xmlSchemaParticlePtr part, last = NULL;
9745
9746 while (IS_SCHEMA(child, "element")) {
9747 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9748 schema, child, 0);
9749 if (part != NULL) {
9750 if (part->minOccurs > 1)
9751 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
9752 NULL, NULL, child,
9753 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9754 if (part->maxOccurs > 1)
9755 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
9756 NULL, NULL, child,
9757 "Invalid value for maxOccurs (must be 0 or 1)",
9758 NULL);
9759 if (last == NULL)
9760 item->children = (xmlSchemaTreeItemPtr) part;
9761 else
9762 last->next = (xmlSchemaTreeItemPtr) part;
9763 last = part;
9764 }
9765 child = child->next;
9766 }
9767 if (child != NULL) {
9768 xmlSchemaPContentErr(ctxt,
9769 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9770 NULL, NULL, node, child, NULL,
9771 "(annotation?, (annotation?, element*)");
9772 }
9773 } else {
9774 /* choice + sequence */
9775 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9776
9777 while ((IS_SCHEMA(child, "element")) ||
9778 (IS_SCHEMA(child, "group")) ||
9779 (IS_SCHEMA(child, "any")) ||
9780 (IS_SCHEMA(child, "choice")) ||
9781 (IS_SCHEMA(child, "sequence"))) {
9782
9783 if (IS_SCHEMA(child, "element")) {
9784 part = (xmlSchemaTreeItemPtr)
9785 xmlSchemaParseElement(ctxt, schema, child, 0);
9786 } else if (IS_SCHEMA(child, "group")) {
9787 part =
9788 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9789 } else if (IS_SCHEMA(child, "any")) {
9790 part = (xmlSchemaTreeItemPtr)
9791 xmlSchemaParseAny(ctxt, schema, child);
9792 } else if (IS_SCHEMA(child, "choice")) {
9793 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9794 XML_SCHEMA_TYPE_CHOICE, 1);
9795 } else if (IS_SCHEMA(child, "sequence")) {
9796 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9797 XML_SCHEMA_TYPE_SEQUENCE, 1);
9798 }
9799 if (part != NULL) {
9800 if (last == NULL)
9801 item->children = part;
9802 else
9803 last->next = part;
9804 last = part;
9805 }
9806 child = child->next;
9807 }
9808 if (child != NULL) {
9809 xmlSchemaPContentErr(ctxt,
9810 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9811 NULL, NULL, node, child, NULL,
9812 "(annotation?, (element | group | choice | sequence | any)*)");
9813 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009814 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009815 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009816 if (withParticle) {
9817 if ((min == 0) && (max == 0))
9818 return (NULL);
9819 else
9820 return ((xmlSchemaTreeItemPtr) particle);
9821 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009822 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009823}
9824
9825/**
9826 * xmlSchemaParseRestriction:
9827 * @ctxt: a schema validation context
9828 * @schema: the schema being built
9829 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009830 *
9831 * parse a XML schema Restriction definition
9832 * *WARNING* this interface is highly subject to change
9833 *
9834 * Returns the type definition or NULL in case of error
9835 */
9836static xmlSchemaTypePtr
9837xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009838 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009839{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009840 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009841 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009842 char buf[30];
9843 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009844 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009845
9846 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9847 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009848 /* Not a component, don't create it. */
9849 type = ctxt->ctxtType;
9850 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
9851
9852 /*
9853 * TODO: Is the container needed at all? the anonymous
9854 * items inside should generate unique names already.
9855 */
9856 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
9857 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009858 /*
9859 * Check for illegal attributes.
9860 */
9861 attr = node->properties;
9862 while (attr != NULL) {
9863 if (attr->ns == NULL) {
9864 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9865 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9866 xmlSchemaPIllegalAttrErr(ctxt,
9867 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009868 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009869 }
9870 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9871 xmlSchemaPIllegalAttrErr(ctxt,
9872 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009873 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009874 }
9875 attr = attr->next;
9876 }
9877 /*
9878 * Extract and validate attributes.
9879 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009880 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009881 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009882 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009883 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009884 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009885 NULL, NULL, node, "base",
9886 &(type->baseNs), NULL,
9887 &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009888 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009889 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009890 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009891 XML_SCHEMAP_S4S_ATTR_MISSING,
William M. Brack2f2a6632004-08-20 23:09:47 +00009892 NULL, type, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009893 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009894 /*
9895 * And now for the children...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009896 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009897 child = node->children;
9898 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009899 /*
9900 * Add the annotation to the simple type ancestor.
9901 */
9902 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9903 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009904 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009906 oldcontainer = ctxt->container;
9907 ctxt->container = container;
9908 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9909 /*
9910 * Corresponds to <simpleType><restriction><simpleType>.
9911 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009912 if (IS_SCHEMA(child, "simpleType")) {
9913 if (type->base != NULL) {
9914 /*
9915 * src-restriction-base-or-simpleType
9916 * Either the base [attribute] or the simpleType [child] of the
9917 * <restriction> element must be present, but not both.
9918 */
9919 xmlSchemaPContentErr(ctxt,
9920 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009921 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009922 "The attribute 'base' and the <simpleType> child are "
9923 "mutually exclusive", NULL);
9924 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009925 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009926 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009927 }
9928 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009929 } else if (type->base == NULL) {
9930 xmlSchemaPContentErr(ctxt,
9931 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9932 NULL, NULL, node, child,
9933 "Either the attribute 'base' or a <simpleType> child "
9934 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009935 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009936 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9937 /*
9938 * Corresponds to <complexType><complexContent><restriction>...
9939 * followed by:
9940 *
9941 * Model groups <all>, <choice> and <sequence>.
9942 */
9943 if (IS_SCHEMA(child, "all")) {
9944 type->subtypes = (xmlSchemaTypePtr)
9945 xmlSchemaParseModelGroup(ctxt, schema, child,
9946 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009947 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009948 } else if (IS_SCHEMA(child, "choice")) {
9949 type->subtypes = (xmlSchemaTypePtr)
9950 xmlSchemaParseModelGroup(ctxt,
9951 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9952 child = child->next;
9953 } else if (IS_SCHEMA(child, "sequence")) {
9954 type->subtypes = (xmlSchemaTypePtr)
9955 xmlSchemaParseModelGroup(ctxt, schema, child,
9956 XML_SCHEMA_TYPE_SEQUENCE, 1);
9957 child = child->next;
9958 /*
9959 * Model group reference <group>.
9960 */
9961 } else if (IS_SCHEMA(child, "group")) {
9962 type->subtypes = (xmlSchemaTypePtr)
9963 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9964 child = child->next;
9965 }
9966 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9967 xmlSchemaTypePtr contType, baseType = NULL;
9968 /*
9969 * Corresponds to <complexType><simpleContent><restriction>...
9970 *
9971 * SPEC (content type):
9972 * "1 If the type definition ·resolved· to by the ·actual value· of
9973 * the base [attribute] is a complex type definition whose own
9974 * {content type} is a simple type definition and the <restriction>
9975 * alternative is chosen, then starting from either" ...
9976 *
9977 * "1.1 the simple type definition corresponding to the <simpleType>
9978 * among the [children] of <restriction> if there is one;"
9979 */
9980 if (IS_SCHEMA(child, "simpleType")) {
9981
9982 baseType = (xmlSchemaTypePtr)
9983 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9984 if (baseType == NULL)
9985 return (NULL);
9986 child = child->next;
9987 }
9988 /*
9989 * SPEC
9990 * "... a simple type definition which restricts the simple type
9991 * definition identified in clause 1.1 or clause 1.2 with a set
9992 * of facet components"
9993 *
9994 * Create the anonymous simple type, which will be the content type
9995 * of the complex type.
9996 * Note that we will use the same node as for the <restriction> to
9997 * have it somehow anchored in the schema doc.
9998 */
9999 snprintf(buf, 29, "#scST%d", ctxt->counter++ + 1);
10000 contType = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
10001 container, node);
10002 if (contType == NULL)
10003 return (NULL);
10004 contType->node = node;
10005 contType->type = XML_SCHEMA_TYPE_SIMPLE;
10006 contType->baseType = baseType;
10007 type->contentTypeDef = contType;
William M. Brack2f2a6632004-08-20 23:09:47 +000010008 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010009
10010 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
10011 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
10012 xmlSchemaFacetPtr facet, lastfacet = NULL;
10013 xmlSchemaTypePtr facetHolder;
10014
10015 if (parentType == XML_SCHEMA_TYPE_SIMPLE)
10016 facetHolder = type;
10017 else
10018 facetHolder = type->contentTypeDef;
10019 /*
10020 * Corresponds to <complexType><simpleContent><restriction>...
10021 * <simpleType><restriction>...
10022 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010023
Daniel Veillard01fa6152004-06-29 17:04:39 +000010024 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010025 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010026 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010027 /*
10028 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
10029 * Simple Type Definition Schema Representation Constraint:
10030 * *Single Facet Value*
10031 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010032 while ((IS_SCHEMA(child, "minInclusive")) ||
10033 (IS_SCHEMA(child, "minExclusive")) ||
10034 (IS_SCHEMA(child, "maxInclusive")) ||
10035 (IS_SCHEMA(child, "maxExclusive")) ||
10036 (IS_SCHEMA(child, "totalDigits")) ||
10037 (IS_SCHEMA(child, "fractionDigits")) ||
10038 (IS_SCHEMA(child, "pattern")) ||
10039 (IS_SCHEMA(child, "enumeration")) ||
10040 (IS_SCHEMA(child, "whiteSpace")) ||
10041 (IS_SCHEMA(child, "length")) ||
10042 (IS_SCHEMA(child, "maxLength")) ||
10043 (IS_SCHEMA(child, "minLength"))) {
10044 facet = xmlSchemaParseFacet(ctxt, schema, child);
10045 if (facet != NULL) {
10046 if (lastfacet == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010047 facetHolder->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010048 else
10049 lastfacet->next = facet;
10050 lastfacet = facet;
10051 lastfacet->next = NULL;
10052 }
10053 child = child->next;
10054 }
10055 /*
10056 * Create links for derivation and validation.
10057 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010058 if (facetHolder->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010059 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10060
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010061 facet = facetHolder->facets;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010062 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010063 facetLink = (xmlSchemaFacetLinkPtr)
10064 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010065 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010066 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010067 xmlFree(facetLink);
10068 return (NULL);
10069 }
10070 facetLink->facet = facet;
10071 facetLink->next = NULL;
10072 if (lastFacetLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010073 facetHolder->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010074 else
10075 lastFacetLink->next = facetLink;
10076 lastFacetLink = facetLink;
10077 facet = facet->next;
10078 } while (facet != NULL);
10079 }
10080 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010081 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10082 /*
10083 * Attribute uses/declarations.
10084 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010085 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010086 /*
10087 * Attribute wildcard.
10088 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010089 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010090 type->attributeWildcard =
10091 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010092 child = child->next;
10093 }
10094 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010095 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010096 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010097 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010098 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10099 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010100 "annotation?, (group | all | choice | sequence)?, "
10101 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010102 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010103 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010104 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10105 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010106 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10107 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10108 "length | minLength | maxLength | enumeration | whiteSpace | "
10109 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10110 } else {
10111 /* Simple type */
10112 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010113 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10114 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010115 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10116 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10117 "length | minLength | maxLength | enumeration | whiteSpace | "
10118 "pattern)*))");
10119 }
10120 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010121 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010122 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010123}
10124
10125/**
10126 * xmlSchemaParseExtension:
10127 * @ctxt: a schema validation context
10128 * @schema: the schema being built
10129 * @node: a subtree containing XML Schema informations
10130 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010131 * Parses an <extension>, which is found inside a
10132 * <simpleContent> or <complexContent>.
10133 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010134 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010135 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010136 */
10137static xmlSchemaTypePtr
10138xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010139 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010140{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010141 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010142 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010143 char buf[30];
10144 const xmlChar *oldcontainer, *container;
10145 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010146
10147 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10148 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010149 /* Not a component, don't create it. */
10150 type = ctxt->ctxtType;
10151 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010152
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010153 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10154 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10155 /*
10156 * Check for illegal attributes.
10157 */
10158 attr = node->properties;
10159 while (attr != NULL) {
10160 if (attr->ns == NULL) {
10161 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10162 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
10163 xmlSchemaPIllegalAttrErr(ctxt,
10164 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10165 NULL, NULL, attr);
10166 }
10167 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10168 xmlSchemaPIllegalAttrErr(ctxt,
10169 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10170 NULL, NULL, attr);
10171 }
10172 attr = attr->next;
10173 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010174
10175 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010176
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010177 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010178 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010179 */
10180 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 NULL, NULL, node, "base", &(type->baseNs), NULL,
10182 &(type->base)) == 0) && (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010183 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 XML_SCHEMAP_S4S_ATTR_MISSING,
10185 NULL, NULL, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010186 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010187 /*
10188 * And now for the children...
10189 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010190 child = node->children;
10191 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010192 /*
10193 * Add the annotation to the type ancestor.
10194 */
10195 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10196 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010197 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010198 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010199 oldcontainer = ctxt->container;
10200 ctxt->container = container;
10201 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10202 /*
10203 * Corresponds to <complexType><complexContent><extension>... and:
10204 *
10205 * Model groups <all>, <choice>, <sequence> and <group>.
10206 */
10207 if (IS_SCHEMA(child, "all")) {
10208 type->subtypes = (xmlSchemaTypePtr)
10209 xmlSchemaParseModelGroup(ctxt, schema,
10210 child, XML_SCHEMA_TYPE_ALL, 1);
10211 child = child->next;
10212 } else if (IS_SCHEMA(child, "choice")) {
10213 type->subtypes = (xmlSchemaTypePtr)
10214 xmlSchemaParseModelGroup(ctxt, schema,
10215 child, XML_SCHEMA_TYPE_CHOICE, 1);
10216 child = child->next;
10217 } else if (IS_SCHEMA(child, "sequence")) {
10218 type->subtypes = (xmlSchemaTypePtr)
10219 xmlSchemaParseModelGroup(ctxt, schema,
10220 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10221 child = child->next;
10222 } else if (IS_SCHEMA(child, "group")) {
10223 type->subtypes = (xmlSchemaTypePtr)
10224 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10225 child = child->next;
10226 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010227 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010228 if (child != NULL) {
10229 /*
10230 * Attribute uses/declarations.
10231 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010232 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010233 /*
10234 * Attribute wildcard.
10235 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010236 if (IS_SCHEMA(child, "anyAttribute")) {
10237 ctxt->ctxtType->attributeWildcard =
10238 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10239 child = child->next;
10240 }
10241 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010242 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010243 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10244 /* Complex content extension. */
10245 xmlSchemaPContentErr(ctxt,
10246 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10247 NULL, NULL, node, child, NULL,
10248 "(annotation?, ((group | all | choice | sequence)?, "
10249 "((attribute | attributeGroup)*, anyAttribute?)))");
10250 } else {
10251 /* Simple content extension. */
10252 xmlSchemaPContentErr(ctxt,
10253 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10254 NULL, NULL, node, child, NULL,
10255 "(annotation?, ((attribute | attributeGroup)*, "
10256 "anyAttribute?))");
10257 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010258 }
10259 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010260 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010261}
10262
10263/**
10264 * xmlSchemaParseSimpleContent:
10265 * @ctxt: a schema validation context
10266 * @schema: the schema being built
10267 * @node: a subtree containing XML Schema informations
10268 *
10269 * parse a XML schema SimpleContent definition
10270 * *WARNING* this interface is highly subject to change
10271 *
10272 * Returns the type definition or NULL in case of error
10273 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010274static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010275xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10276 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010277{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010278 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010279 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010280 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010281
10282 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010283 return (-1);
10284 /* Not a component, don't create it. */
10285 type = ctxt->ctxtType;
10286 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10287 /*
10288 * Check for illegal attributes.
10289 */
10290 attr = node->properties;
10291 while (attr != NULL) {
10292 if (attr->ns == NULL) {
10293 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
10294 xmlSchemaPIllegalAttrErr(ctxt,
10295 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10296 NULL, NULL, attr);
10297 }
10298 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10299 xmlSchemaPIllegalAttrErr(ctxt,
10300 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10301 NULL, NULL, attr);
10302 }
10303 attr = attr->next;
10304 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010305
10306 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010307
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010308 /*
10309 * And now for the children...
10310 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010311 child = node->children;
10312 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010313 /*
10314 * Add the annotation to the complex type ancestor.
10315 */
10316 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10317 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010318 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010319 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010320 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010321 xmlSchemaParseRestriction(ctxt, schema, child,
10322 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010323 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010324 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010325 xmlSchemaParseExtension(ctxt, schema, child,
10326 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010327 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010328 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010329 if (child != NULL) {
10330 xmlSchemaPContentErr(ctxt,
10331 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10332 NULL, NULL, node, child, NULL,
10333 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010334 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010335 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010336}
10337
10338/**
10339 * xmlSchemaParseComplexContent:
10340 * @ctxt: a schema validation context
10341 * @schema: the schema being built
10342 * @node: a subtree containing XML Schema informations
10343 *
10344 * parse a XML schema ComplexContent definition
10345 * *WARNING* this interface is highly subject to change
10346 *
10347 * Returns the type definition or NULL in case of error
10348 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010349static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010350xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10351 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010352{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010353 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010354 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010355 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010356
10357 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010358 return (-1);
10359 /* Not a component, don't create it. */
10360 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010361 /*
10362 * Check for illegal attributes.
10363 */
10364 attr = node->properties;
10365 while (attr != NULL) {
10366 if (attr->ns == NULL) {
10367 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10368 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
10369 {
10370 xmlSchemaPIllegalAttrErr(ctxt,
10371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10372 NULL, NULL, attr);
10373 }
10374 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10375 xmlSchemaPIllegalAttrErr(ctxt,
10376 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10377 NULL, NULL, attr);
10378 }
10379 attr = attr->next;
10380 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010381
10382 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10383
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010384 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010385 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010386 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010387 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10388 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10389 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010390 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010391 child = node->children;
10392 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010393 /*
10394 * Add the annotation to the complex type ancestor.
10395 */
10396 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10397 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010398 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010399 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010400 if (IS_SCHEMA(child, "restriction")) {
10401 xmlSchemaParseRestriction(ctxt, schema, child,
10402 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010403 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010404 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010405 xmlSchemaParseExtension(ctxt, schema, child,
10406 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010407 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010408 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010409 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010410 xmlSchemaPContentErr(ctxt,
10411 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10412 NULL, NULL, node, child,
10413 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010414 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010415 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010416}
10417
10418/**
10419 * xmlSchemaParseComplexType:
10420 * @ctxt: a schema validation context
10421 * @schema: the schema being built
10422 * @node: a subtree containing XML Schema informations
10423 *
10424 * parse a XML schema Complex Type definition
10425 * *WARNING* this interface is highly subject to change
10426 *
10427 * Returns the type definition or NULL in case of error
10428 */
10429static xmlSchemaTypePtr
10430xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010431 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010432{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010433 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010434 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010435 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010436 xmlAttrPtr attr;
10437 const xmlChar *attrValue;
10438 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010439 char buf[40];
10440
Daniel Veillard4255d502002-04-16 15:50:10 +000010441
10442 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10443 return (NULL);
10444
Daniel Veillard01fa6152004-06-29 17:04:39 +000010445 ctxtType = ctxt->ctxtType;
10446
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 if (topLevel) {
10448 attr = xmlSchemaGetPropNode(node, "name");
10449 if (attr == NULL) {
10450 xmlSchemaPMissingAttrErr(ctxt,
10451 XML_SCHEMAP_S4S_ATTR_MISSING,
10452 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
10453 "name", NULL);
10454 return (NULL);
10455 } else if (xmlSchemaPValAttrNode(ctxt,
10456 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
10457 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10458 return (NULL);
10459 }
10460 }
10461
10462 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010463 /*
10464 * Parse as local complex type definition.
10465 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010466 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010467 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10468 if (type == NULL)
10469 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010470 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010471 type->node = node;
10472 type->type = XML_SCHEMA_TYPE_COMPLEX;
10473 /*
10474 * TODO: We need the target namespace.
10475 */
10476 } else {
10477 /*
10478 * Parse as global complex type definition.
10479 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010480 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010481 if (type == NULL)
10482 return (NULL);
10483 type->node = node;
10484 type->type = XML_SCHEMA_TYPE_COMPLEX;
10485 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
10486 /*
10487 * Set defaults.
10488 */
10489 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010490 }
10491 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010492 /*
10493 * Handle attributes.
10494 */
10495 attr = node->properties;
10496 while (attr != NULL) {
10497 if (attr->ns == NULL) {
10498 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10499 /*
10500 * Attribute "id".
10501 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010502 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10503 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010504 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10505 /*
10506 * Attribute "mixed".
10507 */
10508 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10509 (xmlNodePtr) attr))
10510 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10511 } else if (topLevel) {
10512 /*
10513 * Attributes of global complex type definitions.
10514 */
10515 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10516 /* Pass. */
10517 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10518 /*
10519 * Attribute "abstract".
10520 */
10521 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10522 (xmlNodePtr) attr))
10523 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10524 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10525 /*
10526 * Attribute "final".
10527 */
10528 attrValue = xmlSchemaGetNodeContent(ctxt,
10529 (xmlNodePtr) attr);
10530 if (xmlSchemaPValAttrBlockFinal(attrValue,
10531 &(type->flags),
10532 -1,
10533 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10534 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10535 -1, -1, -1) != 0)
10536 {
10537 xmlSchemaPSimpleTypeErr(ctxt,
10538 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10539 &des, type, (xmlNodePtr) attr,
10540 NULL,
10541 "(#all | List of (extension | restriction))",
10542 attrValue, NULL, NULL, NULL);
10543 }
10544 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10545 /*
10546 * Attribute "block".
10547 */
10548 attrValue = xmlSchemaGetNodeContent(ctxt,
10549 (xmlNodePtr) attr);
10550 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
10551 -1,
10552 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
10553 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
10554 -1, -1, -1) != 0) {
10555 xmlSchemaPSimpleTypeErr(ctxt,
10556 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10557 &des, type, (xmlNodePtr) attr,
10558 NULL,
10559 "(#all | List of (extension | restriction)) ",
10560 attrValue, NULL, NULL, NULL);
10561 }
10562 } else {
10563 xmlSchemaPIllegalAttrErr(ctxt,
10564 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10565 &des, type, attr);
10566 }
10567 } else {
10568 xmlSchemaPIllegalAttrErr(ctxt,
10569 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10570 &des, type, attr);
10571 }
10572 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10573 xmlSchemaPIllegalAttrErr(ctxt,
10574 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10575 &des, type, attr);
10576 }
10577 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010578 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010579 if (xmlSchemaGetPropNode(node, "block") == NULL) {
10580 /*
10581 * Apply default "block" values.
10582 */
10583 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10584 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10585 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10586 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10587 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010588 /*
10589 * And now for the children...
10590 */
10591 oldcontainer = ctxt->container;
10592 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010593 child = node->children;
10594 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010595 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10596 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010597 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010598 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010599 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010600 /*
10601 * 3.4.3 : 2.2
10602 * Specifying mixed='true' when the <simpleContent>
10603 * alternative is chosen has no effect
10604 */
William M. Bracke7091952004-05-11 15:09:58 +000010605 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10606 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010607 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010608 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010609 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010610 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10611 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010612 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010613 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010614 /*
10615 * SPEC
10616 * "...the third alternative (neither <simpleContent> nor
10617 * <complexContent>) is chosen. This case is understood as shorthand
10618 * for complex content restricting the ·ur-type definition·, and the
10619 * details of the mappings should be modified as necessary.
10620 */
10621 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10622 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010623 /*
10624 * Parse model groups.
10625 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010626 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010627 type->subtypes = (xmlSchemaTypePtr)
10628 xmlSchemaParseModelGroup(ctxt, schema, child,
10629 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010630 child = child->next;
10631 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010632 type->subtypes = (xmlSchemaTypePtr)
10633 xmlSchemaParseModelGroup(ctxt, schema, child,
10634 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010635 child = child->next;
10636 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010637 type->subtypes = (xmlSchemaTypePtr)
10638 xmlSchemaParseModelGroup(ctxt, schema, child,
10639 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010640 child = child->next;
10641 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010642 type->subtypes = (xmlSchemaTypePtr)
10643 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010644 child = child->next;
10645 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010646 /*
10647 * Parse attribute decls/refs.
10648 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010649 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010650 /*
10651 * Parse attribute wildcard.
10652 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010653 if (IS_SCHEMA(child, "anyAttribute")) {
10654 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10655 child = child->next;
10656 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010657 }
10658 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010659 xmlSchemaPContentErr(ctxt,
10660 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10661 &des, type, node, child,
10662 NULL, "(annotation?, (simpleContent | complexContent | "
10663 "((group | all | choice | sequence)?, ((attribute | "
10664 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010665 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010666 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010667 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010668 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010669 return (type);
10670}
10671
Daniel Veillard4255d502002-04-16 15:50:10 +000010672/**
10673 * xmlSchemaParseSchema:
10674 * @ctxt: a schema validation context
10675 * @node: a subtree containing XML Schema informations
10676 *
10677 * parse a XML schema definition from a node set
10678 * *WARNING* this interface is highly subject to change
10679 *
10680 * Returns the internal XML Schema structure built from the resource or
10681 * NULL in case of error
10682 */
10683static xmlSchemaPtr
10684xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10685{
10686 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010687 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010688 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010689 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010690
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010691 /*
10692 * This one is called by xmlSchemaParse only and is used if
10693 * the schema to be parsed was specified via the API; i.e. not
10694 * automatically by the validated instance document.
10695 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010696 if ((ctxt == NULL) || (node == NULL))
10697 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010698 nberrors = ctxt->nberrors;
10699 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010700 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010701 xmlSchemaImportPtr import;
10702
Daniel Veillard4255d502002-04-16 15:50:10 +000010703 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010704 if (schema == NULL)
10705 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010706 /*
10707 * Disable build of list of items.
10708 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010709 attr = xmlSchemaGetPropNode(node, "targetNamespace");
10710 if (attr != NULL) {
10711 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
10712 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10713 /*
10714 * TODO: Should we proceed with an invalid target namespace?
10715 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010716 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
10717 } else {
10718 schema->targetNamespace = NULL;
10719 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010720 /*
10721 * Add the current ns name and location to the import table;
10722 * this is needed to have a consistent mechanism, regardless
10723 * if all schemata are constructed dynamically fired by the
10724 * instance or if the schema to be used was specified via
10725 * the API.
10726 */
10727 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10728 schema->targetNamespace);
10729 if (import == NULL) {
10730 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10731 NULL, NULL, (xmlNodePtr) ctxt->doc,
10732 "Internal error: xmlSchemaParseSchema, "
10733 "failed to add an import entry", NULL);
10734 xmlSchemaFree(schema);
10735 schema = NULL;
10736 return (NULL);
10737 }
10738 import->schemaLocation = ctxt->URL;
10739 /*
10740 * NOTE: We won't set the doc here, otherwise it will be freed
10741 * if the import struct is freed.
10742 * import->doc = ctxt->doc;
10743 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010744 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010745 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10746 } else {
10747 xmlDocPtr doc;
10748
10749 doc = node->doc;
10750
10751 if ((doc != NULL) && (doc->URL != NULL)) {
10752 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10753 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010754 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010755 } else {
10756 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10757 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010758 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010759 }
10760 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010761 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010762 if (ctxt->nberrors != 0) {
10763 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010764 xmlSchemaFree(schema);
10765 schema = NULL;
10766 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010767 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010768 if (schema != NULL)
10769 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010770 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010771#ifdef DEBUG
10772 if (schema == NULL)
10773 xmlGenericError(xmlGenericErrorContext,
10774 "xmlSchemaParse() failed\n");
10775#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010776 return (schema);
10777}
10778
10779/************************************************************************
10780 * *
10781 * Validating using Schemas *
10782 * *
10783 ************************************************************************/
10784
10785/************************************************************************
10786 * *
10787 * Reading/Writing Schemas *
10788 * *
10789 ************************************************************************/
10790
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010791#if 0 /* Will be enabled if it is clear what options are needed. */
10792/**
10793 * xmlSchemaParserCtxtSetOptions:
10794 * @ctxt: a schema parser context
10795 * @options: a combination of xmlSchemaParserOption
10796 *
10797 * Sets the options to be used during the parse.
10798 *
10799 * Returns 0 in case of success, -1 in case of an
10800 * API error.
10801 */
10802static int
10803xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10804 int options)
10805
10806{
10807 int i;
10808
10809 if (ctxt == NULL)
10810 return (-1);
10811 /*
10812 * WARNING: Change the start value if adding to the
10813 * xmlSchemaParseOption.
10814 */
10815 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10816 if (options & 1<<i) {
10817 return (-1);
10818 }
10819 }
10820 ctxt->options = options;
10821 return (0);
10822}
10823
10824/**
10825 * xmlSchemaValidCtxtGetOptions:
10826 * @ctxt: a schema parser context
10827 *
10828 * Returns the option combination of the parser context.
10829 */
10830static int
10831xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
10832
10833{
10834 if (ctxt == NULL)
10835 return (-1);
10836 else
10837 return (ctxt->options);
10838}
10839
10840 void *curItems; /* used for dynamic addition of schemata */
10841 int nbCurItems; /* used for dynamic addition of schemata */
10842 int sizeCurItems; /* used for dynamic addition of schemata */
10843
10844#endif
10845
Daniel Veillard4255d502002-04-16 15:50:10 +000010846/**
10847 * xmlSchemaNewParserCtxt:
10848 * @URL: the location of the schema
10849 *
10850 * Create an XML Schemas parse context for that file/resource expected
10851 * to contain an XML Schemas file.
10852 *
10853 * Returns the parser context or NULL in case of error
10854 */
10855xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010856xmlSchemaNewParserCtxt(const char *URL)
10857{
Daniel Veillard4255d502002-04-16 15:50:10 +000010858 xmlSchemaParserCtxtPtr ret;
10859
10860 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010861 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010862
10863 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10864 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010865 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010866 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010867 return (NULL);
10868 }
10869 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010870 ret->dict = xmlDictCreate();
10871 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010872 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010873 return (ret);
10874}
10875
10876/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010877 * xmlSchemaNewParserCtxtUseDict:
10878 * @URL: the location of the schema
10879 * @dict: the dictionary to be used
10880 *
10881 * Create an XML Schemas parse context for that file/resource expected
10882 * to contain an XML Schemas file.
10883 *
10884 * Returns the parser context or NULL in case of error
10885 */
10886static xmlSchemaParserCtxtPtr
10887xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10888{
10889 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010890 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010891 if (URL == NULL)
10892 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010893 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010894
10895 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10896 if (ret == NULL) {
10897 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10898 NULL);
10899 return (NULL);
10900 }
10901 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10902 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010903 xmlDictReference(dict);
10904 if (URL != NULL)
10905 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010906 ret->includes = 0;
10907 return (ret);
10908}
10909
10910
10911/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010912 * xmlSchemaNewMemParserCtxt:
10913 * @buffer: a pointer to a char array containing the schemas
10914 * @size: the size of the array
10915 *
10916 * Create an XML Schemas parse context for that memory buffer expected
10917 * to contain an XML Schemas file.
10918 *
10919 * Returns the parser context or NULL in case of error
10920 */
10921xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010922xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10923{
Daniel Veillard6045c902002-10-09 21:13:59 +000010924 xmlSchemaParserCtxtPtr ret;
10925
10926 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010927 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010928
10929 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10930 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010931 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010932 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010933 return (NULL);
10934 }
10935 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10936 ret->buffer = buffer;
10937 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010938 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010939 return (ret);
10940}
10941
10942/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010943 * xmlSchemaNewDocParserCtxt:
10944 * @doc: a preparsed document tree
10945 *
10946 * Create an XML Schemas parse context for that document.
10947 * NB. The document may be modified during the parsing process.
10948 *
10949 * Returns the parser context or NULL in case of error
10950 */
10951xmlSchemaParserCtxtPtr
10952xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10953{
10954 xmlSchemaParserCtxtPtr ret;
10955
10956 if (doc == NULL)
10957 return (NULL);
10958
10959 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10960 if (ret == NULL) {
10961 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10962 NULL);
10963 return (NULL);
10964 }
10965 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10966 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010967 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010968 /* The application has responsibility for the document */
10969 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010970
10971 return (ret);
10972}
10973
10974/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010975 * xmlSchemaFreeParserCtxt:
10976 * @ctxt: the schema parser context
10977 *
10978 * Free the resources associated to the schema parser context
10979 */
10980void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010981xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10982{
Daniel Veillard4255d502002-04-16 15:50:10 +000010983 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010984 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010985 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010986 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010987 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010988 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010989 xmlFree(ctxt->assemble);
10990 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010991 if (ctxt->vctxt != NULL) {
10992 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10993 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010994 if (ctxt->localImports != NULL)
10995 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010996 if (ctxt->substGroups != NULL)
10997 xmlHashFree(ctxt->substGroups,
10998 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010999 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000011000 xmlFree(ctxt);
11001}
11002
11003/************************************************************************
11004 * *
11005 * Building the content models *
11006 * *
11007 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011008
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011009static void
11010xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011011 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011012{
11013 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011014 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011015 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011016 xmlSchemaSubstGroupPtr substGroup;
11017 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011018
11019 elemDecl = (xmlSchemaElementPtr) particle->children;
11020 /*
11021 * Wrap the substitution group with a CHOICE.
11022 */
11023 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011024 end = xmlAutomataNewState(pctxt->am);
11025 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
11026 if (substGroup == NULL) {
11027 xmlSchemaPErr(pctxt, GET_NODE(particle),
11028 XML_SCHEMAP_INTERNAL,
11029 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
11030 "declaration is marked having a subst. group but none "
11031 "available.\n", elemDecl->name, NULL);
11032 return;
11033 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011034 if (particle->maxOccurs == 1) {
11035 /*
11036 * NOTE that we put the declaration in, even if it's abstract,
11037 */
11038 xmlAutomataNewEpsilon(pctxt->am,
11039 xmlAutomataNewTransition2(pctxt->am,
11040 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011041 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
11042 /*
11043 * Add subst. group members.
11044 */
11045 for (i = 0; i < substGroup->members->nbItems; i++) {
11046 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11047 xmlAutomataNewEpsilon(pctxt->am,
11048 xmlAutomataNewTransition2(pctxt->am,
11049 start, NULL,
11050 member->name, member->targetNamespace, member),
11051 end);
11052 }
11053 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011054 int counter;
11055 xmlAutomataStatePtr hop;
11056 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11057 UNBOUNDED : particle->maxOccurs - 1;
11058 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
11059
11060 counter =
11061 xmlAutomataNewCounter(pctxt->am, minOccurs,
11062 maxOccurs);
11063 hop = xmlAutomataNewState(pctxt->am);
11064
11065 xmlAutomataNewEpsilon(pctxt->am,
11066 xmlAutomataNewTransition2(pctxt->am,
11067 start, NULL,
11068 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011069 hop);
11070 /*
11071 * Add subst. group members.
11072 */
11073 for (i = 0; i < substGroup->members->nbItems; i++) {
11074 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11075 xmlAutomataNewEpsilon(pctxt->am,
11076 xmlAutomataNewTransition2(pctxt->am,
11077 start, NULL,
11078 member->name, member->targetNamespace, member),
11079 hop);
11080 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011081 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11082 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11083 }
11084 if (particle->minOccurs == 0)
11085 xmlAutomataNewEpsilon(pctxt->am, start, end);
11086 pctxt->state = end;
11087}
11088
11089static void
11090xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11091 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011092{
11093 if (((xmlSchemaElementPtr) particle->children)->flags &
11094 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011095 /*
11096 * Substitution groups.
11097 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011098 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011099 } else {
11100 xmlSchemaElementPtr elemDecl;
11101 xmlAutomataStatePtr start;
11102
11103 elemDecl = (xmlSchemaElementPtr) particle->children;
11104
11105 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
11106 return;
11107 if (particle->maxOccurs == 1) {
11108 start = ctxt->state;
11109 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11110 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11111 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
11112 /* Special case. */
11113 start = ctxt->state;
11114 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11115 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11116 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
11117 } else {
11118 int counter;
11119 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11120 UNBOUNDED : particle->maxOccurs - 1;
11121 int minOccurs = particle->minOccurs < 1 ?
11122 0 : particle->minOccurs - 1;
11123
11124 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
11125 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11126 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11127 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11128 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11129 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11130 NULL, counter);
11131 }
11132 if (particle->minOccurs == 0)
11133 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11134 }
11135}
11136
Daniel Veillard4255d502002-04-16 15:50:10 +000011137/**
11138 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011139 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011140 * @particle: the particle component
11141 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011142 *
11143 * Generate the automata sequence needed for that type
11144 */
11145static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011146xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
11147 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011148 const xmlChar * name)
11149{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011150 if (particle == NULL) {
11151 xmlSchemaPErr(ctxt, NULL,
11152 XML_SCHEMAP_INTERNAL,
11153 "Internal error: xmlSchemaBuildAContentModel, "
11154 "particle is NULL.\n", NULL, NULL);
11155 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011156 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 if (particle->children == NULL) {
11158 xmlSchemaPErr(ctxt, GET_NODE(particle),
11159 XML_SCHEMAP_INTERNAL,
11160 "Internal error: xmlSchemaBuildAContentModel, "
11161 "no term on particle.\n", NULL, NULL);
11162 return;
11163 }
11164
11165 switch (particle->children->type) {
11166 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011167 xmlAutomataStatePtr start, end;
11168 xmlSchemaWildcardPtr wild;
11169 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011170
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011171 wild = (xmlSchemaWildcardPtr) particle->children;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011172
11173 start = ctxt->state;
11174 end = xmlAutomataNewState(ctxt->am);
11175
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011176 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011177 if (wild->any == 1) {
11178 /*
11179 * We need to add both transitions:
11180 *
11181 * 1. the {"*", "*"} for elements in a namespace.
11182 */
11183 ctxt->state =
11184 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011186 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11187 /*
11188 * 2. the {"*"} for elements in no namespace.
11189 */
11190 ctxt->state =
11191 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011192 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011193 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11194
11195 } else if (wild->nsSet != NULL) {
11196 ns = wild->nsSet;
11197 do {
11198 ctxt->state = start;
11199 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011200 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011201 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11202 ns = ns->next;
11203 } while (ns != NULL);
11204
11205 } else if (wild->negNsSet != NULL) {
11206 xmlAutomataStatePtr deadEnd;
11207
11208 deadEnd = xmlAutomataNewState(ctxt->am);
11209 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011211 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011213 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11214 }
11215 } else {
11216 int counter;
11217 xmlAutomataStatePtr hop;
11218 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011219 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011220 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011221 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011222
11223 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11224 hop = xmlAutomataNewState(ctxt->am);
11225 if (wild->any == 1) {
11226 ctxt->state =
11227 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011229 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11230 ctxt->state =
11231 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011232 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011233 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11234 } else if (wild->nsSet != NULL) {
11235 ns = wild->nsSet;
11236 do {
11237 ctxt->state =
11238 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011239 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011240 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11241 ns = ns->next;
11242 } while (ns != NULL);
11243
11244 } else if (wild->negNsSet != NULL) {
11245 xmlAutomataStatePtr deadEnd;
11246
11247 deadEnd = xmlAutomataNewState(ctxt->am);
11248 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011250 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011251 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011252 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11253 }
11254 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11255 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11256 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011257 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011258 xmlAutomataNewEpsilon(ctxt->am, start, end);
11259 }
11260 ctxt->state = end;
11261 break;
11262 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011263 case XML_SCHEMA_TYPE_ELEMENT:
11264 xmlSchemaBuildContentModelForElement(ctxt, particle);
11265 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011266 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011267 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011268
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011269 /*
11270 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011271 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011272 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11274 sub = particle->children->children;
11275 while (sub != NULL) {
11276 xmlSchemaBuildAContentModel(ctxt,
11277 (xmlSchemaParticlePtr) sub, name);
11278 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011279 }
11280 } else {
11281 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011282
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011283 if (particle->maxOccurs >= UNBOUNDED) {
11284 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011285 xmlAutomataStatePtr tmp;
11286 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011287
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011288 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011289 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011290 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011291
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011294
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011295 sub = particle->children->children;
11296 while (sub != NULL) {
11297 xmlSchemaBuildAContentModel(ctxt,
11298 (xmlSchemaParticlePtr) sub, name);
11299 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011300 }
11301 tmp = ctxt->state;
11302 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11303 oldstate, counter);
11304 ctxt->state =
11305 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11306 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011307
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011308 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011309 sub = particle->children->children;
11310 while (sub != NULL) {
11311 xmlSchemaBuildAContentModel(ctxt,
11312 (xmlSchemaParticlePtr) sub, name);
11313 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011314 }
11315 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11316 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 if (particle->minOccurs == 0) {
11318 xmlAutomataNewEpsilon(ctxt->am,
11319 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011320 }
11321 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011322 } else if ((particle->maxOccurs > 1)
11323 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011324 xmlAutomataStatePtr tmp;
11325 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011326
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011327 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011328 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011329 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011330
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011331 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 particle->minOccurs - 1,
11333 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011334
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 sub = particle->children->children;
11336 while (sub != NULL) {
11337 xmlSchemaBuildAContentModel(ctxt,
11338 (xmlSchemaParticlePtr) sub, name);
11339 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 }
11341 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 xmlAutomataNewCountedTrans(ctxt->am,
11343 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011344 ctxt->state =
11345 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11346 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011347 if (particle->minOccurs == 0) {
11348 xmlAutomataNewEpsilon(ctxt->am,
11349 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011350 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011351 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011352 sub = particle->children->children;
11353 while (sub != NULL) {
11354 xmlSchemaBuildAContentModel(ctxt,
11355 (xmlSchemaParticlePtr) sub, name);
11356 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011357 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011358 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011359 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11360 ctxt->state);
11361 }
11362 }
11363 }
11364 break;
11365 }
11366 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011367 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011368 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011369
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011370 start = ctxt->state;
11371 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011372
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011373 /*
11374 * iterate over the subtypes and remerge the end with an
11375 * epsilon transition
11376 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011377 if (particle->maxOccurs == 1) {
11378 sub = particle->children->children;
11379 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011380 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011381 xmlSchemaBuildAContentModel(ctxt,
11382 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011383 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011384 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011385 }
11386 } else {
11387 int counter;
11388 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011389 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11390 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011391 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011392 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011393
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011394 /*
11395 * use a counter to keep track of the number of transtions
11396 * which went through the choice.
11397 */
11398 counter =
11399 xmlAutomataNewCounter(ctxt->am, minOccurs,
11400 maxOccurs);
11401 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011402
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011403 sub = particle->children->children;
11404 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011405 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011406 xmlSchemaBuildAContentModel(ctxt,
11407 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011408 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011409 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011410 }
11411 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11412 counter);
11413 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11414 counter);
11415 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011416 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011417 xmlAutomataNewEpsilon(ctxt->am, start, end);
11418 }
11419 ctxt->state = end;
11420 break;
11421 }
11422 case XML_SCHEMA_TYPE_ALL:{
11423 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011424 xmlSchemaParticlePtr sub;
11425 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011426 int lax;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011427
11428 sub = (xmlSchemaParticlePtr) particle->children->children;
11429 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011430 break;
11431 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011432 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011433 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011434
11435 elemDecl = (xmlSchemaElementPtr) sub->children;
11436 if (elemDecl == NULL) {
11437 xmlSchemaPErr(ctxt, NULL,
11438 XML_SCHEMAP_INTERNAL,
11439 "Internal error: xmlSchemaBuildAContentModel, "
11440 "<element> particle a NULL term.\n", NULL, NULL);
11441 return;
11442 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011443 /*
11444 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011445 * {particles} of the group must be 0 or 1; this is
11446 * already ensured during the parse of the content of
11447 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011448 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011449 if ((sub->minOccurs == 1) &&
11450 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011451 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11452 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011453 elemDecl->name,
11454 elemDecl->targetNamespace,
11455 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011456 } else if ((sub->minOccurs == 0) &&
11457 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011458
11459 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11460 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011461 elemDecl->name,
11462 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011463 0,
11464 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011465 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011466 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011468 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011469 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011470 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011471 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011472 break;
11473 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011474 default:
11475 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011476 "Internal error: xmlSchemaBuildAContentModel, found "
11477 "unexpected term of type %d in content model of complex "
11478 "type '%s'.\n",
11479 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011480 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011481 }
11482}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011483
Daniel Veillard4255d502002-04-16 15:50:10 +000011484/**
11485 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011486 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011488 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011489 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011490 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011491 */
11492static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011493xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011494 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011495 const xmlChar * name)
11496{
Daniel Veillard4255d502002-04-16 15:50:10 +000011497 xmlAutomataStatePtr start;
11498
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011499 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11500 (type->contModel != NULL) ||
11501 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11502 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011503 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011504
11505#ifdef DEBUG_CONTENT
11506 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011507 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011508#endif
11509
Daniel Veillard4255d502002-04-16 15:50:10 +000011510 ctxt->am = xmlNewAutomata();
11511 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011512 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011513 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011514 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011515 }
11516 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011517 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011518 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011519 type->contModel = xmlAutomataCompile(ctxt->am);
11520 if (type->contModel == NULL) {
11521 xmlSchemaPCustomErr(ctxt,
11522 XML_SCHEMAP_INTERNAL,
11523 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011524 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011525 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011526 xmlSchemaPCustomErr(ctxt,
11527 XML_SCHEMAP_NOT_DETERMINISTIC,
11528 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011529 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011530 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011531 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011532#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011533 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011534 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011535 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011536#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011537 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011538 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011539 xmlFreeAutomata(ctxt->am);
11540 ctxt->am = NULL;
11541}
11542
11543/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011544 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011545 * @elem: the schema element context
11546 * @ctxt: the schema parser context
11547 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011548 * Resolves the references of an element declaration
11549 * or particle, which has an element declaration as it's
11550 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011551 */
11552static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011553xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011554 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011555 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011556 const xmlChar * context ATTRIBUTE_UNUSED,
11557 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011558{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011559 if ((ctxt == NULL) || (elemDecl == NULL) ||
11560 ((elemDecl != NULL) && (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011561 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011562 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011563
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011564 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565 xmlSchemaTypePtr type;
11566
11567 /* (type definition) ... otherwise the type definition ·resolved·
11568 * to by the ·actual value· of the type [attribute] ...
11569 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011570 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
11571 elemDecl->namedTypeNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011572 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011573 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011574 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011575 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
11576 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011577 XML_SCHEMA_TYPE_BASIC, "type definition");
11578 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011579 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011580 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011581 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011582 xmlSchemaElementPtr substHead;
11583
Daniel Veillardc0826a72004-08-10 14:17:33 +000011584 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011585 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
11586 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011587 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011588 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11589 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 if (substHead == NULL) {
11591 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011592 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011593 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
11594 "substitutionGroup", elemDecl->substGroup,
11595 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 } else {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011597 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011598 /*
11599 * Set the "substitution group affiliation".
11600 * NOTE that now we use the "refDecl" field for this.
11601 */
11602 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011603 /*
11604 * (type definition)...otherwise the {type definition} of the
11605 * element declaration ·resolved· to by the ·actual value· of
11606 * the substitutionGroup [attribute], if present
11607 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011608 if (elemDecl->subtypes == NULL)
11609 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011610 }
11611 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011612 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11613 (elemDecl->substGroup == NULL))
11614 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011615}
11616
11617/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011618 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011619 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011620 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011621 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011622 * Checks and builds the "member type definitions" property of the union
11623 * simple type. This handles part (1), part (2) is done in
11624 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11625 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011626 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011627 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011628static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011629xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11630 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011631{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011632
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011633 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011634 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011635
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011636 /*
11637 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Daniel Veillard01fa6152004-06-29 17:04:39 +000011638 * define the explicit members as the type definitions ·resolved·
11639 * to by the items in the ·actual value· of the memberTypes [attribute],
11640 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011641 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011642 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011643 /*
11644 * Resolve references.
11645 */
11646 link = type->memberTypes;
11647 lastLink = NULL;
11648 while (link != NULL) {
11649 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011650
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011651 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11652 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11653
11654 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11655 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11656 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
11657 NULL, type, type->node, "memberTypes",
11658 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11659 /*
11660 * Remove the member type link.
11661 */
11662 if (lastLink == NULL)
11663 type->memberTypes = link->next;
11664 else
11665 lastLink->next = link->next;
11666 newLink = link;
11667 link = link->next;
11668 xmlFree(newLink);
11669 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011670 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011671 lastLink = link;
11672 link = link->next;
11673 }
11674 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011675 /*
11676 * Add local simple types,
11677 */
11678 memberType = type->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011679 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011680 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11681 if (link == NULL) {
11682 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11683 return (-1);
11684 }
11685 link->type = memberType;
11686 link->next = NULL;
11687 if (lastLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011688 type->memberTypes = link;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011689 else
11690 lastLink->next = link;
11691 lastLink = link;
11692 memberType = memberType->next;
11693 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011694 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011695}
11696
Daniel Veillard4255d502002-04-16 15:50:10 +000011697/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011698 * xmlSchemaIsDerivedFromBuiltInType:
11699 * @ctxt: the schema parser context
11700 * @type: the type definition
11701 * @valType: the value type
11702 *
11703 *
11704 * Returns 1 if the type has the given value type, or
11705 * is derived from such a type.
11706 */
William M. Brack803812b2004-06-03 02:11:24 +000011707static int
Daniel Veillard3646d642004-06-02 19:19:14 +000011708xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
11709 xmlSchemaTypePtr type, int valType)
11710{
11711 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011712 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011713 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011714 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011715 return(1);
11716 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
11717 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
11718 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
11719 ((xmlSchemaAttributePtr) type)->subtypes, valType));
11720 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
11721 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
11722 if (type->baseType != NULL)
11723 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
11724 valType));
11725 } else if ((type->subtypes != NULL) &&
11726 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
11727 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11728 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
11729 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
11730 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
11731 valType));
11732 }
11733
11734 return (0);
11735}
11736
11737/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011738 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011739 * @type: the simpleType definition
11740 *
11741 * Returns the primitive type of the given type or
11742 * NULL in case of error.
11743 */
11744static xmlSchemaTypePtr
11745xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11746{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011747
Daniel Veillard01fa6152004-06-29 17:04:39 +000011748 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011749 /*
11750 * Note that anySimpleType is actually not a primitive type
11751 * but we need that here.
11752 */
11753 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11754 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011755 return (type);
11756 type = type->baseType;
11757 }
11758
11759 return (NULL);
11760}
11761
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011762#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011763/**
11764 * xmlSchemaGetBuiltInTypeAncestor:
11765 * @type: the simpleType definition
11766 *
11767 * Returns the primitive type of the given type or
11768 * NULL in case of error.
11769 */
11770static xmlSchemaTypePtr
11771xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11772{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011773 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11774 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
11775 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011776 while (type != NULL) {
11777 if (type->type == XML_SCHEMA_TYPE_BASIC)
11778 return (type);
11779 type = type->baseType;
11780 }
11781
11782 return (NULL);
11783}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011784#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011785
Daniel Veillard01fa6152004-06-29 17:04:39 +000011786/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011787 * xmlSchemaBuildAttributeUsesOwned:
11788 * @ctxt: the schema parser context
11789 * @type: the complex type definition
11790 * @cur: the attribute declaration list
11791 * @lastUse: the top of the attribute use list
11792 *
11793 * Builds the attribute uses list on the given complex type.
11794 * This one is supposed to be called by
11795 * xmlSchemaBuildAttributeValidation only.
11796 */
11797static int
11798xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
11799 xmlSchemaAttributePtr cur,
11800 xmlSchemaAttributeLinkPtr *uses,
11801 xmlSchemaAttributeLinkPtr *lastUse)
11802{
11803 xmlSchemaAttributeLinkPtr tmp;
11804 while (cur != NULL) {
11805 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11806 /*
11807 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11808 * to by the ·actual value·s of the ref [attribute] of the
11809 * <attributeGroup> [children], if any."
11810 */
11811 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11812 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
11813 lastUse) == -1) {
11814 return (-1);
11815 }
11816 } else {
11817 /* W3C: "1 The set of attribute uses corresponding to the
11818 * <attribute> [children], if any."
11819 */
11820 tmp = (xmlSchemaAttributeLinkPtr)
11821 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11822 if (tmp == NULL) {
11823 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11824 return (-1);
11825 }
11826 tmp->attr = cur;
11827 tmp->next = NULL;
11828 if (*uses == NULL)
11829 *uses = tmp;
11830 else
11831 (*lastUse)->next = tmp;
11832 *lastUse = tmp;
11833 }
11834 cur = cur->next;
11835 }
11836 return (0);
11837}
11838
Daniel Veillard50355f02004-06-08 17:52:16 +000011839/**
11840 * xmlSchemaCloneWildcardNsConstraints:
11841 * @ctxt: the schema parser context
11842 * @dest: the destination wildcard
11843 * @source: the source wildcard
11844 *
11845 * Clones the namespace constraints of source
11846 * and assignes them to dest.
11847 * Returns -1 on internal error, 0 otherwise.
11848 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011849static int
11850xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11851 xmlSchemaWildcardPtr *dest,
11852 xmlSchemaWildcardPtr source)
11853{
11854 xmlSchemaWildcardNsPtr cur, tmp, last;
11855
11856 if ((source == NULL) || (*dest == NULL))
11857 return(-1);
11858 (*dest)->any = source->any;
11859 cur = source->nsSet;
11860 last = NULL;
11861 while (cur != NULL) {
11862 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11863 if (tmp == NULL)
11864 return(-1);
11865 tmp->value = cur->value;
11866 if (last == NULL)
11867 (*dest)->nsSet = tmp;
11868 else
11869 last->next = tmp;
11870 last = tmp;
11871 cur = cur->next;
11872 }
11873 if ((*dest)->negNsSet != NULL)
11874 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
11875 if (source->negNsSet != NULL) {
11876 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11877 if ((*dest)->negNsSet == NULL)
11878 return(-1);
11879 (*dest)->negNsSet->value = source->negNsSet->value;
11880 } else
11881 (*dest)->negNsSet = NULL;
11882 return(0);
11883}
11884
Daniel Veillard50355f02004-06-08 17:52:16 +000011885/**
11886 * xmlSchemaUnionWildcards:
11887 * @ctxt: the schema parser context
11888 * @completeWild: the first wildcard
11889 * @curWild: the second wildcard
11890 *
11891 * Unions the namespace constraints of the given wildcards.
11892 * @completeWild will hold the resulting union.
11893 * Returns a positive error code on failure, -1 in case of an
11894 * internal error, 0 otherwise.
11895 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011896static int
11897xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11898 xmlSchemaWildcardPtr completeWild,
11899 xmlSchemaWildcardPtr curWild)
11900{
11901 xmlSchemaWildcardNsPtr cur, curB, tmp;
11902
11903 /*
11904 * 1 If O1 and O2 are the same value, then that value must be the
11905 * value.
11906 */
11907 if ((completeWild->any == curWild->any) &&
11908 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11909 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11910
11911 if ((completeWild->negNsSet == NULL) ||
11912 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11913
11914 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011915 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011916
11917 /*
11918 * Check equality of sets.
11919 */
11920 cur = completeWild->nsSet;
11921 while (cur != NULL) {
11922 found = 0;
11923 curB = curWild->nsSet;
11924 while (curB != NULL) {
11925 if (cur->value == curB->value) {
11926 found = 1;
11927 break;
11928 }
11929 curB = curB->next;
11930 }
11931 if (!found)
11932 break;
11933 cur = cur->next;
11934 }
11935 if (found)
11936 return(0);
11937 } else
11938 return(0);
11939 }
11940 }
11941 /*
11942 * 2 If either O1 or O2 is any, then any must be the value
11943 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011944 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011945 if (completeWild->any == 0) {
11946 completeWild->any = 1;
11947 if (completeWild->nsSet != NULL) {
11948 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11949 completeWild->nsSet = NULL;
11950 }
11951 if (completeWild->negNsSet != NULL) {
11952 xmlFree(completeWild->negNsSet);
11953 completeWild->negNsSet = NULL;
11954 }
11955 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011956 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011957 }
11958 /*
11959 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11960 * then the union of those sets must be the value.
11961 */
11962 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11963 int found;
11964 xmlSchemaWildcardNsPtr start;
11965
11966 cur = curWild->nsSet;
11967 start = completeWild->nsSet;
11968 while (cur != NULL) {
11969 found = 0;
11970 curB = start;
11971 while (curB != NULL) {
11972 if (cur->value == curB->value) {
11973 found = 1;
11974 break;
11975 }
11976 curB = curB->next;
11977 }
11978 if (!found) {
11979 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11980 if (tmp == NULL)
11981 return (-1);
11982 tmp->value = cur->value;
11983 tmp->next = completeWild->nsSet;
11984 completeWild->nsSet = tmp;
11985 }
11986 cur = cur->next;
11987 }
11988
11989 return(0);
11990 }
11991 /*
11992 * 4 If the two are negations of different values (namespace names
11993 * or ·absent·), then a pair of not and ·absent· must be the value.
11994 */
11995 if ((completeWild->negNsSet != NULL) &&
11996 (curWild->negNsSet != NULL) &&
11997 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11998 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011999
12000 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012001 }
12002 /*
12003 * 5.
12004 */
12005 if (((completeWild->negNsSet != NULL) &&
12006 (completeWild->negNsSet->value != NULL) &&
12007 (curWild->nsSet != NULL)) ||
12008 ((curWild->negNsSet != NULL) &&
12009 (curWild->negNsSet->value != NULL) &&
12010 (completeWild->nsSet != NULL))) {
12011
12012 int nsFound, absentFound = 0;
12013
12014 if (completeWild->nsSet != NULL) {
12015 cur = completeWild->nsSet;
12016 curB = curWild->negNsSet;
12017 } else {
12018 cur = curWild->nsSet;
12019 curB = completeWild->negNsSet;
12020 }
12021 nsFound = 0;
12022 while (cur != NULL) {
12023 if (cur->value == NULL)
12024 absentFound = 1;
12025 else if (cur->value == curB->value)
12026 nsFound = 1;
12027 if (nsFound && absentFound)
12028 break;
12029 cur = cur->next;
12030 }
12031
12032 if (nsFound && absentFound) {
12033 /*
12034 * 5.1 If the set S includes both the negated namespace
12035 * name and ·absent·, then any must be the value.
12036 */
12037 completeWild->any = 1;
12038 if (completeWild->nsSet != NULL) {
12039 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12040 completeWild->nsSet = NULL;
12041 }
12042 if (completeWild->negNsSet != NULL) {
12043 xmlFree(completeWild->negNsSet);
12044 completeWild->negNsSet = NULL;
12045 }
12046 } else if (nsFound && (!absentFound)) {
12047 /*
12048 * 5.2 If the set S includes the negated namespace name
12049 * but not ·absent·, then a pair of not and ·absent· must
12050 * be the value.
12051 */
12052 if (completeWild->nsSet != NULL) {
12053 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12054 completeWild->nsSet = NULL;
12055 }
12056 if (completeWild->negNsSet == NULL) {
12057 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12058 if (completeWild->negNsSet == NULL)
12059 return (-1);
12060 }
12061 completeWild->negNsSet->value = NULL;
12062 } else if ((!nsFound) && absentFound) {
12063 /*
12064 * 5.3 If the set S includes ·absent· but not the negated
12065 * namespace name, then the union is not expressible.
12066 */
12067 xmlSchemaPErr(ctxt, completeWild->node,
12068 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012069 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012070 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012071 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012072 } else if ((!nsFound) && (!absentFound)) {
12073 /*
12074 * 5.4 If the set S does not include either the negated namespace
12075 * name or ·absent·, then whichever of O1 or O2 is a pair of not
12076 * and a namespace name must be the value.
12077 */
12078 if (completeWild->negNsSet == NULL) {
12079 if (completeWild->nsSet != NULL) {
12080 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12081 completeWild->nsSet = NULL;
12082 }
12083 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12084 if (completeWild->negNsSet == NULL)
12085 return (-1);
12086 completeWild->negNsSet->value = curWild->negNsSet->value;
12087 }
12088 }
12089 return (0);
12090 }
12091 /*
12092 * 6.
12093 */
12094 if (((completeWild->negNsSet != NULL) &&
12095 (completeWild->negNsSet->value == NULL) &&
12096 (curWild->nsSet != NULL)) ||
12097 ((curWild->negNsSet != NULL) &&
12098 (curWild->negNsSet->value == NULL) &&
12099 (completeWild->nsSet != NULL))) {
12100
12101 if (completeWild->nsSet != NULL) {
12102 cur = completeWild->nsSet;
12103 } else {
12104 cur = curWild->nsSet;
12105 }
12106 while (cur != NULL) {
12107 if (cur->value == NULL) {
12108 /*
12109 * 6.1 If the set S includes ·absent·, then any must be the
12110 * value.
12111 */
12112 completeWild->any = 1;
12113 if (completeWild->nsSet != NULL) {
12114 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12115 completeWild->nsSet = NULL;
12116 }
12117 if (completeWild->negNsSet != NULL) {
12118 xmlFree(completeWild->negNsSet);
12119 completeWild->negNsSet = NULL;
12120 }
12121 return (0);
12122 }
12123 cur = cur->next;
12124 }
12125 if (completeWild->negNsSet == NULL) {
12126 /*
12127 * 6.2 If the set S does not include ·absent·, then a pair of not
12128 * and ·absent· must be the value.
12129 */
12130 if (completeWild->nsSet != NULL) {
12131 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12132 completeWild->nsSet = NULL;
12133 }
12134 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12135 if (completeWild->negNsSet == NULL)
12136 return (-1);
12137 completeWild->negNsSet->value = NULL;
12138 }
12139 return (0);
12140 }
12141 return (0);
12142
12143}
12144
Daniel Veillard50355f02004-06-08 17:52:16 +000012145/**
12146 * xmlSchemaIntersectWildcards:
12147 * @ctxt: the schema parser context
12148 * @completeWild: the first wildcard
12149 * @curWild: the second wildcard
12150 *
12151 * Intersects the namespace constraints of the given wildcards.
12152 * @completeWild will hold the resulting intersection.
12153 * Returns a positive error code on failure, -1 in case of an
12154 * internal error, 0 otherwise.
12155 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012156static int
12157xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
12158 xmlSchemaWildcardPtr completeWild,
12159 xmlSchemaWildcardPtr curWild)
12160{
William M. Brack803812b2004-06-03 02:11:24 +000012161 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012162
12163 /*
12164 * 1 If O1 and O2 are the same value, then that value must be the
12165 * value.
12166 */
12167 if ((completeWild->any == curWild->any) &&
12168 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12169 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
12170
12171 if ((completeWild->negNsSet == NULL) ||
12172 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
12173
12174 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012175 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012176
12177 /*
12178 * Check equality of sets.
12179 */
12180 cur = completeWild->nsSet;
12181 while (cur != NULL) {
12182 found = 0;
12183 curB = curWild->nsSet;
12184 while (curB != NULL) {
12185 if (cur->value == curB->value) {
12186 found = 1;
12187 break;
12188 }
12189 curB = curB->next;
12190 }
12191 if (!found)
12192 break;
12193 cur = cur->next;
12194 }
12195 if (found)
12196 return(0);
12197 } else
12198 return(0);
12199 }
12200 }
12201 /*
12202 * 2 If either O1 or O2 is any, then the other must be the value.
12203 */
12204 if ((completeWild->any != curWild->any) && (completeWild->any)) {
12205 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12206 return(-1);
12207 return(0);
12208 }
12209 /*
12210 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12211 * name or ·absent·) and the other is a set of (namespace names or
12212 * ·absent·), then that set, minus the negated value if it was in
12213 * the set, minus ·absent· if it was in the set, must be the value.
12214 */
12215 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12216 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12217 const xmlChar *neg;
12218
12219 if (completeWild->nsSet == NULL) {
12220 neg = completeWild->negNsSet->value;
12221 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12222 return(-1);
12223 } else
12224 neg = curWild->negNsSet->value;
12225 /*
12226 * Remove absent and negated.
12227 */
12228 prev = NULL;
12229 cur = completeWild->nsSet;
12230 while (cur != NULL) {
12231 if (cur->value == NULL) {
12232 if (prev == NULL)
12233 completeWild->nsSet = cur->next;
12234 else
12235 prev->next = cur->next;
12236 xmlFree(cur);
12237 break;
12238 }
12239 prev = cur;
12240 cur = cur->next;
12241 }
12242 if (neg != NULL) {
12243 prev = NULL;
12244 cur = completeWild->nsSet;
12245 while (cur != NULL) {
12246 if (cur->value == neg) {
12247 if (prev == NULL)
12248 completeWild->nsSet = cur->next;
12249 else
12250 prev->next = cur->next;
12251 xmlFree(cur);
12252 break;
12253 }
12254 prev = cur;
12255 cur = cur->next;
12256 }
12257 }
12258
12259 return(0);
12260 }
12261 /*
12262 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
12263 * then the intersection of those sets must be the value.
12264 */
12265 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
12266 int found;
12267
12268 cur = completeWild->nsSet;
12269 prev = NULL;
12270 while (cur != NULL) {
12271 found = 0;
12272 curB = curWild->nsSet;
12273 while (curB != NULL) {
12274 if (cur->value == curB->value) {
12275 found = 1;
12276 break;
12277 }
12278 curB = curB->next;
12279 }
12280 if (!found) {
12281 if (prev == NULL)
12282 completeWild->nsSet = cur->next;
12283 else
12284 prev->next = cur->next;
12285 tmp = cur->next;
12286 xmlFree(cur);
12287 cur = tmp;
12288 continue;
12289 }
12290 prev = cur;
12291 cur = cur->next;
12292 }
12293
12294 return(0);
12295 }
12296 /* 5 If the two are negations of different namespace names,
12297 * then the intersection is not expressible
12298 */
12299 if ((completeWild->negNsSet != NULL) &&
12300 (curWild->negNsSet != NULL) &&
12301 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12302 (completeWild->negNsSet->value != NULL) &&
12303 (curWild->negNsSet->value != NULL)) {
12304
12305 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012306 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012307 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012308 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012309 }
12310 /*
12311 * 6 If the one is a negation of a namespace name and the other
12312 * is a negation of ·absent·, then the one which is the negation
12313 * of a namespace name must be the value.
12314 */
12315 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12316 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12317 (completeWild->negNsSet->value == NULL)) {
12318 completeWild->negNsSet->value = curWild->negNsSet->value;
12319 }
12320 return(0);
12321}
12322
Daniel Veillard50355f02004-06-08 17:52:16 +000012323/**
12324 * xmlSchemaIsWildcardNsConstraintSubset:
12325 * @ctxt: the schema parser context
12326 * @wildA: the first wildcard
12327 * @wildB: the second wildcard
12328 *
12329 * Returns 1 if the namespace constraint of @wildA is an intensional
12330 * subset of @wildB, 0 otherwise.
12331 */
12332static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000012333xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
12334 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000012335{
Daniel Veillard3646d642004-06-02 19:19:14 +000012336
Daniel Veillard50355f02004-06-08 17:52:16 +000012337 /*
12338 * Schema Component Constraint: Wildcard Subset
12339 */
12340 /*
12341 * 1 super must be any.
12342 */
12343 if (wildB->any)
12344 return (1);
12345 /*
12346 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12347 * 2.2 super must be a pair of not and the same value.
12348 */
12349 if ((wildA->negNsSet != NULL) &&
12350 (wildB->negNsSet != NULL) &&
12351 (wildA->negNsSet->value == wildA->negNsSet->value))
12352 return (1);
12353 /*
12354 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
12355 */
12356 if (wildA->nsSet != NULL) {
12357 /*
12358 * 3.2.1 super must be the same set or a superset thereof.
12359 */
12360 if (wildB->nsSet != NULL) {
12361 xmlSchemaWildcardNsPtr cur, curB;
12362 int found = 0;
12363
12364 cur = wildA->nsSet;
12365 while (cur != NULL) {
12366 found = 0;
12367 curB = wildB->nsSet;
12368 while (curB != NULL) {
12369 if (cur->value == curB->value) {
12370 found = 1;
12371 break;
12372 }
12373 curB = curB->next;
12374 }
12375 if (!found)
12376 return (0);
12377 cur = cur->next;
12378 }
12379 if (found)
12380 return (1);
12381 } else if (wildB->negNsSet != NULL) {
12382 xmlSchemaWildcardNsPtr cur;
12383 /*
12384 * 3.2.2 super must be a pair of not and a namespace name or
12385 * ·absent· and that value must not be in sub's set.
12386 */
12387 cur = wildA->nsSet;
12388 while (cur != NULL) {
12389 if (cur->value == wildB->negNsSet->value)
12390 return (0);
12391 cur = cur->next;
12392 }
12393 return (1);
12394 }
12395 }
12396 return (0);
12397}
12398
12399/**
12400 * xmlSchemaBuildCompleteAttributeWildcard:
12401 * @ctxt: the schema parser context
12402 * @attrs: the attribute list
12403 * @completeWild: the resulting complete wildcard
12404 *
12405 * Returns -1 in case of an internal error, 0 otherwise.
12406 */
12407static int
12408xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
12409 xmlSchemaAttributePtr attrs,
12410 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000012411{
12412 while (attrs != NULL) {
12413 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12414 xmlSchemaAttributeGroupPtr group;
12415
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 group = (xmlSchemaAttributeGroupPtr) attrs;
12417 /*
12418 * Handle attribute group references.
12419 */
12420 if (group->ref != NULL) {
12421 if (group->refItem == NULL) {
12422 /*
12423 * TODO: Should we raise a warning here?
12424 */
12425 /*
12426 * The referenced attribute group definition could not
12427 * be resolved beforehand, so skip.
12428 */
12429 attrs = attrs->next;
12430 continue;
12431 } else
12432 group = group->refItem;
12433 }
12434 /*
12435 * For every attribute group definition, an intersected wildcard
12436 * will be created (assumed that a wildcard exists on the
12437 * particular attr. gr. def. or on any contained attr. gr. def
12438 * at all).
12439 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12440 * that the intersection will be performed only once.
12441 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012442 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12443 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012444 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12445 group->attributes, &group->attributeWildcard) == -1)
12446 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012447 }
12448 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
12449 }
12450 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012451 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012452 /*
12453 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012454 *
12455 * Although the complete wildcard might not correspond to any
12456 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012457 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012458 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12459 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12460 group->attributeWildcard->node);
Daniel Veillard50355f02004-06-08 17:52:16 +000012461 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
12462 completeWild, group->attributeWildcard) == -1)
12463 return (-1);
12464 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012465 (*completeWild)->node = group->attributeWildcard->node;
12466 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012467 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012468 }
12469 }
12470 attrs = attrs->next;
12471 }
12472
Daniel Veillard50355f02004-06-08 17:52:16 +000012473 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012474}
12475
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012476static int
12477xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12478 int *fixed,
12479 const xmlChar **value,
12480 xmlSchemaValPtr *val)
12481{
12482 *fixed = 0;
12483 *value = NULL;
12484 if (val != 0)
12485 *val = NULL;
12486
12487 if (item->defValue == NULL)
12488 item = item->refDecl;
12489
12490 if (item == NULL)
12491 return (0);
12492
12493 if (item->defValue != NULL) {
12494 *value = item->defValue;
12495 if (val != 0)
12496 *val = item->defVal;
12497 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12498 *fixed = 1;
12499 return (1);
12500 }
12501 return (0);
12502}
Daniel Veillard3646d642004-06-02 19:19:14 +000012503/**
12504 * xmlSchemaMatchesWildcardNs:
12505 * @wild: the wildcard
12506 * @ns: the namespace
12507 *
12508 *
12509 * Returns 1 if the given namespace matches the wildcard,
12510 * 0 otherwise.
12511 */
12512static int
12513xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
12514{
12515 if (wild == NULL)
12516 return(0);
12517
12518 if (wild->any)
12519 return(1);
12520 else if (wild->nsSet != NULL) {
12521 xmlSchemaWildcardNsPtr cur;
12522
12523 cur = wild->nsSet;
12524 while (cur != NULL) {
12525 if (xmlStrEqual(cur->value, ns))
12526 return(1);
12527 cur = cur->next;
12528 }
12529 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
12530 (!xmlStrEqual(wild->negNsSet->value, ns)))
12531 return(1);
12532
12533 return(0);
12534}
12535
12536/**
12537 * xmlSchemaBuildAttributeValidation:
12538 * @ctxt: the schema parser context
12539 * @type: the complex type definition
12540 *
12541 *
12542 * Builds the wildcard and the attribute uses on the given complex type.
12543 * Returns -1 if an internal error occurs, 0 otherwise.
12544 */
12545static int
12546xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
12547{
12548 xmlSchemaTypePtr baseType = NULL;
12549 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000012550 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012551 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012552 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000012553 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012554 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012555 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012556
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012558 /*
12559 * Complex Type Definition with complex content Schema Component.
12560 *
12561 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012562 * TODO: Add checks for absent referenced attribute declarations and
12563 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012564 */
12565 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012566 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012567 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000012568 "attribute uses already builded.\n",
12569 NULL, NULL);
12570 return (-1);
12571 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012572 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012573 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012574 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012575 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012576 type->name, NULL);
12577 return (-1);
12578 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012579 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012580 if (baseType == anyType)
12581 baseIsAnyType = 1;
12582 /*
12583 * Inherit the attribute uses of the base type.
12584 */
12585 /*
12586 * NOTE: It is allowed to "extend" the anyType complex type.
12587 */
12588 if (!baseIsAnyType) {
12589 if (baseType != NULL) {
12590 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
12591 tmp = (xmlSchemaAttributeLinkPtr)
12592 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12593 if (tmp == NULL) {
12594 xmlSchemaPErrMemory(ctxt,
12595 "building attribute uses of complexType", NULL);
12596 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012597 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012598 tmp->attr = cur->attr;
12599 tmp->next = NULL;
12600 if (type->attributeUses == NULL) {
12601 type->attributeUses = tmp;
12602 } else
12603 lastBaseUse->next = tmp;
12604 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012605 }
12606 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012607 }
12608 if ((type->subtypes != NULL) &&
12609 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
12610 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012611 /*
12612 * type --> (<simpleContent>|<complexContent>)
12613 * --> (<restriction>|<extension>) --> attributes
12614 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012615 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012616 } else {
12617 /* Short hand form of the complexType. */
12618 attrs = type->attributes;
12619 }
12620 /*
12621 * Handle attribute wildcards.
12622 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012623 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12624 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012625 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012626 * NOTE: During the parse time, the wildcard is created on the complexType
12627 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012628 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012629 if (err == -1) {
12630 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
12631 "Internal error: xmlSchemaBuildAttributeValidation: "
12632 "failed to build an intersected attribute wildcard.\n",
12633 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012634 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012635 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012636
12637 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12638 ((baseIsAnyType) ||
12639 ((baseType != NULL) &&
12640 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12641 (baseType->attributeWildcard != NULL)))) {
12642 if (type->attributeWildcard != NULL) {
12643 /*
12644 * Union the complete wildcard with the base wildcard.
12645 */
12646 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
12647 baseType->attributeWildcard) == -1)
12648 return (-1);
12649 } else {
12650 /*
12651 * Just inherit the wildcard.
12652 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012653 /*
12654 * NOTE: This is the only case where an attribute
12655 * wildcard is shared.
12656 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012657 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012658 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012659 }
12660
12661 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12662 if (type->attributeWildcard != NULL) {
12663 /*
12664 * Derivation Valid (Restriction, Complex)
12665 * 4.1 The {base type definition} must also have one.
12666 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012667 if (baseType->attributeWildcard == NULL) {
12668 xmlSchemaPCustomErr(ctxt,
12669 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
12670 NULL, type, NULL,
12671 "The type has an attribute wildcard, "
12672 "but the base type %s does not have one",
12673 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12674 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012675 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012677 type->attributeWildcard, baseType->attributeWildcard) == 0) {
12678 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012679 xmlSchemaPCustomErr(ctxt,
12680 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
12681 NULL, type, NULL,
12682 "The attribute wildcard is not a valid "
12683 "subset of the wildcard in the base type %s",
12684 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12685 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012686 return (1);
12687 }
12688 /* 4.3 Unless the {base type definition} is the ·ur-type
12689 * definition·, the complex type definition's {attribute
12690 * wildcard}'s {process contents} must be identical to or
12691 * stronger than the {base type definition}'s {attribute
12692 * wildcard}'s {process contents}, where strict is stronger
12693 * than lax is stronger than skip.
12694 */
12695 if ((type->baseType != anyType) &&
12696 (type->attributeWildcard->processContents <
12697 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012698 xmlSchemaPCustomErr(ctxt,
12699 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
12700 NULL, type, NULL,
12701 "The 'process contents' of the attribute wildcard is weaker than "
12702 "the one in the base type %s",
12703 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12704 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012705 return (1);
12706 }
12707 }
12708 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12709 /*
12710 * Derivation Valid (Extension)
12711 * At this point the type and the base have both, either
12712 * no wildcard or a wildcard.
12713 */
12714 if ((baseType->attributeWildcard != NULL) &&
12715 (baseType->attributeWildcard != type->attributeWildcard)) {
12716 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012717 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012718 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012719 xmlSchemaPCustomErr(ctxt,
12720 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
12721 NULL, type, NULL,
12722 "The attribute wildcard is not a valid "
12723 "superset of the one in the base type %s",
12724 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12725 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012726 return (1);
12727 }
12728 }
12729 }
12730
Daniel Veillard3646d642004-06-02 19:19:14 +000012731 /*
12732 * Gather attribute uses defined by this type.
12733 */
12734 if (attrs != NULL) {
12735 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
12736 &uses, &lastUse) == -1) {
12737 return (-1);
12738 }
12739 }
12740 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
12741 * "Two distinct attribute declarations in the {attribute uses} must
12742 * not have identical {name}s and {target namespace}s."
12743 *
12744 * For "extension" this is done further down.
12745 */
12746 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
12747 cur = uses;
12748 while (cur != NULL) {
12749 tmp = cur->next;
12750 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012751 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12752 xmlSchemaGetAttrName(tmp->attr))) &&
12753 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12754 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12755
12756 xmlSchemaPAttrUseErr(ctxt,
12757 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12758 NULL, type, NULL, cur->attr,
12759 "Duplicate attribute use %s specified",
12760 xmlSchemaFormatNsUriLocal(&str,
12761 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12762 xmlSchemaGetAttrName(tmp->attr))
12763 );
12764 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012765 break;
12766 }
12767 tmp = tmp->next;
12768 }
12769 cur = cur->next;
12770 }
12771 }
12772 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12773 /*
12774 * Derive by restriction.
12775 */
12776 if (baseIsAnyType) {
12777 type->attributeUses = uses;
12778 } else {
12779 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012780 const xmlChar *bEffValue;
12781 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012782
12783 cur = uses;
12784 while (cur != NULL) {
12785 found = 0;
12786 base = type->attributeUses;
12787 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012788 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12789 xmlSchemaGetAttrName(base->attr)) &&
12790 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
12791 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012792
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012793 found = 1;
12794
Daniel Veillard3646d642004-06-02 19:19:14 +000012795 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12796 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12797 /*
12798 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000012799 */
12800 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012801 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012802 NULL, type, NULL, cur->attr,
12803 "The 'optional' use is inconsistent with a matching "
12804 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012805 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12806 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12807 /*
12808 * derivation-ok-restriction 3
12809 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012810 xmlSchemaPCustomErr(ctxt,
12811 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12812 NULL, type, NULL,
12813 "A matching attribute use for the 'required' "
12814 "attribute use %s of the base type is missing",
12815 xmlSchemaFormatNsUriLocal(&str,
12816 xmlSchemaGetAttrTargetNsURI(base->attr),
12817 xmlSchemaGetAttrName(base->attr)));
12818 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012819 } else {
12820 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012821 * 2.1.3 [Definition:] Let the effective value
12822 * constraint of an attribute use be its {value
12823 * constraint}, if present, otherwise its {attribute
12824 * declaration}'s {value constraint} .
12825 */
12826 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12827 &bEffValue, 0);
12828 /*
12829 * 2.1.3 ... one of the following must be true
12830 *
12831 * 2.1.3.1 B's ·effective value constraint· is
12832 * ·absent· or default.
12833 */
12834 if ((bEffValue != NULL) &&
12835 (effFixed == 1)) {
12836 const xmlChar *rEffValue = NULL;
12837
12838 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12839 &rEffValue, 0);
12840 /*
12841 * 2.1.3.2 R's ·effective value constraint· is
12842 * fixed with the same string as B's.
12843 */
12844 if ((effFixed == 0) ||
12845 (! xmlStrEqual(rEffValue, bEffValue))) {
12846 xmlSchemaPAttrUseErr(ctxt,
12847 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12848 NULL, type, NULL, cur->attr,
12849 "The effective value constraint of the "
12850 "attribute use is inconsistent with "
12851 "its correspondent of the base type",
12852 NULL);
12853 }
12854 }
12855 /*
12856 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
12857 */
12858 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012859 * Override the attribute use.
12860 */
12861 base->attr = cur->attr;
12862 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012863
Daniel Veillard3646d642004-06-02 19:19:14 +000012864 break;
12865 }
12866 base = base->next;
12867 }
12868
12869 if (!found) {
12870 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12871 /*
12872 * derivation-ok-restriction 2.2
12873 */
12874 if ((type->attributeWildcard != NULL) &&
12875 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12876 cur->attr->targetNamespace))
12877 found = 1;
12878
12879 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012880 xmlSchemaPAttrUseErr(ctxt,
12881 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12882 NULL, type, NULL, cur->attr,
12883 "Neither a matching attribute use, "
12884 "nor a matching wildcard in the base type does exist",
12885 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012886 } else {
12887 /*
12888 * Add the attribute use.
12889 *
12890 * Note that this may lead to funny derivation error reports, if
12891 * multiple equal attribute uses exist; but this is not
12892 * allowed anyway, and it will be reported beforehand.
12893 */
12894 tmp = cur;
12895 if (prev != NULL)
12896 prev->next = cur->next;
12897 else
12898 uses = cur->next;
12899 cur = cur->next;
12900 if (type->attributeUses == NULL) {
12901 type->attributeUses = tmp;
12902 } else
12903 lastBaseUse->next = tmp;
12904 lastBaseUse = tmp;
12905
12906 continue;
12907 }
12908 }
12909 }
12910 prev = cur;
12911 cur = cur->next;
12912 }
12913 if (uses != NULL)
12914 xmlSchemaFreeAttributeUseList(uses);
12915 }
12916 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12917 /*
12918 * The spec allows only appending, and not other kinds of extensions.
12919 *
12920 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12921 */
12922 if (uses != NULL) {
12923 if (type->attributeUses == NULL) {
12924 type->attributeUses = uses;
12925 } else
12926 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012927 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012928 } else {
12929 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012930 * Derive implicitely from the ur-type.
12931 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012932 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012933 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012934 /*
12935 * 3.4.6 -> Complex Type Definition Properties Correct
12936 */
12937 if (type->attributeUses != NULL) {
12938 cur = type->attributeUses;
12939 prev = NULL;
12940 while (cur != NULL) {
12941 /*
12942 * 4. Two distinct attribute declarations in the {attribute uses} must
12943 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012944 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012945 * Note that this was already done for "restriction" and types derived from
12946 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012947 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012948 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12949 tmp = cur->next;
12950 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012951 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12952 xmlSchemaGetAttrName(tmp->attr))) &&
12953 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12954 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012955
Daniel Veillardc0826a72004-08-10 14:17:33 +000012956 xmlSchemaPAttrUseErr(ctxt,
12957 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12958 NULL, type, NULL, tmp->attr,
12959 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012960 break;
12961 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012962 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012963 }
12964 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012965 /*
12966 * 5. Two distinct attribute declarations in the {attribute uses} must
12967 * not have {type definition}s which are or are derived from ID.
12968 */
12969 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012970 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012971 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012972 xmlSchemaPAttrUseErr(ctxt,
12973 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12974 NULL, type, NULL, cur->attr,
12975 "There must not exist more than one attribute use, "
12976 "declared of type 'ID' or derived from it",
12977 NULL);
12978 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012979 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012980 id = cur;
12981 }
12982 /*
12983 * Remove "prohibited" attribute uses. The reason this is done at this late
12984 * stage is to be able to catch dublicate attribute uses. So we had to keep
12985 * prohibited uses in the list as well.
12986 */
12987 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12988 tmp = cur;
12989 if (prev == NULL)
12990 type->attributeUses = cur->next;
12991 else
12992 prev->next = cur->next;
12993 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012994 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012995 } else {
12996 prev = cur;
12997 cur = cur->next;
12998 }
12999 }
13000 }
13001 /*
13002 * TODO: This check should be removed if we are 100% sure of
13003 * the base type attribute uses already being built.
13004 */
13005 if ((baseType != NULL) && (!baseIsAnyType) &&
13006 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013007 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013008 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013009 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013010 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000013011 baseType->name, NULL);
13012 }
13013 return (0);
13014}
13015
13016/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013017 * xmlSchemaTypeFinalContains:
13018 * @schema: the schema
13019 * @type: the type definition
13020 * @final: the final
13021 *
13022 * Evaluates if a type definition contains the given "final".
13023 * This does take "finalDefault" into account as well.
13024 *
13025 * Returns 1 if the type does containt the given "final",
13026 * 0 otherwise.
13027 */
13028static int
13029xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
13030{
13031 int tfinal = final, tflags = type->flags;
13032
13033 if (type == NULL)
13034 return (0);
13035 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
13036 switch (final) {
13037 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
13038 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
13039 break;
13040 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
13041 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
13042 break;
13043 case XML_SCHEMAS_TYPE_FINAL_LIST:
13044 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
13045 break;
13046 case XML_SCHEMAS_TYPE_FINAL_UNION:
13047 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
13048 break;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013049 default:
13050 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013051 }
13052 tflags = schema->flags;
13053 }
13054 if (tflags & tfinal)
13055 return (1);
13056 else
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013057 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013058}
13059
13060/**
13061 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13062 * @type: the Union Simple Type
13063 *
13064 * Returns a list of member types of @type if existing,
13065 * returns NULL otherwise.
13066 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013067static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013068xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13069{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013070 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013071 if (type->memberTypes != NULL)
13072 return (type->memberTypes);
13073 else
13074 type = type->baseType;
13075 }
13076 return (NULL);
13077}
13078
13079/**
13080 * xmlSchemaGetListSimpleTypeItemType:
13081 * @type: the simple type definition
13082 *
13083 * Returns the item type definition of the list simple type.
13084 */
13085static xmlSchemaTypePtr
13086xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
13087{
13088 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
13089 return (NULL);
13090 /*
13091 * Note: In libxml2, the built-in types do not reflect
13092 * the datatype hierarchy (yet?) - we have to treat them
13093 * in a special way.
13094 */
13095 if (type->type == XML_SCHEMA_TYPE_BASIC)
13096 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 return (type->subtypes);
13098}
13099
13100
13101static int
13102xmlSchemaGetParticleTotalRangeMin(xmlSchemaTreeItemPtr particle)
13103{
13104 if ((particle->children == NULL) ||
13105 ( ((xmlSchemaParticlePtr) particle)->minOccurs == 0))
13106 return (0);
13107 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13108 int min = 0, cur;
13109 xmlSchemaTreeItemPtr part = particle->children->children;
13110
13111 if (part == NULL)
13112 return (0);
13113 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13114 (part->children->type == XML_SCHEMA_TYPE_ANY))
13115 min = ((xmlSchemaParticlePtr) part)->minOccurs;
13116 else
13117 min = xmlSchemaGetParticleTotalRangeMin(part);
13118 if (min == 0)
13119 return (0);
13120 part = part->next;
13121 while (part != NULL) {
13122 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13123 (part->children->type == XML_SCHEMA_TYPE_ANY))
13124 cur = ((xmlSchemaParticlePtr) part)->minOccurs;
13125 else
13126 cur = xmlSchemaGetParticleTotalRangeMin(part);
13127 if (cur == 0)
13128 return (0);
13129 if (min > cur)
13130 min = cur;
13131 part = part->next;
13132 }
13133 return (((xmlSchemaParticlePtr) particle)->minOccurs * min);
13134 } else {
13135 /* <all> and <sequence> */
13136 int sum = 0;
13137 xmlSchemaTreeItemPtr part = particle->children->children;
13138
13139 if (part == NULL)
13140 return (0);
13141 do {
13142 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13143 (part->children->type == XML_SCHEMA_TYPE_ANY))
13144 sum += ((xmlSchemaParticlePtr) part)->minOccurs;
13145 else
13146 sum += xmlSchemaGetParticleTotalRangeMin(part);
13147 part = part->next;
13148 } while (part != NULL);
13149 return (((xmlSchemaParticlePtr) particle)->minOccurs * sum);
13150 }
13151}
13152
13153
13154static int
13155xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13156{
13157 if ((particle == NULL) || (particle->minOccurs == 0) ||
13158 (particle->children == NULL))
13159 return (1);
13160
13161 if (IS_MODEL_GROUP(particle->children)) {
13162 if (xmlSchemaGetParticleTotalRangeMin(
13163 (xmlSchemaTreeItemPtr) particle) == 0)
13164 return (1);
13165 }
13166 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013167}
13168
13169/**
13170 * xmlSchemaCheckCOSSTDerivedOK:
13171 * @type: the derived simple type definition
13172 * @baseType: the base type definition
13173 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013174 * Schema Component Constraint:
13175 * Type Derivation OK (Simple) (cos-st-derived-OK)
13176 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013177 * Checks wheter @type can be validly
13178 * derived from @baseType.
13179 *
13180 * Returns 0 on success, an positive error code otherwise.
13181 */
13182static int
13183xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
13184 xmlSchemaTypePtr type,
13185 xmlSchemaTypePtr baseType,
13186 int subset)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013187{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013188 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013189 * 1 They are the same type definition.
13190 * TODO: The identy check might have to be more complex than this.
13191 */
13192 if (type == baseType)
13193 return (0);
13194 /*
13195 * 2.1 restriction is not in the subset, or in the {final}
13196 * of its own {base type definition};
13197 */
13198 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
13199 (xmlSchemaTypeFinalContains(schema,
13200 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13201 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
13202 }
13203 /* 2.2 */
13204 if (type->baseType == baseType) {
13205 /*
13206 * 2.2.1 D's ·base type definition· is B.
13207 */
13208 return (0);
13209 }
13210 /*
13211 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13212 * and is validly derived from B given the subset, as defined by this
13213 * constraint.
13214 */
13215 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
13216 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
13217 return (0);
13218 }
13219 /*
13220 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
13221 * definition·.
13222 */
13223 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13224 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
13225 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
13226 return (0);
13227 }
13228 /*
13229 * 2.2.4 B's {variety} is union and D is validly derived from a type
13230 * definition in B's {member type definitions} given the subset, as
13231 * defined by this constraint.
13232 *
13233 * NOTE: This seems not to involve built-in types, since there is no
13234 * built-in Union Simple Type.
13235 */
13236 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13237 xmlSchemaTypeLinkPtr cur;
13238
13239 cur = baseType->memberTypes;
13240 while (cur != NULL) {
13241 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
13242 cur->type, subset) == 0)
13243 return (0);
13244 cur = cur->next;
13245 }
13246 }
13247
13248 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13249}
13250
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013251/**
13252 * xmlSchemaCheckTypeDefCircularInternal:
13253 * @pctxt: the schema parser context
13254 * @ctxtType: the type definition
13255 * @ancestor: an ancestor of @ctxtType
13256 *
13257 * Checks st-props-correct (2) + ct-props-correct (3).
13258 * Circular type definitions are not allowed.
13259 *
13260 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13261 * circular, 0 otherwise.
13262 */
13263static int
13264xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13265 xmlSchemaTypePtr ctxtType,
13266 xmlSchemaTypePtr ancestor)
13267{
13268 int ret;
13269
13270 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13271 return (0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013272
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013273 if (ctxtType == ancestor) {
13274 xmlSchemaPCustomErr(pctxt,
13275 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13276 NULL, ctxtType, GET_NODE(ctxtType),
13277 "The definition is circular", NULL);
13278 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13279 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013280 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13281 /*
13282 * Avoid inifinite recursion on circular types not yet checked.
13283 */
13284 return (0);
13285 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013286 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13287 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13288 ancestor->baseType);
13289 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13290 return (ret);
13291}
13292
13293/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013294 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013295 * @item: the complex/simple type definition
13296 * @ctxt: the parser context
13297 * @name: the name
13298 *
13299 * Checks for circular type definitions.
13300 */
13301static void
13302xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
13303 xmlSchemaParserCtxtPtr ctxt,
13304 const xmlChar * name ATTRIBUTE_UNUSED)
13305{
13306 if ((item == NULL) ||
13307 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13308 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13309 return;
13310 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13311
13312}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013313
13314/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013315 * xmlSchemaResolveTypeDefs:
13316 * @item: the complex/simple type definition
13317 * @ctxt: the parser context
13318 * @name: the name
13319 *
13320 * Checks for circular type definitions.
13321 */
13322static void
13323xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
13324 xmlSchemaParserCtxtPtr ctxt,
13325 const xmlChar * name ATTRIBUTE_UNUSED)
13326{
13327 if (typeDef == NULL)
13328 return;
13329
13330 if (IS_SIMPLE_TYPE(typeDef)) {
13331 if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13332 /*
13333 * Resolve the memberTypes.
13334 */
13335 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13336 return;
13337 } else if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13338 /*
13339 * Resolve the itemType.
13340 */
13341 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13342 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13343 typeDef->ref, typeDef->refNs);
13344 if ((typeDef->subtypes == NULL) ||
13345 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13346 typeDef->subtypes = NULL;
13347 xmlSchemaPResCompAttrErr(ctxt,
13348 XML_SCHEMAP_SRC_RESOLVE,
13349 NULL, typeDef, typeDef->node,
13350 "itemType", typeDef->ref, typeDef->refNs,
13351 XML_SCHEMA_TYPE_SIMPLE, NULL);
13352 }
13353 }
13354 return;
13355 }
13356 }
13357 /*
13358 * Resolve the base type.
13359 */
13360 if (typeDef->baseType == NULL) {
13361 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13362 typeDef->base, typeDef->baseNs);
13363 if (typeDef->baseType == NULL) {
13364 xmlSchemaPResCompAttrErr(ctxt,
13365 XML_SCHEMAP_SRC_RESOLVE,
13366 NULL, typeDef, typeDef->node,
13367 "base", typeDef->base, typeDef->baseNs,
13368 XML_SCHEMA_TYPE_SIMPLE, NULL);
13369 return;
13370 }
13371 }
13372}
13373
13374
13375
13376/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013377 * xmlSchemaCheckSTPropsCorrect:
13378 * @ctxt: the schema parser context
13379 * @type: the simple type definition
13380 *
13381 * Checks st-props-correct.
13382 *
13383 * Returns 0 if the properties are correct,
13384 * if not, a positive error code and -1 on internal
13385 * errors.
13386 */
13387static int
13388xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13389 xmlSchemaTypePtr type)
13390{
13391 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13392 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013393 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013394
Daniel Veillardc0826a72004-08-10 14:17:33 +000013395 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013396 /*
13397 * Schema Component Constraint: Simple Type Definition Properties Correct
13398 *
13399 * NOTE: This is somehow redundant, since we actually built a simple type
13400 * to have all the needed information; this acts as an self test.
13401 */
13402 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13403 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013404 /* Base type: If the datatype has been ·derived· by ·restriction·
13405 * then the Simple Type Definition component from which it is ·derived·,
13406 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
13407 */
13408 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013409 /*
13410 * TODO: Think about: "modulo the impact of Missing
13411 * Sub-components (§5.3)."
13412 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013413 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013414 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013415 NULL, type, NULL,
13416 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013418
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013420 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013421 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013422 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013423 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013424 "The base type '%s' is not a simple type",
13425 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013426 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13428 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013429 if ((baseType->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
13430 ((type->flags &
13431 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13432 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13433 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013434 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013435 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013436 NULL, type, NULL,
13437 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013438 "the simple ur-type definition as base type, not '%s'",
13439 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013440 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13442 }
13443 /*
13444 * Variety: One of {atomic, list, union}.
13445 */
13446 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13447 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
13448 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013449 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013451 NULL, type, NULL,
13452 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013453 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13454 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013455 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013456
13457 /*
13458 * 3 The {final} of the {base type definition} must not contain restriction.
13459 */
13460 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
13461 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13462 xmlSchemaPCustomErr(ctxt,
13463 XML_SCHEMAP_ST_PROPS_CORRECT_3,
13464 NULL, type, NULL,
13465 "The 'final' of its base type '%s' must not contain "
13466 "'restriction'",
13467 xmlSchemaGetComponentQName(&str, baseType));
13468 FREE_AND_NULL(str)
13469 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
13470 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471
13472 /*
13473 * 2 All simple type definitions must be derived ultimately from the ·simple
13474 * ur-type definition (so· circular definitions are disallowed). That is, it
13475 * must be possible to reach a built-in primitive datatype or the ·simple
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013476 * ur-type definition· by repeatedly following the {base type definition}.
13477 *
13478 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 return (0);
13481}
13482
13483/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013484 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013485 * @ctxt: the schema parser context
13486 * @type: the simple type definition
13487 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013488 * Schema Component Constraint:
13489 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13490
13491 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013492 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013493 *
13494 * Returns -1 on internal errors, 0 if the type is validly derived,
13495 * a positive error code otherwise.
13496 */
13497static int
13498xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013499 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013500{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013501 xmlChar *str = NULL;
13502
Daniel Veillard01fa6152004-06-29 17:04:39 +000013503 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
13504 xmlSchemaPErr(ctxt, type->node,
13505 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013506 "xmlSchemaCheckCOSSTRestricts: The given "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013507 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013508 type->name, NULL);
13509 return (-1);
13510 }
13511
13512 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13513 xmlSchemaTypePtr primitive;
13514 /*
13515 * 1.1 The {base type definition} must be an atomic simple
13516 * type definition or a built-in primitive datatype.
13517 */
13518 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013519 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013521 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013522 "The base type '%s' is not an atomic simple type",
13523 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013524 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13526 }
13527 /* 1.2 The {final} of the {base type definition} must not contain
13528 * restriction.
13529 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013530 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013531 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13532 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013533 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013534 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013535 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013536 "The final of its base type '%s' must not contain 'restriction'",
13537 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013538 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013539 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13540 }
13541
13542 /*
13543 * 1.3.1 DF must be an allowed constraining facet for the {primitive
13544 * type definition}, as specified in the appropriate subsection of 3.2
13545 * Primitive datatypes.
13546 */
13547 if (type->facets != NULL) {
13548 xmlSchemaFacetPtr facet;
13549 int ok = 1;
13550
13551 primitive = xmlSchemaGetPrimitiveType(type);
13552 if (primitive == NULL) {
13553 xmlSchemaPErr(ctxt, type->node,
13554 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013555 "xmlSchemaCheckCOSSTRestricts: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013556 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013557 type->name, NULL);
13558 return (-1);
13559 }
13560 facet = type->facets;
13561 do {
13562 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013563 ok = 0;
13564 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013565 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013566 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013567 }
13568 facet = facet->next;
13569 } while (facet != NULL);
13570 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013571 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013572 }
13573 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013574 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13575 * of the {base type definition} (call this BF),then the DF's {value}
13576 * must be a valid restriction of BF's {value} as defined in
13577 * [XML Schemas: Datatypes]."
13578 *
13579 * NOTE (1.3.2) Facet derivation constraints are currently handled in
13580 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 */
13582 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13583 xmlSchemaTypePtr itemType = NULL;
13584
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013585 itemType = type->subtypes;
13586 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013587 xmlSchemaPErr(ctxt, type->node,
13588 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013589 "Internal error: xmlSchemaCheckCOSSTRestricts: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013590 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 type->name, NULL);
13592 return (-1);
13593 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013594 if (IS_NOT_TYPEFIXED(itemType))
13595 xmlSchemaTypeFixup(itemType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013596 /*
13597 * 2.1 The {item type definition} must have a {variety} of atomic or
13598 * union (in which case all the {member type definitions}
13599 * must be atomic).
13600 */
13601 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13602 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013603 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013604 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013605 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013606 "The item type '%s' does not have a variety of atomic or union",
13607 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013608 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13610 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13611 xmlSchemaTypeLinkPtr member;
13612
13613 member = itemType->memberTypes;
13614 while (member != NULL) {
13615 if ((member->type->flags &
13616 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013617 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013618 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013619 NULL, type, NULL,
13620 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013621 "member type '%s' of this item type is not atomic",
13622 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013623 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013624 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13625 }
13626 member = member->next;
13627 }
13628 }
13629
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013630 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013631 xmlSchemaFacetPtr facet;
13632 /*
13633 * This is the case if we have: <simpleType><list ..
13634 */
13635 /*
13636 * 2.3.1
13637 * 2.3.1.1 The {final} of the {item type definition} must not
13638 * contain list.
13639 */
13640 if (xmlSchemaTypeFinalContains(ctxt->schema,
13641 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013642 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013643 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013644 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013645 "The final of its item type '%s' must not contain 'list'",
13646 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013647 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013648 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13649 }
13650 /*
13651 * 2.3.1.2 The {facets} must only contain the whiteSpace
13652 * facet component.
13653 */
13654 if (type->facets != NULL) {
13655 facet = type->facets;
13656 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013657 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13658 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013659 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013660 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013661 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13662 }
13663 facet = facet->next;
13664 } while (facet != NULL);
13665 }
13666 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013667 * MABY TODO: (Hmm, not really) Datatypes states:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013668 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13669 * whose ·lexical space· allows space (such as string or anyURI)or
13670 * a ·union· datatype any of whose {member type definitions}'s
13671 * ·lexical space· allows space.
13672 */
13673 } else {
13674 /*
13675 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013676 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013677 */
13678 /*
13679 * 2.3.2
13680 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13681 */
13682 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013683 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013684 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013685 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013686 "The base type '%s' must be a list type",
13687 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013688 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13690 }
13691 /*
13692 * 2.3.2.2 The {final} of the {base type definition} must not
13693 * contain restriction.
13694 */
13695 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13696 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013697 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013699 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013700 "The 'final' of the base type '%s' must not contain 'restriction'",
13701 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013702 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13704 }
13705 /*
13706 * 2.3.2.3 The {item type definition} must be validly derived
13707 * from the {base type definition}'s {item type definition} given
13708 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13709 */
13710 {
13711 xmlSchemaTypePtr baseItemType;
13712
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013713 baseItemType = type->baseType->subtypes;
13714 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 xmlSchemaPErr(ctxt, type->node,
13716 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013717 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013718 "List simple type '%s': Failed to "
13719 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013720 type->name, type->baseType->name);
13721 return (-1);
13722 }
13723 if ((itemType != baseItemType) &&
13724 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
13725 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013726 xmlChar *strBIT = NULL, *strBT = NULL;
13727 xmlSchemaPCustomErrExt(ctxt,
13728 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
13729 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013730 "The item type '%s' is not validly derived from the "
13731 "item type '%s' of the base type '%s'",
13732 xmlSchemaGetComponentQName(&str, itemType),
13733 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13734 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013735
13736 FREE_AND_NULL(str)
13737 FREE_AND_NULL(strBIT)
13738 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13740 }
13741 }
13742
13743 if (type->facets != NULL) {
13744 xmlSchemaFacetPtr facet;
13745 int ok = 1;
13746 /*
13747 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
13748 * and enumeration facet components are allowed among the {facets}.
13749 */
13750 facet = type->facets;
13751 do {
13752 switch (facet->type) {
13753 case XML_SCHEMA_FACET_LENGTH:
13754 case XML_SCHEMA_FACET_MINLENGTH:
13755 case XML_SCHEMA_FACET_MAXLENGTH:
13756 case XML_SCHEMA_FACET_WHITESPACE:
13757 /*
13758 * TODO: 2.5.1.2 List datatypes
13759 * The value of ·whiteSpace· is fixed to the value collapse.
13760 */
13761 case XML_SCHEMA_FACET_PATTERN:
13762 case XML_SCHEMA_FACET_ENUMERATION:
13763 break;
13764 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013765 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013767 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 /*
13769 * We could return, but it's nicer to report all
13770 * invalid facets.
13771 */
13772 ok = 0;
13773 }
13774 }
13775 facet = facet->next;
13776 } while (facet != NULL);
13777 if (ok == 0)
13778 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13779 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013780 * SPEC (2.3.2.5) (same as 1.3.2)
13781 *
13782 * NOTE (2.3.2.5) This is currently done in
13783 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 */
13785 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013786 }
13787 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13788 /*
13789 * 3.1 The {member type definitions} must all have {variety} of
13790 * atomic or list.
13791 */
13792 xmlSchemaTypeLinkPtr member;
13793
13794 member = type->memberTypes;
13795 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013796 if (IS_NOT_TYPEFIXED(member->type))
13797 xmlSchemaTypeFixup(member->type, ctxt, NULL);
13798
Daniel Veillard01fa6152004-06-29 17:04:39 +000013799 if (((member->type->flags &
13800 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13801 ((member->type->flags &
13802 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013803 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013805 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013806 "The member type '%s' is neither an atomic, nor a list type",
13807 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013809 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13810 }
13811 member = member->next;
13812 }
13813 /*
13814 * 3.3.1 If the {base type definition} is the ·simple ur-type
13815 * definition·
13816 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013817 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 /*
13819 * 3.3.1.1 All of the {member type definitions} must have a
13820 * {final} which does not contain union.
13821 */
13822 member = type->memberTypes;
13823 while (member != NULL) {
13824 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
13825 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013826 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013828 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013829 "The 'final' of member type '%s' contains 'union'",
13830 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013831 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13833 }
13834 member = member->next;
13835 }
13836 /*
13837 * 3.3.1.2 The {facets} must be empty.
13838 */
13839 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013840 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013841 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013842 NULL, type, NULL,
13843 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013844 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13845 }
13846 } else {
13847 /*
13848 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013849 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013850 */
13851 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013852 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013853 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013854 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013855 "The base type '%s' is not a union type",
13856 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013857 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13859 }
13860 /*
13861 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13862 */
13863 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13864 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013865 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013866 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013867 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013868 "The 'final' of its base type '%s' must not contain 'restriction'",
13869 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013870 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13872 }
13873 /*
13874 * 3.3.2.3 The {member type definitions}, in order, must be validly
13875 * derived from the corresponding type definitions in the {base
13876 * type definition}'s {member type definitions} given the empty set,
13877 * as defined in Type Derivation OK (Simple) (§3.14.6).
13878 */
13879 {
13880 xmlSchemaTypeLinkPtr baseMember;
13881
13882 /*
13883 * OPTIMIZE: if the type is restricting, it has no local defined
13884 * member types and inherits the member types of the base type;
13885 * thus a check for equality can be skipped.
13886 */
13887 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013888 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000013889 * union simple type can have other member types as the member
13890 * types of it's base type. This check seems not necessary with
13891 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013892 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013893 */
13894 if (type->memberTypes != NULL) {
13895 member = type->memberTypes;
13896 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
13897 if ((member == NULL) && (baseMember != NULL)) {
13898 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013899 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013900 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013901 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 "of member types in the base type\n",
13903 type->name, NULL);
13904 }
13905 while (member != NULL) {
13906 if (baseMember == NULL) {
13907 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013908 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013909 "Internal error: "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013910 "xmlSchemaCheckCOSSTRestricts "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013911 "(3.3.2.3), union simple type '%s', unequal number "
13912 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013913 type->name, NULL);
13914 }
13915 if ((member->type != baseMember->type) &&
13916 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
13917 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 xmlChar *strBMT = NULL, *strBT = NULL;
13919
13920 xmlSchemaPCustomErrExt(ctxt,
13921 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13922 NULL, type, NULL,
13923 "The member type %s is not validly derived from its "
13924 "corresponding member type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013925 xmlSchemaGetComponentQName(&str, member->type),
13926 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13927 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013928 FREE_AND_NULL(str)
13929 FREE_AND_NULL(strBMT)
13930 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013931 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
13932 }
13933 member = member->next;
13934 baseMember = baseMember->next;
13935 }
13936 }
13937 }
13938 /*
13939 * 3.3.2.4 Only pattern and enumeration facet components are
13940 * allowed among the {facets}.
13941 */
13942 if (type->facets != NULL) {
13943 xmlSchemaFacetPtr facet;
13944 int ok = 1;
13945
13946 facet = type->facets;
13947 do {
13948 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13949 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013950 xmlSchemaPIllegalFacetListUnionErr(ctxt,
13951 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
13952 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013953 ok = 0;
13954 }
13955 facet = facet->next;
13956 } while (facet != NULL);
13957 if (ok == 0)
13958 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
13959
13960 }
13961 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013962 * SPEC (3.3.2.5) (same as 1.3.2)
13963 *
13964 * NOTE (3.3.2.5) This is currently done in
13965 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013966 */
13967 }
13968 }
13969
13970 return (0);
13971}
13972
13973/**
13974 * xmlSchemaCheckSRCSimpleType:
13975 * @ctxt: the schema parser context
13976 * @type: the simple type definition
13977 *
13978 * Checks crc-simple-type constraints.
13979 *
13980 * Returns 0 if the constraints are satisfied,
13981 * if not a positive error code and -1 on internal
13982 * errors.
13983 */
13984static int
13985xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13986 xmlSchemaTypePtr type)
13987{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013988 /*
13989 * src-simple-type.1 The corresponding simple type definition, if any,
13990 * must satisfy the conditions set out in Constraints on Simple Type
13991 * Definition Schema Components (§3.14.6).
13992 */
13993 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13994 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13995 /*
13996 * TODO: Removed this, since it got annoying to get an
13997 * extra error report, if anything failed until now.
13998 * Enable this if needed.
13999 */
14000 /*
14001 xmlSchemaPErr(ctxt, type->node,
14002 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014003 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014004 "on simple type definitions.\n",
14005 type->name, NULL);
14006 */
14007 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14008 }
14009
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014010 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 /*
14012 * src-simple-type.2 If the <restriction> alternative is chosen,
14013 * either it must have a base [attribute] or a <simpleType> among its
14014 * [children], but not both.
14015 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014016 /*
14017 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014018 * NOTE: This is checked in the parse function of <restriction>.
William M. Brack2f2a6632004-08-20 23:09:47 +000014019 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014020 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014021 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14022 * an itemType [attribute] or a <simpleType> among its [children],
14023 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014024 *
14025 * REMOVED: This is checked in the parse function of <list>.
14026 */
14027 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014028 xmlSchemaTypeLinkPtr member;
14029 xmlSchemaTypePtr ancestor, anySimpleType;
14030
14031 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14032
14033 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14034 * the <union> alternative is chosen, there must not be any entries
14035 * in the memberTypes [attribute] at any depth which resolve to the
14036 * component corresponding to the <simpleType>.
14037 */
14038 member = type->memberTypes;
14039 while (member != NULL) {
14040 ancestor = member->type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014041 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
14042 if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014043 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014044 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014045 NULL, type, NULL,
14046 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014047 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014048 }
14049 if (IS_NOT_TYPEFIXED(ancestor))
14050 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
14051 if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014052 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014053 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000014054 * type as item type, which in turn has a list ST as member
14055 * type, we will assume this here as well, since this check
14056 * was not yet performed.
14057 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014058 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014059
Daniel Veillard01fa6152004-06-29 17:04:39 +000014060 ancestor = ancestor->baseType;
14061 }
14062 member = member->next;
14063 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014064 }
14065
14066 return (0);
14067}
14068
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014069#if 0 /* Not yet used code for ST schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000014070static int
14071xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
14072 const xmlChar * value,
14073 xmlSchemaTypePtr type,
14074 int fireErrors)
14075{
14076 int ret;
14077 /*
14078 * 3.14.4 Simple Type Definition Validation Rules
14079 * Validation Rule: String Valid
14080 */
14081 /*
14082 * 1 It is schema-valid with respect to that definition as defined
14083 * by Datatype Valid in [XML Schemas: Datatypes].
14084 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014085 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14086 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000014087 return (ret);
14088 /*
14089 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
14090 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
14091 * the string must be a ·declared entity name·.
14092 */
14093 /*
14094 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
14095 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
14096 * then every whitespace-delimited substring of the string must be a ·declared
14097 * entity name·.
14098 */
14099 /*
14100 * 2.3 otherwise no further condition applies.
14101 */
14102
14103 return (0);
14104}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014105#endif
14106
William M. Brack2f2a6632004-08-20 23:09:47 +000014107
14108static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014109xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
14110{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000014111 if (vctxt->pctxt == NULL) {
14112 if (vctxt->schema != NULL)
14113 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
14114 else
14115 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014116 if (vctxt->pctxt == NULL) {
14117 xmlSchemaVErr(vctxt, NULL,
14118 XML_SCHEMAV_INTERNAL,
14119 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14120 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000014121 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014122 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014123 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014124 /* TODO: Pass user data. */
14125 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
14126 }
14127 return (0);
14128}
14129
14130static int
14131xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14132{
14133 if (ctxt->vctxt == NULL) {
14134 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14135 if (ctxt->vctxt == NULL) {
14136 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014137 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014138 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14139 "failed to create a temp. validation context.\n",
14140 NULL, NULL);
14141 return (-1);
14142 }
14143 /* TODO: Pass user data. */
14144 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
14145 }
14146 return (0);
14147}
14148
14149/**
14150 * xmlSchemaCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014151 * @pctxt: the schema parser context
14152 * @vctxt: the temporary schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014153 * @type: the simple type definition
14154 * @value: the default value
14155 * @node: an optional node (the holder of the value)
14156 *
14157 * Checks the "cos-valid-default" constraints.
14158 *
14159 * Returns 0 if the constraints are satisfied,
14160 * if not, a positive error code and -1 on internal
14161 * errors.
14162 */
14163static int
14164xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14165 xmlSchemaValidCtxtPtr vctxt,
14166 xmlSchemaTypePtr type,
14167 const xmlChar *value,
14168 xmlNodePtr node)
14169{
14170 int ret = 0;
14171
14172 /*
14173 * cos-valid-default:
14174 * Schema Component Constraint: Element Default Valid (Immediate)
14175 * For a string to be a valid default with respect to a type
14176 * definition the appropriate case among the following must be true:
14177 */
14178 /*
14179 * NOTE: This has to work without a given node (the holder of the
14180 * value), since it should work on the component, i.e. an underlying
14181 * DOM must not be mandatory.
14182 */
14183 if ((pctxt == NULL) || (vctxt == NULL)) {
14184 xmlSchemaPErr(pctxt, node,
14185 XML_SCHEMAP_INTERNAL,
14186 "Internal error: xmlSchemaCheckCOSValidDefault, "
14187 "bad arguments: the parser and/or validation context is "
14188 "missing.\n",
14189 NULL, NULL);
14190 return (-1);
14191 }
14192 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014193 /*
14194 * Complex type.
14195 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014196 * SPEC (2.1) "its {content type} must be a simple type definition
14197 * or mixed."
14198 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
14199 * type}'s particle must be ·emptiable· as defined by
14200 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014201 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014202 if ((! HAS_SIMPLE_CONTENT(type)) &&
14203 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14204 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014205 xmlSchemaPSimpleTypeErr(pctxt,
14206 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
14207 NULL, NULL, node,
14208 type, NULL, NULL,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014209 "For a string to be a valid default, the type definition "
14210 "must be a simple type or a complex type with mixed content "
14211 "and a particle emptiable",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014212 NULL, NULL);
14213 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14214 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014215 }
14216 /*
14217 * 1 If the type definition is a simple type definition, then the string
14218 * must be ·valid· with respect to that definition as defined by String
14219 * Valid (§3.14.4).
14220 *
14221 * AND
14222 *
14223 * 2.2.1 If the {content type} is a simple type definition, then the
14224 * string must be ·valid· with respect to that simple type definition
14225 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014226 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014227 vctxt->node = node;
14228 vctxt->cur = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014229 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014230 if (IS_SIMPLE_TYPE(type))
14231 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value,
14232 1, 1, 1, 0);
14233 else if (HAS_SIMPLE_CONTENT(type))
14234 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type->contentTypeDef,
14235 value, 1, 1, 1, 0);
14236 else
14237 return (ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014238 if (ret != 0) {
14239 pctxt->err = vctxt->err;
14240 pctxt->nberrors++;
14241 }
14242
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014243 if (ret < 0) {
14244 xmlSchemaPErr(pctxt, node,
14245 /* NOTNICE: error code: This function will be used during
14246 * schema construction and xsi:type validation.
14247 */
14248 XML_SCHEMAP_INTERNAL,
14249 "Internal error: xmlSchemaCheckCOSValidDefault, "
14250 "while validating a value constaint value.\n",
14251 NULL, NULL);
14252
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014253 }
14254
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014255 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014256}
14257
14258/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014259 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014260 * @ctxt: the schema parser context
14261 * @type: the complex type definition
14262 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014263 *.(4.6) Constraints on Complex Type Definition Schema Components
14264 * Schema Component Constraint:
14265 * Complex Type Definition Properties Correct (ct-props-correct)
14266 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014267 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014268 * Returns 0 if the constraints are satisfied, a positive
14269 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014270 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014271static int
14272xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14273 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014274{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014275 /*
14276 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14277 *
14278 * SPEC (1) "The values of the properties of a complex type definition must
14279 * be as described in the property tableau in The Complex Type Definition
14280 * Schema Component (§3.4.1), modulo the impact of Missing
14281 * Sub-components (§5.3)."
14282 */
14283 if ((type->baseType != NULL) &&
14284 (IS_SIMPLE_TYPE(type->baseType)) &&
14285 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14286 /*
14287 * SPEC (2) "If the {base type definition} is a simple type definition,
14288 * the {derivation method} must be extension."
14289 */
14290 xmlSchemaPCustomErr(pctxt,
14291 XML_SCHEMAP_SRC_CT_1,
14292 NULL, type, NULL,
14293 "If the base type is a simple type, the derivation method must be "
14294 "'extension'", NULL);
14295 return (XML_SCHEMAP_SRC_CT_1);
14296 }
14297 /*
14298 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14299 * definition·. That is, it must be possible to reach the ·ur-type
14300 * definition by repeatedly following the {base type definition}."
14301 *
14302 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14303 *
14304 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
14305 * must not have identical {name}s and {target namespace}s."
14306 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14307 * must not have {type definition}s which are or are derived from ID."
14308 *
14309 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14310 */
14311 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014312}
14313
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014314static int
14315xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14316 xmlSchemaTypePtr typeB)
14317{
14318 /*
14319 * TODO: This should implement component-identity
14320 * in the future.
14321 */
14322 if ((typeA == NULL) || (typeB == NULL))
14323 return (0);
14324 return (typeA == typeB);
14325}
14326
14327/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014328 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014329 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014330 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014331 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014332 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014333 *
14334 * Schema Component Constraint:
14335 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14336 *
14337 * STATUS: completed
14338 *
14339 * Returns 0 if the constraints are satisfied, or 1
14340 * if not.
14341 */
14342static int
14343xmlSchemaCheckCOSCTDerivedOK(xmlSchemaPtr schema,
14344 xmlSchemaTypePtr type,
14345 xmlSchemaTypePtr baseType,
14346 int set)
14347{
14348 int equal = xmlSchemaAreEqualTypes(type, baseType);
14349 /* TODO: Error codes. */
14350 /*
14351 * SPEC "For a complex type definition (call it D, for derived)
14352 * to be validly derived from a type definition (call this
14353 * B, for base) given a subset of {extension, restriction}
14354 * all of the following must be true:"
14355 */
14356 if (! equal) {
14357 /*
14358 * SPEC (1) "If B and D are not the same type definition, then the
14359 * {derivation method} of D must not be in the subset."
14360 */
14361 if (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
14362 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
14363 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
14364 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014365 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014366 } else {
14367 /*
14368 * SPEC (2.1) "B and D must be the same type definition."
14369 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014370 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014371 }
14372 /*
14373 * SPEC (2.2) "B must be D's {base type definition}."
14374 */
14375 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014376 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014377 /*
14378 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14379 * definition·."
14380 */
14381 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014382 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014383
14384 if (IS_COMPLEX_TYPE(type->baseType)) {
14385 /*
14386 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14387 * must be validly derived from B given the subset as defined by this
14388 * constraint."
14389 */
14390 return (xmlSchemaCheckCOSCTDerivedOK(schema, type->baseType,
14391 baseType, set));
14392 } else {
14393 /*
14394 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14395 * must be validly derived from B given the subset as defined in Type
14396 * Derivation OK (Simple) (§3.14.6).
14397 */
14398 return (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType,
14399 set));
14400 }
14401}
14402
14403/**
14404 * xmlSchemaCheckCOSDerivedOK:
14405 * @type: the derived simple type definition
14406 * @baseType: the base type definition
14407 *
14408 * Calls:
14409 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
14410 *
14411 * Checks wheter @type can be validly derived from @baseType.
14412 *
14413 * Returns 0 on success, an positive error code otherwise.
14414 */
14415static int
14416xmlSchemaCheckCOSDerivedOK(xmlSchemaPtr schema,
14417 xmlSchemaTypePtr type,
14418 xmlSchemaTypePtr baseType,
14419 int set)
14420{
14421 if (IS_SIMPLE_TYPE(type))
14422 return (xmlSchemaCheckCOSSTDerivedOK(schema, type, baseType, set));
14423 else
14424 return (xmlSchemaCheckCOSCTDerivedOK(schema, type, baseType, set));
14425}
14426
William M. Brack2f2a6632004-08-20 23:09:47 +000014427/**
14428 * xmlSchemaCheckCOSCTExtends:
14429 * @ctxt: the schema parser context
14430 * @type: the complex type definition
14431 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014432 * (3.4.6) Constraints on Complex Type Definition Schema Components
14433 * Schema Component Constraint:
14434 * Derivation Valid (Extension) (cos-ct-extends)
14435 *
14436 * STATUS:
14437 * missing:
14438 * (1.5)
14439 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014440 *
14441 * Returns 0 if the constraints are satisfied, a positive
14442 * error code if not and -1 if an internal error occured.
14443 */
14444static int
14445xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14446 xmlSchemaTypePtr type)
14447{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014448 xmlSchemaTypePtr base = type->baseType;
14449 /*
14450 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14451 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014452 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014453 /*
14454 * SPEC (1) "If the {base type definition} is a complex type definition,
14455 * then all of the following must be true:"
14456 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014457 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14458 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014459 * SPEC (1.1) "The {final} of the {base type definition} must not
14460 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014461 */
14462 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14463 xmlSchemaPCustomErr(ctxt,
14464 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14465 NULL, type, NULL,
14466 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014467 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014468 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14469 }
14470 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014471 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
14472 * uses}
William M. Brack2f2a6632004-08-20 23:09:47 +000014473 * of the complex type definition itself, that is, for every attribute
14474 * use in the {attribute uses} of the {base type definition}, there
14475 * must be an attribute use in the {attribute uses} of the complex
14476 * type definition itself whose {attribute declaration} has the same
14477 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014478 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014479 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014480 * NOTE (1.2): This will be already satisfied by the way the attribute
14481 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14482 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014483 */
14484
14485 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014486 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14487 * definition must also have one, and the base type definition's
14488 * {attribute wildcard}'s {namespace constraint} must be a subset
14489 * of the complex type definition's {attribute wildcard}'s {namespace
14490 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014491 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014492 * NOTE (1.3) This is already checked in
14493 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014494 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014495 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014496 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014497 if ((type->contentTypeDef != NULL) &&
14498 (type->contentTypeDef == base->contentTypeDef)) {
14499 /*
14500 * SPEC (1.4.1) "The {content type} of the {base type definition}
14501 * and the {content type} of the complex type definition itself
14502 * must be the same simple type definition"
14503 * PASS
14504 */
14505 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14506 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14507 /*
14508 * SPEC (1.4.2) "The {content type} of both the {base type
14509 * definition} and the complex type definition itself must
14510 * be empty."
14511 * PASS
14512 */
14513 } else {
14514 /*
14515 * SPEC (1.4.3) "All of the following must be true:"
14516 */
14517 if (type->subtypes == NULL) {
14518 /*
14519 * SPEC 1.4.3.1 The {content type} of the complex type
14520 * definition itself must specify a particle.
14521 */
14522 xmlSchemaPCustomErr(ctxt,
14523 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14524 NULL, type, NULL,
14525 "The content type must specify a particle", NULL);
14526 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14527 }
14528 /*
14529 * SPEC (1.4.3.2) "One of the following must be true:"
14530 */
14531 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14532 /*
14533 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14534 * definition} must be empty.
14535 * PASS
14536 */
14537 } else {
14538 /*
14539 * SPEC (1.4.3.2.2) "All of the following must be true:"
14540 */
14541 if ((type->contentType != base->contentType) ||
14542 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14543 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14544 /*
14545 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14546 * or both must be element-only."
14547 */
14548 xmlSchemaPCustomErr(ctxt,
14549 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14550 NULL, type, NULL,
14551 "The content type of both, the type and its base "
14552 "type, must either 'mixed' or 'element-only'", NULL);
14553 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14554 }
14555 /*
14556 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14557 * complex type definition must be a ·valid extension·
14558 * of the {base type definition}'s particle, as defined
14559 * in Particle Valid (Extension) (§3.9.6)."
14560 *
14561 * NOTE that we won't check "Particle Valid (Extension)",
14562 * since it is ensured by the derivation process in
14563 * xmlSchemaTypeFixup(). We need to implement this when heading
14564 * for a construction API
14565 */
14566 }
14567 /*
14568 * TODO (1.5)
14569 */
14570 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014571 } else {
14572 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014573 * SPEC (2) "If the {base type definition} is a simple type definition,
14574 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014575 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014576 if (type->contentTypeDef != base) {
14577 /*
14578 * SPEC (2.1) "The {content type} must be the same simple type
14579 * definition."
14580 */
14581 xmlSchemaPCustomErr(ctxt,
14582 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14583 NULL, type, NULL,
14584 "The content type must be the simple base type", NULL);
14585 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14586 }
14587 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14588 /*
14589 * SPEC (2.2) "The {final} of the {base type definition} must not
14590 * contain extension"
14591 * NOTE that this is the same as (1.1).
14592 */
14593 xmlSchemaPCustomErr(ctxt,
14594 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14595 NULL, type, NULL,
14596 "The 'final' of the base type definition "
14597 "contains 'extension'", NULL);
14598 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14599 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014600 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014601 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014602}
14603
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014604/**
14605 * xmlSchemaCheckDerivationOKRestriction:
14606 * @ctxt: the schema parser context
14607 * @type: the complex type definition
14608 *
14609 * (3.4.6) Constraints on Complex Type Definition Schema Components
14610 * Schema Component Constraint:
14611 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14612 *
14613 * STATUS:
14614 * missing:
14615 * (5.4.2), (5.2.2.1)
14616 *
14617 * Returns 0 if the constraints are satisfied, a positive
14618 * error code if not and -1 if an internal error occured.
14619 */
14620static int
14621xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14622 xmlSchemaTypePtr type)
14623{
14624 xmlSchemaTypePtr base;
14625
14626 /*
14627 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14628 * temporarily only.
14629 */
14630 base = type->baseType;
14631 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14632 /*
14633 * SPEC (1) "The {base type definition} must be a complex type
14634 * definition whose {final} does not contain restriction."
14635 */
14636 xmlSchemaPCustomErr(ctxt,
14637 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14638 NULL, type, NULL,
14639 "The 'final' of the base type definition "
14640 "contains 'restriction'", NULL);
14641 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14642 }
14643 /*
14644 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14645 *
14646 * SPEC (5) "One of the following must be true:"
14647 */
14648 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14649 /*
14650 * SPEC (5.1) "The {base type definition} must be the
14651 * ·ur-type definition·."
14652 * PASS
14653 */
14654 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14655 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14656 /*
14657 * SPEC (5.2.1) "The {content type} of the complex type definition
14658 * must be a simple type definition"
14659 *
14660 * SPEC (5.2.2) "One of the following must be true:"
14661 */
14662 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14663 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14664 /*
14665 * SPEC (5.2.2.1) "The {content type} of the {base type
14666 * definition} must be a simple type definition from which
14667 * the {content type} is validly derived given the empty
14668 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14669 * URGENT TODO
14670 */
14671 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14672 (xmlSchemaIsParticleEmptiable(
14673 (xmlSchemaParticlePtr) base->subtypes))) {
14674 /*
14675 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14676 * and have a particle which is ·emptiable· as defined in
14677 * Particle Emptiable (§3.9.6)."
14678 * PASS
14679 */
14680 } else {
14681 xmlSchemaPCustomErr(ctxt,
14682 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14683 NULL, type, NULL,
14684 "The content type of the base type must be either "
14685 "a simple type or 'mixed' and an emptiable particle", NULL);
14686 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14687 }
14688 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14689 /*
14690 * SPEC (5.3.1) "The {content type} of the complex type itself must
14691 * be empty"
14692 */
14693 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14694 /*
14695 * SPEC (5.3.2.1) "The {content type} of the {base type
14696 * definition} must also be empty."
14697 * PASS
14698 */
14699 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14700 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14701 xmlSchemaIsParticleEmptiable(
14702 (xmlSchemaParticlePtr) base->subtypes)) {
14703 /*
14704 * SPEC (5.3.2.2) "The {content type} of the {base type
14705 * definition} must be elementOnly or mixed and have a particle
14706 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14707 * PASS
14708 */
14709 } else {
14710 xmlSchemaPCustomErr(ctxt,
14711 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14712 NULL, type, NULL,
14713 "The content type of the base type must be either "
14714 "empty or 'mixed' (or 'elements-only') and an emptiable "
14715 "particle", NULL);
14716 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14717 }
14718 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14719 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14720 (base->contentType == XML_SCHEMA_CONTENT_MIXED))) {
14721 /*
14722 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14723 * itself must be element-only"
14724 * SPEC (5.4.1.2) "The {content type} of the complex type definition
14725 * itself and of the {base type definition} must be mixed"
14726 */
14727 /*
14728 * SPEC (5.4.2) "The particle of the complex type definition itself
14729 * must be a ·valid restriction· of the particle of the {content
14730 * type} of the {base type definition} as defined in Particle Valid
14731 * (Restriction) (§3.9.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014732 * URGENT TODO: (5.4.2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014733 */
14734 } else {
14735 xmlSchemaPCustomErr(ctxt,
14736 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14737 NULL, type, NULL,
14738 "The type is not a valid restriction of its base type", NULL);
14739 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14740 }
14741 return (0);
14742}
14743
14744/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014745 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014746 * @ctxt: the schema parser context
14747 * @type: the complex type definition
14748 *
14749 * (3.4.6) Constraints on Complex Type Definition Schema Components
14750 *
14751 * Returns 0 if the constraints are satisfied, a positive
14752 * error code if not and -1 if an internal error occured.
14753 */
14754static int
14755xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14756 xmlSchemaTypePtr type)
14757{
14758 int ret;
14759 /*
14760 * Complex Type Definition Properties Correct
14761 */
14762 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14763 if (ret != 0)
14764 return (ret);
14765 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14766 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14767 else
14768 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14769 return (ret);
14770}
14771
14772/**
14773 * xmlSchemaCheckSRCCT:
14774 * @ctxt: the schema parser context
14775 * @type: the complex type definition
14776 *
14777 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
14778 * Schema Representation Constraint:
14779 * Complex Type Definition Representation OK (src-ct)
14780 *
14781 * Returns 0 if the constraints are satisfied, a positive
14782 * error code if not and -1 if an internal error occured.
14783 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014784static int
14785xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
14786 xmlSchemaTypePtr type)
14787{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014788 xmlSchemaTypePtr base;
14789 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014790
14791 /*
14792 * TODO: Adjust the error codes here, as I used
14793 * XML_SCHEMAP_SRC_CT_1 only yet.
14794 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014795 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014796 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014797 /*
14798 * 1 If the <complexContent> alternative is chosen, the type definition
14799 * ·resolved· to by the ·actual value· of the base [attribute]
14800 * must be a complex type definition;
14801 */
14802 if (! IS_COMPLEX_TYPE(base)) {
14803 xmlChar *str = NULL;
14804 xmlSchemaPCustomErr(ctxt,
14805 XML_SCHEMAP_SRC_CT_1,
14806 NULL, type, type->node,
14807 "If using <complexContent>, the base type is expected to be "
14808 "a complex type. The base type '%s' is a simple type",
14809 xmlSchemaFormatQName(&str, base->targetNamespace,
14810 base->name));
14811 FREE_AND_NULL(str)
14812 return (XML_SCHEMAP_SRC_CT_1);
14813 }
14814 } else {
14815 /*
14816 * SPEC
14817 * 2 If the <simpleContent> alternative is chosen, all of the
14818 * following must be true:
14819 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14820 * base [attribute] must be one of the following:
14821 */
14822 if (IS_SIMPLE_TYPE(base)) {
14823 if ((type->flags &
14824 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14825 xmlChar *str = NULL;
14826 /*
14827 * 2.1.3 only if the <extension> alternative is also
14828 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014829 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014830 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014831 xmlSchemaPCustomErr(ctxt,
14832 XML_SCHEMAP_SRC_CT_1,
14833 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014834 "If using <simpleContent> and <restriction>, the base "
14835 "type must be a complex type. The base type '%s' is "
14836 "a simple type",
14837 xmlSchemaFormatQName(&str, base->targetNamespace,
14838 base->name));
14839 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014840 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014841 }
14842 } else {
14843 /* Base type is a complex type. */
14844 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14845 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14846 /*
14847 * 2.1.1 a complex type definition whose {content type} is a
14848 * simple type definition;
14849 * PASS
14850 */
14851 if (base->contentTypeDef == NULL) {
14852 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014853 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014854 "Internal error: xmlSchemaCheckSRCCT, "
14855 "'%s', base type has no content type",
14856 type->name);
14857 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014858 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014859 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14860 (type->flags &
14861 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014862
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014863 /*
14864 * 2.1.2 only if the <restriction> alternative is also
14865 * chosen, a complex type definition whose {content type}
14866 * is mixed and a particle emptiable.
14867 */
14868 if (! xmlSchemaIsParticleEmptiable(
14869 (xmlSchemaParticlePtr) base->subtypes)) {
14870 ret = XML_SCHEMAP_SRC_CT_1;
14871 } else if ((type->contentTypeDef == NULL) ||
14872 (type->contentTypeDef->baseType == NULL)) {
14873 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014874 /*
14875 * 2.2 If clause 2.1.2 above is satisfied, then there
14876 * must be a <simpleType> among the [children] of
14877 * <restriction>.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014878 */
14879 /* TODO: Change error code to ..._SRC_CT_2_2. */
14880 xmlSchemaPCustomErr(ctxt,
14881 XML_SCHEMAP_SRC_CT_1,
14882 NULL, type, NULL,
14883 "A <simpleType> is expected among the children "
14884 "of <restriction>, if <simpleContent> is used and "
14885 "the base type '%s' is a complex type",
14886 xmlSchemaFormatQName(&str, base->targetNamespace,
14887 base->name));
14888 FREE_AND_NULL(str)
14889 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014890 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014891 } else {
14892 ret = XML_SCHEMAP_SRC_CT_1;
14893 }
14894 }
14895 if (ret > 0) {
14896 xmlChar *str = NULL;
14897 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
14898 xmlSchemaPCustomErr(ctxt,
14899 XML_SCHEMAP_SRC_CT_1,
14900 NULL, type, NULL,
14901 "If <simpleContent> and <restriction> is used, the "
14902 "base type must be a simple type or a complex type with "
14903 "mixed content and particle emptiable. The base type "
14904 "'%s' is none of those",
14905 xmlSchemaFormatQName(&str, base->targetNamespace,
14906 base->name));
14907 } else {
14908 xmlSchemaPCustomErr(ctxt,
14909 XML_SCHEMAP_SRC_CT_1,
14910 NULL, type, NULL,
14911 "If <simpleContent> and <extension> is used, the "
14912 "base type must be a simple type. The base type '%s' "
14913 "is a complex type",
14914 xmlSchemaFormatQName(&str, base->targetNamespace,
14915 base->name));
14916 }
14917 FREE_AND_NULL(str)
14918 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014919 }
14920 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014921 * SPEC (3) "The corresponding complex type definition component must
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014922 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014923 * Definition Schema Components (§3.4.6);"
14924 * NOTE (3) will be done in xmlSchemaTypeFixup().
14925 */
14926 /*
14927 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014928 * above for {attribute wildcard} is satisfied, the intensional
14929 * intersection must be expressible, as defined in Attribute Wildcard
14930 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014931 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014932 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014933 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014934}
William M. Brack2f2a6632004-08-20 23:09:47 +000014935
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014936#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
14937 xmlSchemaPCustomErrExt(pctxt, \
14938 XML_SCHEMAP_INVALID_FACET_VALUE, \
14939 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14940 "It is an error for both '%s' and '%s' to be specified on the "\
14941 "same type definition", \
14942 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
14943 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
14944
14945#define FACET_RESTR_ERR(fac1, msg) \
14946 xmlSchemaPCustomErr(pctxt, \
14947 XML_SCHEMAP_INVALID_FACET_VALUE, \
14948 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14949 msg, NULL);
14950
14951#define FACET_RESTR_FIXED_ERR(fac) \
14952 xmlSchemaPCustomErr(pctxt, \
14953 XML_SCHEMAP_INVALID_FACET_VALUE, \
14954 NULL, (xmlSchemaTypePtr) fac, fac->node, \
14955 "The base type's facet is 'fixed', thus the value must not " \
14956 "differ", NULL);
14957
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014958static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014959xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
14960 xmlSchemaFacetPtr facet1,
14961 xmlSchemaFacetPtr facet2,
14962 int lessGreater,
14963 int orEqual,
14964 int ofBase)
14965{
14966 xmlChar *msg = NULL;
14967
14968 msg = xmlStrdup(BAD_CAST "'");
14969 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
14970 msg = xmlStrcat(msg, BAD_CAST "' has to be");
14971 if (lessGreater == 0)
14972 msg = xmlStrcat(msg, BAD_CAST " equal to");
14973 if (lessGreater == 1)
14974 msg = xmlStrcat(msg, BAD_CAST " greater than");
14975 else
14976 msg = xmlStrcat(msg, BAD_CAST " less than");
14977
14978 if (orEqual)
14979 msg = xmlStrcat(msg, BAD_CAST " or equal to");
14980 msg = xmlStrcat(msg, BAD_CAST " '");
14981 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
14982 if (ofBase)
14983 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
14984 else
14985 msg = xmlStrcat(msg, BAD_CAST "'");
14986
14987 xmlSchemaPCustomErr(pctxt,
14988 XML_SCHEMAP_INVALID_FACET_VALUE,
14989 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
14990 (const char *) msg, NULL);
14991
14992 if (msg != NULL)
14993 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014994}
14995
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014996static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014997xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
14998 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014999{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015000 xmlSchemaTypePtr base = type->baseType;
15001 xmlSchemaFacetLinkPtr link, cur, last = NULL;
15002 xmlSchemaFacetPtr facet, bfacet,
15003 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15004 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15005 fmininc = NULL, fmaxinc = NULL,
15006 fminexc = NULL, fmaxexc = NULL,
15007 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15008 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15009 bfmininc = NULL, bfmaxinc = NULL,
15010 bfminexc = NULL, bfmaxexc = NULL;
15011 int res, err = 0, fixedErr;
15012 /*
15013 * 3 The {facets} of R are the union of S and the {facets}
15014 * of B, eliminating duplicates. To eliminate duplicates,
15015 * when a facet of the same kind occurs in both S and the
15016 * {facets} of B, the one in the {facets} of B is not
15017 * included, with the exception of enumeration and pattern
15018 * facets, for which multiple occurrences with distinct values
15019 * are allowed.
15020 */
15021 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15022 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015023
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015024 last = type->facetSet;
15025 if (last != NULL)
15026 while (last->next != NULL)
15027 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015028
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015029 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15030 facet = cur->facet;
15031 switch (facet->type) {
15032 case XML_SCHEMA_FACET_LENGTH:
15033 flength = facet; break;
15034 case XML_SCHEMA_FACET_MINLENGTH:
15035 fminlen = facet; break;
15036 case XML_SCHEMA_FACET_MININCLUSIVE:
15037 fmininc = facet; break;
15038 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15039 fminexc = facet; break;
15040 case XML_SCHEMA_FACET_MAXLENGTH:
15041 fmaxlen = facet; break;
15042 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15043 fmaxinc = facet; break;
15044 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15045 fmaxexc = facet; break;
15046 case XML_SCHEMA_FACET_TOTALDIGITS:
15047 ftotdig = facet; break;
15048 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15049 ffracdig = facet; break;
15050 default:
15051 break;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015052 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015053 }
15054 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15055 facet = cur->facet;
15056 switch (facet->type) {
15057 case XML_SCHEMA_FACET_LENGTH:
15058 bflength = facet; break;
15059 case XML_SCHEMA_FACET_MINLENGTH:
15060 bfminlen = facet; break;
15061 case XML_SCHEMA_FACET_MININCLUSIVE:
15062 bfmininc = facet; break;
15063 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15064 bfminexc = facet; break;
15065 case XML_SCHEMA_FACET_MAXLENGTH:
15066 bfmaxlen = facet; break;
15067 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15068 bfmaxinc = facet; break;
15069 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15070 bfmaxexc = facet; break;
15071 case XML_SCHEMA_FACET_TOTALDIGITS:
15072 bftotdig = facet; break;
15073 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15074 bffracdig = facet; break;
15075 default:
15076 break;
15077 }
15078 }
15079 err = 0;
15080 /*
15081 * length and minLength or maxLength (2.2) + (3.2)
15082 */
15083 if (flength && (fminlen || fmaxlen)) {
15084 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15085 "either of 'minLength' or 'maxLength' to be specified on "
15086 "the same type definition")
15087 }
15088 /*
15089 * Mutual exclusions in the same derivation step.
15090 */
15091 if ((fmaxinc) && (fmaxexc)) {
15092 /*
15093 * SCC "maxInclusive and maxExclusive"
15094 */
15095 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15096 }
15097 if ((fmininc) && (fminexc)) {
15098 /*
15099 * SCC "minInclusive and minExclusive"
15100 */
15101 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015102 }
15103
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015104 if (flength && bflength) {
15105 /*
15106 * SCC "length valid restriction"
15107 * The values have to be equal.
15108 */
15109 res = xmlSchemaCompareValues(flength->val, bflength->val);
15110 if (res == -2)
15111 goto internal_error;
15112 /*
15113 * TODO: Maby a bug in the spec.
15114 */
15115 if (res != 0)
15116 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15117 if ((res != 0) && (bflength->fixed)) {
15118 FACET_RESTR_FIXED_ERR(flength)
15119 }
15120
15121 }
15122 if (fminlen && bfminlen) {
15123 /*
15124 * SCC "minLength valid restriction"
15125 * minLength >= BASE minLength
15126 */
15127 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15128 if (res == -2)
15129 goto internal_error;
15130 if (res == -1)
15131 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15132 if ((res != 0) && (bfminlen->fixed)) {
15133 FACET_RESTR_FIXED_ERR(fminlen)
15134 }
15135 }
15136 if (fmaxlen && bfmaxlen) {
15137 /*
15138 * SCC "maxLength valid restriction"
15139 * maxLength <= BASE minLength
15140 */
15141 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15142 if (res == -2)
15143 goto internal_error;
15144 if (res == 1)
15145 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15146 if ((res != 0) && (bfmaxlen->fixed)) {
15147 FACET_RESTR_FIXED_ERR(fmaxlen)
15148 }
15149 }
15150 /*
15151 * SCC "length and minLength or maxLength"
15152 */
15153 if (! flength)
15154 flength = bflength;
15155 if (flength) {
15156 if (! fminlen)
15157 flength = bflength;
15158 if (fminlen) {
15159 /* (1.1) length >= minLength */
15160 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15161 if (res == -2)
15162 goto internal_error;
15163 if (res == -1)
15164 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15165 }
15166 if (! fmaxlen)
15167 fmaxlen = bfmaxlen;
15168 if (fmaxlen) {
15169 /* (2.1) length <= maxLength */
15170 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15171 if (res == -2)
15172 goto internal_error;
15173 if (res == 1)
15174 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15175 }
15176 }
15177 if (fmaxinc) {
15178 /*
15179 * "maxInclusive"
15180 */
15181 if (fmininc) {
15182 /* SCC "maxInclusive >= minInclusive" */
15183 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15184 if (res == -2)
15185 goto internal_error;
15186 if (res == -1) {
15187 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15188 }
15189 }
15190 /*
15191 * SCC "maxInclusive valid restriction"
15192 */
15193 if (bfmaxinc) {
15194 /* maxInclusive <= BASE maxInclusive */
15195 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15196 if (res == -2)
15197 goto internal_error;
15198 if (res == 1)
15199 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15200 if ((res != 0) && (bfmaxinc->fixed)) {
15201 FACET_RESTR_FIXED_ERR(fmaxinc)
15202 }
15203 }
15204 if (bfmaxexc) {
15205 /* maxInclusive < BASE maxExclusive */
15206 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15207 if (res == -2)
15208 goto internal_error;
15209 if (res != -1) {
15210 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15211 }
15212 }
15213 if (bfmininc) {
15214 /* maxInclusive >= BASE minInclusive */
15215 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15216 if (res == -2)
15217 goto internal_error;
15218 if (res == -1) {
15219 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15220 }
15221 }
15222 if (bfminexc) {
15223 /* maxInclusive > BASE minExclusive */
15224 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15225 if (res == -2)
15226 goto internal_error;
15227 if (res != 1) {
15228 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15229 }
15230 }
15231 }
15232 if (fmaxexc) {
15233 /*
15234 * "maxExclusive >= minExclusive"
15235 */
15236 if (fminexc) {
15237 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15238 if (res == -2)
15239 goto internal_error;
15240 if (res == -1) {
15241 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15242 }
15243 }
15244 /*
15245 * "maxExclusive valid restriction"
15246 */
15247 if (bfmaxexc) {
15248 /* maxExclusive <= BASE maxExclusive */
15249 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15250 if (res == -2)
15251 goto internal_error;
15252 if (res == 1) {
15253 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15254 }
15255 if ((res != 0) && (bfmaxexc->fixed)) {
15256 FACET_RESTR_FIXED_ERR(fmaxexc)
15257 }
15258 }
15259 if (bfmaxinc) {
15260 /* maxExclusive <= BASE maxInclusive */
15261 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15262 if (res == -2)
15263 goto internal_error;
15264 if (res == 1) {
15265 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15266 }
15267 }
15268 if (bfmininc) {
15269 /* maxExclusive > BASE minInclusive */
15270 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15271 if (res == -2)
15272 goto internal_error;
15273 if (res != 1) {
15274 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15275 }
15276 }
15277 if (bfminexc) {
15278 /* maxExclusive > BASE minExclusive */
15279 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15280 if (res == -2)
15281 goto internal_error;
15282 if (res != 1) {
15283 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15284 }
15285 }
15286 }
15287 if (fminexc) {
15288 /*
15289 * "minExclusive < maxInclusive"
15290 */
15291 if (fmaxinc) {
15292 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15293 if (res == -2)
15294 goto internal_error;
15295 if (res != -1) {
15296 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15297 }
15298 }
15299 /*
15300 * "minExclusive valid restriction"
15301 */
15302 if (bfminexc) {
15303 /* minExclusive >= BASE minExclusive */
15304 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15305 if (res == -2)
15306 goto internal_error;
15307 if (res == -1) {
15308 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15309 }
15310 if ((res != 0) && (bfminexc->fixed)) {
15311 FACET_RESTR_FIXED_ERR(fminexc)
15312 }
15313 }
15314 if (bfmaxinc) {
15315 /* minExclusive <= BASE maxInclusive */
15316 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15317 if (res == -2)
15318 goto internal_error;
15319 if (res == 1) {
15320 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15321 }
15322 }
15323 if (bfmininc) {
15324 /* minExclusive >= BASE minInclusive */
15325 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15326 if (res == -2)
15327 goto internal_error;
15328 if (res == -1) {
15329 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15330 }
15331 }
15332 if (bfmaxexc) {
15333 /* minExclusive < BASE maxExclusive */
15334 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15335 if (res == -2)
15336 goto internal_error;
15337 if (res != -1) {
15338 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15339 }
15340 }
15341 }
15342 if (fmininc) {
15343 /*
15344 * "minInclusive < maxExclusive"
15345 */
15346 if (fmaxexc) {
15347 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15348 if (res == -2)
15349 goto internal_error;
15350 if (res != -1) {
15351 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15352 }
15353 }
15354 /*
15355 * "minExclusive valid restriction"
15356 */
15357 if (bfmininc) {
15358 /* minInclusive >= BASE minInclusive */
15359 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15360 if (res == -2)
15361 goto internal_error;
15362 if (res == -1) {
15363 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15364 }
15365 if ((res != 0) && (bfmininc->fixed)) {
15366 FACET_RESTR_FIXED_ERR(fmininc)
15367 }
15368 }
15369 if (bfmaxinc) {
15370 /* minInclusive <= BASE maxInclusive */
15371 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15372 if (res == -2)
15373 goto internal_error;
15374 if (res == -1) {
15375 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15376 }
15377 }
15378 if (bfminexc) {
15379 /* minInclusive > BASE minExclusive */
15380 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15381 if (res == -2)
15382 goto internal_error;
15383 if (res != 1)
15384 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15385 }
15386 if (bfmaxexc) {
15387 /* minInclusive < BASE maxExclusive */
15388 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15389 if (res == -2)
15390 goto internal_error;
15391 if (res != -1)
15392 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15393 }
15394 }
15395 if (ftotdig && bftotdig) {
15396 /*
15397 * SCC " totalDigits valid restriction"
15398 * totalDigits <= BASE totalDigits
15399 */
15400 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15401 if (res == -2)
15402 goto internal_error;
15403 if (res == 1)
15404 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15405 -1, 1, 1);
15406 if ((res != 0) && (bftotdig->fixed)) {
15407 FACET_RESTR_FIXED_ERR(ftotdig)
15408 }
15409 }
15410 if (ffracdig && bffracdig) {
15411 /*
15412 * SCC "fractionDigits valid restriction"
15413 * fractionDigits <= BASE fractionDigits
15414 */
15415 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15416 if (res == -2)
15417 goto internal_error;
15418 if (res == 1)
15419 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15420 -1, 1, 1);
15421 if ((res != 0) && (bffracdig->fixed)) {
15422 FACET_RESTR_FIXED_ERR(ffracdig)
15423 }
15424 }
15425 /*
15426 * SCC "fractionDigits less than or equal to totalDigits"
15427 */
15428 if (! ftotdig)
15429 ftotdig = bftotdig;
15430 if (! ffracdig)
15431 ffracdig = bffracdig;
15432 if (ftotdig && ffracdig) {
15433 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15434 if (res == -2)
15435 goto internal_error;
15436 if (res == 1)
15437 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15438 -1, 1, 0);
15439 }
15440 /*
15441 * *Enumerations* won' be added here, since only the first set
15442 * of enumerations in the ancestor-or-self axis is used
15443 * for validation, plus we need to use the base type of those
15444 * enumerations for whitespace.
15445 *
15446 * *Patterns*: won't be add here, since they are ORed at
15447 * type level and ANDed at ancestor level. This will
15448 * happed during validation by walking the base axis
15449 * of the type.
15450 */
15451 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15452 bfacet = cur->facet;
15453 /*
15454 * Special handling of enumerations and patterns.
15455 * TODO: hmm, they should not appear in the set, so remove this.
15456 */
15457 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
15458 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
15459 continue;
15460 /*
15461 * Search for a duplicate facet in the current type.
15462 */
15463 link = type->facetSet;
15464 err = 0;
15465 fixedErr = 0;
15466 while (link != NULL) {
15467 facet = link->facet;
15468 if (facet->type == bfacet->type) {
15469 switch (facet->type) {
15470 case XML_SCHEMA_FACET_WHITESPACE:
15471 /*
15472 * The whitespace must be stronger.
15473 */
15474 if (facet->whitespace < bfacet->whitespace) {
15475 FACET_RESTR_ERR(flength,
15476 "The 'whitespace' value has to be equal to "
15477 "or stronger than the 'whitespace' value of "
15478 "the base type")
15479 }
15480 if ((bfacet->fixed) &&
15481 (facet->whitespace != bfacet->whitespace)) {
15482 FACET_RESTR_FIXED_ERR(facet)
15483 }
15484 break;
15485 default:
15486 break;
15487 }
15488 /* Duplicate found. */
15489 break;
15490 }
15491 link = link->next;
15492 }
15493 /*
15494 * If no duplicate was found: add the base types's facet
15495 * to the set.
15496 */
15497 if (link == NULL) {
15498 link = (xmlSchemaFacetLinkPtr)
15499 xmlMalloc(sizeof(xmlSchemaFacetLink));
15500 if (link == NULL) {
15501 xmlSchemaPErrMemory(pctxt,
15502 "deriving facets, creating a facet link", NULL);
15503 return (-1);
15504 }
15505 link->facet = cur->facet;
15506 link->next = NULL;
15507 if (last == NULL)
15508 type->facetSet = link;
15509 else
15510 last->next = link;
15511 last = link;
15512 }
15513
15514 }
15515
15516 return (0);
15517internal_error:
15518 xmlSchemaPCustomErr(pctxt,
15519 XML_SCHEMAP_INVALID_FACET_VALUE,
15520 NULL, type, NULL,
15521 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15522 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015523}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015524
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015525static int
15526xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15527 xmlSchemaTypePtr type)
15528{
15529 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15530 /*
15531 * The actual value is then formed by replacing any union type
15532 * definition in the ·explicit members· with the members of their
15533 * {member type definitions}, in order.
15534 */
15535 link = type->memberTypes;
15536 while (link != NULL) {
15537
15538 if (IS_NOT_TYPEFIXED(link->type))
15539 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15540
15541 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15542 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
15543 if (subLink != NULL) {
15544 link->type = subLink->type;
15545 if (subLink->next != NULL) {
15546 lastLink = link->next;
15547 subLink = subLink->next;
15548 prevLink = link;
15549 while (subLink != NULL) {
15550 newLink = (xmlSchemaTypeLinkPtr)
15551 xmlMalloc(sizeof(xmlSchemaTypeLink));
15552 if (newLink == NULL) {
15553 xmlSchemaPErrMemory(pctxt, "allocating a type link",
15554 NULL);
15555 return (-1);
15556 }
15557 newLink->type = subLink->type;
15558 prevLink->next = newLink;
15559 prevLink = newLink;
15560 newLink->next = lastLink;
15561
15562 subLink = subLink->next;
15563 }
15564 }
15565 }
15566 }
15567 link = link->next;
15568 }
15569 return (0);
15570}
15571
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015572/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015573 * xmlSchemaTypeFixup:
15574 * @typeDecl: the schema type definition
15575 * @ctxt: the schema parser context
15576 *
15577 * Fixes the content model of the type.
15578 */
15579static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015580xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015581 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015582{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015583 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015584 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015585 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15586 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015587 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015588 if (! IS_NOT_TYPEFIXED(type))
15589 return;
15590 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015591 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015592 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015593
15594 if (type->baseType == NULL) {
15595 xmlSchemaPCustomErr(ctxt,
15596 XML_SCHEMAP_INTERNAL,
15597 NULL, type, NULL,
15598 "Internal error: xmlSchemaTypeFixup, "
15599 "baseType is missing on '%s'", type->name);
15600 return;
15601 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015602
15603 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015604 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015605
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015606 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015607 * Type-fix the base type.
15608 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015609 if (IS_NOT_TYPEFIXED(baseType))
15610 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15611 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15612 /*
15613 * Skip fixup if the base type is invalid.
15614 * TODO: Generate a warning!
15615 */
15616 return;
15617 }
15618 /*
15619 * This basically checks if the base type can be derived.
15620 */
15621 if (xmlSchemaCheckSRCCT(ctxt, type) != 0) {
15622 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15623 return;
15624 }
15625 /*
15626 * Fixup the content type.
15627 */
15628 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15629 /*
15630 * Corresponds to <complexType><simpleContent>...
15631 */
15632 if ((IS_COMPLEX_TYPE(baseType)) &&
15633 (baseType->contentTypeDef != NULL) &&
15634 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15635 /*
15636 * SPEC (1) If <restriction> + base type is <complexType>,
15637 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015638 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015639 * NOTE (1.1) is handled during parsing of <restriction>.
15640 *
15641 * (1.2) "...otherwise (<restriction> has no <simpleType> among
15642 * its [children]), the simple type definition which is the
15643 * {content type} of the ... base type."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015644 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015645 if (type->contentTypeDef->baseType == NULL) {
15646 /*
15647 * <simpleContent><restriction> has *no* <simpleType>
15648 * child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015649 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015650 type->contentTypeDef->baseType =
15651 baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015652 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015653 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15654 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15655 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15656 /*
15657 * SPEC (2) If <restriction> + base is a mixed <complexType> with
15658 * an emptiable particle, then a simple type definition which
15659 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015660 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015661 if ((type->contentTypeDef == NULL) ||
15662 (type->contentTypeDef->baseType == NULL)) {
15663 /*
15664 * TODO: Check if this ever happens.
15665 */
15666 xmlSchemaPCustomErr(ctxt,
15667 XML_SCHEMAP_INTERNAL,
15668 NULL, type, NULL,
15669 "Internal error: xmlSchemaTypeFixup, "
15670 "complex type '%s': the <simpleContent><restriction> "
15671 "is missing a <simpleType> child, but was not catched "
15672 "by xmlSchemaCheckSRCCT()", type->name);
15673 }
15674 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15675 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15676 /*
15677 * SPEC (3) If <extension> + base is <complexType> with
15678 * <simpleType> content, "...then the {content type} of that
15679 * complex type definition"
15680 */
15681 if (baseType->contentTypeDef == NULL) {
15682 /*
15683 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
15684 * should have catched this already.
15685 */
15686 xmlSchemaPCustomErr(ctxt,
15687 XML_SCHEMAP_INTERNAL,
15688 NULL, type, NULL,
15689 "Internal error: xmlSchemaTypeFixup, "
15690 "complex type '%s': the <extension>ed base type is "
15691 "a complex type with no simple content type",
15692 type->name);
15693 }
15694 type->contentTypeDef = baseType->contentTypeDef;
15695 } else if ((IS_SIMPLE_TYPE(baseType)) &&
15696 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15697 /*
15698 * SPEC (4) <extension> + base is <simpleType>
15699 * "... then that simple type definition"
15700 */
15701 type->contentTypeDef = baseType;
15702 } else {
15703 /*
15704 * TODO: Check if this ever happens.
15705 */
15706 xmlSchemaPCustomErr(ctxt,
15707 XML_SCHEMAP_INTERNAL,
15708 NULL, type, NULL,
15709 "Internal error: xmlSchemaTypeFixup, "
15710 "complex type '%s' with <simpleContent>: unhandled "
15711 "derivation case", type->name);
15712 }
15713 } else {
15714 int dummySequence = 0;
15715 xmlSchemaParticlePtr particle =
15716 (xmlSchemaParticlePtr) type->subtypes;
15717 /*
15718 * Corresponds to <complexType><complexContent>...
15719 *
15720 * NOTE that the effective mixed was already set during parsing of
15721 * <complexType> and <complexContent>; its flag value is
15722 * XML_SCHEMAS_TYPE_MIXED.
15723 *
15724 * Compute the "effective content":
15725 * (2.1.1) + (2.1.2) + (2.1.3)
15726 */
15727 if ((particle == NULL) ||
15728 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
15729 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
15730 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
15731 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
15732 (particle->minOccurs == 0))) &&
15733 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
15734 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
15735 /*
15736 * SPEC (2.1.4) "If the ·effective mixed· is true, then
15737 * a particle whose properties are as follows:..."
15738 *
15739 * Empty sequence model group with
15740 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
15741 * NOTE that we sill assign it the <complexType> node to
15742 * somehow anchor it in the doc.
15743 */
15744 if ((particle == NULL) ||
15745 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015746 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015747 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015748 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015749 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15750 type->node, 1, 1);
15751 if (particle == NULL)
15752 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015753 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015754 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015755 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015756 particle->children = (xmlSchemaTreeItemPtr)
15757 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15758 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15759 if (particle->children == NULL)
15760 return;
15761
15762 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015763 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015764 dummySequence = 1;
15765 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15766 } else {
15767 /*
15768 * SPEC (2.1.5) "otherwise empty"
15769 */
15770 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
15771 }
15772 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015773 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015774 * SPEC (2.2) "otherwise the particle corresponding to the
15775 * <all>, <choice>, <group> or <sequence> among the
15776 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015777 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015778 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15779 }
15780 /*
15781 * Compute the "content type".
15782 */
15783 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015784 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015785 * SPEC (3.1) "If <restriction>..."
15786 * (3.1.1) + (3.1.2) */
15787 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
15788 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15789 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15790 }
15791 } else {
15792 /*
15793 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015794 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015795 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15796 /*
15797 * SPEC (3.2.1)
15798 */
15799 type->contentType = baseType->contentType;
15800 type->subtypes = baseType->subtypes;
15801 /*
15802 * NOTE that the effective mixed is ignored here.
15803 */
15804 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15805 /*
15806 * SPEC (3.2.2)
15807 */
15808 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15809 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15810 } else {
15811 /*
15812 * SPEC (3.2.3)
15813 */
15814 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15815 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15816 /*
15817 * "A model group whose {compositor} is sequence and whose
15818 * {particles} are..."
15819 */
15820 if (! dummySequence) {
15821 xmlSchemaTreeItemPtr effectiveContent =
15822 (xmlSchemaTreeItemPtr) type->subtypes;
15823 /*
15824 * Create the particle.
15825 */
15826 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15827 type->node, 1, 1);
15828 if (particle == NULL)
15829 return;
15830 /*
15831 * Create the "sequence" model group.
15832 */
15833 particle->children = (xmlSchemaTreeItemPtr)
15834 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15835 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15836 if (particle->children == NULL)
15837 return;
15838 type->subtypes = (xmlSchemaTypePtr) particle;
15839 /*
15840 * SPEC "the particle of the {content type} of
15841 * the ... base ..."
15842 * Create a duplicate of the base type's particle
15843 * and assign its "term" to it.
15844 */
15845 particle->children->children =
15846 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(ctxt,
15847 ctxt->schema, type->node,
15848 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
15849 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
15850 if (particle->children->children == NULL)
15851 return;
15852 particle = (xmlSchemaParticlePtr)
15853 particle->children->children;
15854 particle->children =
15855 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
15856 /*
15857 * SPEC "followed by the ·effective content·."
15858 */
15859 particle->next = effectiveContent;
15860 } else {
15861 /*
15862 * This is the case when there is already an empty
15863 * <sequence> with minOccurs==maxOccurs==1.
15864 * Just add the base types's content type.
15865 * NOTE that, although we miss to add an intermediate
15866 * <sequence>, this should produce no difference to
15867 * neither the regex compilation of the content model,
15868 * nor to the complex type contraints.
15869 */
15870 particle->children->children =
15871 (xmlSchemaTreeItemPtr) baseType->subtypes;
15872 }
15873 }
15874 }
15875 }
15876 /*
15877 * Apply the complex type component constraints; this will not
15878 * check attributes, since this is done in
15879 * xmlSchemaBuildAttributeValidation().
15880 */
15881 if (xmlSchemaCheckCTComponent(ctxt, type) != 0)
15882 return;
15883 /*
15884 * Inherit & check constraints for attributes.
15885 */
15886 xmlSchemaBuildAttributeValidation(ctxt, type);
15887 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
15888 /*
15889 * Simple Type Definition Schema Component
15890 */
15891 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
15892 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15893 /*
15894 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015895 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015896 if (type->subtypes == NULL) {
15897 /*
15898 * This one is really needed, so get out.
15899 */
15900 return;
15901 }
15902 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015903 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015904 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15905 /*
15906 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015907 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015908 if (type->memberTypes == NULL) {
15909 /*
15910 * This one is really needed, so get out.
15911 */
15912 return;
15913 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015914 if (xmlSchemaFinishMemberTypeDefinitionsProperty(ctxt, type) == -1)
15915 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015916 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015917 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015918 /*
15919 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015920 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015921 if (IS_NOT_TYPEFIXED(baseType))
15922 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15923 /*
15924 * Variety
15925 * If the <restriction> alternative is chosen, then the
15926 * {variety} of the {base type definition}.
15927 */
15928 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
15929 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
15930 else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15931 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
15932 /*
15933 * Inherit the itemType.
15934 */
15935 type->subtypes = baseType->subtypes;
15936 } else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15937 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
15938 /*
15939 * NOTE that we won't assign the memberTypes of the base,
15940 * since this will make trouble when freeing them; we will
15941 * use a lookup function to access them instead.
15942 */
15943 }
15944
15945 /*
15946 * Some optimization for validation:
15947 * If there are no facets beside the "whitespace" facet,
15948 * then a value needs not to checked against against a
15949 * facet, thus no computed value is needed.
15950 */
15951#if 0
15952 if (baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
15953 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15954 else {
15955 for (cur = type->facetSet; cur != NULL;
15956 cur = cur->next) {
15957 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15958 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15959 break;
15960 }
15961 }
15962 }
15963#endif
15964 }
15965 /*
15966 * Check constraints.
15967 *
15968 * TODO: Split this somehow, we need to know first if we can derive
15969 * from the base type at all!
15970 */
15971 if (type->baseType != NULL) {
15972 /*
15973 * Schema Component Constraint: Simple Type Restriction
15974 * (Facets)
15975 * NOTE: Satisfaction of 1 and 2 arise from the fixup
15976 * applied beforehand.
15977 */
15978 xmlSchemaCheckSRCSimpleType(ctxt, type);
15979 xmlSchemaCheckFacetValues(type, ctxt);
15980 xmlSchemaDeriveAndValidateFacets(ctxt, type);
15981 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015982 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015983
Daniel Veillard8651f532002-04-17 09:06:27 +000015984#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015985 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015986 xmlGenericError(xmlGenericErrorContext,
15987 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015988 type->node->doc->URL,
15989 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015990 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015991 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015992 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
15994 switch (type->contentType) {
15995 case XML_SCHEMA_CONTENT_SIMPLE:
15996 xmlGenericError(xmlGenericErrorContext, "simple\n");
15997 break;
15998 case XML_SCHEMA_CONTENT_ELEMENTS:
15999 xmlGenericError(xmlGenericErrorContext, "elements\n");
16000 break;
16001 case XML_SCHEMA_CONTENT_UNKNOWN:
16002 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16003 break;
16004 case XML_SCHEMA_CONTENT_EMPTY:
16005 xmlGenericError(xmlGenericErrorContext, "empty\n");
16006 break;
16007 case XML_SCHEMA_CONTENT_MIXED:
16008 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
16009 type->subtypes))
16010 xmlGenericError(xmlGenericErrorContext,
16011 "mixed as emptiable particle\n");
16012 else
16013 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16014 break;
16015 /* Removed, since not used. */
16016 /*
16017 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16018 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16019 break;
16020 */
16021 case XML_SCHEMA_CONTENT_BASIC:
16022 xmlGenericError(xmlGenericErrorContext, "basic\n");
16023 break;
16024 default:
16025 xmlGenericError(xmlGenericErrorContext,
16026 "not registered !!!\n");
16027 break;
16028 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016029 }
16030#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016031}
16032
16033/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016034 * xmlSchemaCheckFacet:
16035 * @facet: the facet
16036 * @typeDecl: the schema type definition
16037 * @ctxt: the schema parser context or NULL
16038 * @name: name of the type
16039 *
16040 * Checks the default values types, especially for facets
16041 *
16042 * Returns 0 if okay or -1 in cae of error
16043 */
16044int
16045xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016046 xmlSchemaTypePtr typeDecl,
16047 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016048{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016049 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016050 int ret = 0, reuseValCtxt = 0;
16051
Daniel Veillardce682bc2004-11-05 17:22:25 +000016052 if ((facet == NULL) || (typeDecl == NULL))
16053 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016054 /*
16055 * TODO: will the parser context be given if used from
16056 * the relaxNG module?
16057 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016058
16059 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016060 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000016061 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016062 }
16063 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016064 case XML_SCHEMA_FACET_MININCLUSIVE:
16065 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16066 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016067 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16068 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016069 /*
16070 * Okay we need to validate the value
16071 * at that point.
16072 */
16073 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016074 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016075
16076 /* 4.3.5.5 Constraints on enumeration Schema Components
16077 * Schema Component Constraint: enumeration valid restriction
16078 * It is an ·error· if any member of {value} is not in the
16079 * ·value space· of {base type definition}.
16080 *
16081 * minInclusive, maxInclusive, minExclusive, maxExclusive:
16082 * The value ·must· be in the
16083 * ·value space· of the ·base type·.
16084 */
16085 /*
16086 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016087 * on the facet. In this implementation of XML Schemata the
16088 * type holding a facet, won't be a built-in type.
16089 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016090 * calls (relaxng) do work, if the given type is a built-in
16091 * type, we will assume that the given built-in type *is
16092 * already* the base type.
16093 */
16094 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16095 base = typeDecl->baseType;
16096 if (base == NULL) {
16097 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016098 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016099 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016100 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016101 typeDecl->name, NULL);
16102 return (-1);
16103 }
16104 } else
16105 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016106 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016107 * This avoids perseverative creation of the
16108 * validation context if a parser context is
16109 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016110 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016111 if (ctxt != NULL) {
16112 reuseValCtxt = 1;
16113 if (ctxt->vctxt == NULL) {
16114 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16115 return (-1);
16116 }
16117 vctxt = ctxt->vctxt;
16118 } else {
16119 vctxt = xmlSchemaNewValidCtxt(NULL);
16120 if (vctxt == NULL) {
16121 xmlSchemaPErr(ctxt, typeDecl->node,
16122 XML_SCHEMAP_INTERNAL,
16123 "Internal error: xmlSchemaCheckFacet, "
16124 "creating a new validation context.\n",
16125 NULL, NULL);
16126 return (-1);
16127 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016128 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016129
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016130 vctxt->node = facet->node;
16131 vctxt->cur = NULL;
16132 /*
16133 * NOTE: This call does not check the content nodes,
16134 * since they are not available:
16135 * facet->node is just the node holding the facet
16136 * definition, *not* the attribute holding the *value*
16137 * of the facet.
16138 */
16139 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016140 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016141 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016142 /* error code */
16143 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016144 xmlChar *str = NULL;
16145
16146 xmlSchemaPCustomErrExt(ctxt,
16147 XML_SCHEMAP_INVALID_FACET_VALUE,
16148 NULL, (xmlSchemaTypePtr) facet, facet->node,
16149 "The value '%s' of the facet does not validate "
16150 "against the base type '%s'",
16151 facet->value,
16152 xmlSchemaFormatQName(&str,
16153 base->targetNamespace, base->name), NULL);
16154 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016155 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016156 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016157 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016158 } else if (ret < 0) {
16159 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016160 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016161 NULL, NULL, NULL,
16162 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016163 "failed to validate the value '%s' name of the "
16164 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016165 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016166 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016167 base->name, NULL, NULL);
16168 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016169 } else {
16170 if (vctxt->value != NULL) {
16171 facet->val = vctxt->value;
16172 vctxt->value = NULL;
16173 } else {
16174 xmlChar *str;
16175 /*
16176 * Ensure computed values even for type string.
16177 * TODO OPTIMIZE MEMORY: The value will be hold twice,
16178 * by the facet->value and by the computed value.
16179 */
16180 str = xmlStrdup(facet->value);
16181 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
16182 BAD_CAST str, &(facet->val)) == -1) {
16183 FREE_AND_NULL(str)
16184 xmlSchemaPErr(ctxt, typeDecl->node,
16185 XML_SCHEMAP_INTERNAL,
16186 "Internal error: xmlSchemaCheckFacet, "
16187 "post-creating a computed value.\n",
16188 NULL, NULL);
16189 /* Note that we don't return a failure yet.*/
16190 }
16191 }
16192 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016193 if (reuseValCtxt == 0)
16194 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016195 break;
16196 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016197 case XML_SCHEMA_FACET_PATTERN:
16198 facet->regexp = xmlRegexpCompile(facet->value);
16199 if (facet->regexp == NULL) {
16200 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016201 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016202 "Type definition '%s': The value '%s' of the "
16203 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016204 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016205 ret = -1;
16206 }
16207 break;
16208 case XML_SCHEMA_FACET_TOTALDIGITS:
16209 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16210 case XML_SCHEMA_FACET_LENGTH:
16211 case XML_SCHEMA_FACET_MAXLENGTH:
16212 case XML_SCHEMA_FACET_MINLENGTH:{
16213 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016214
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016215 tmp =
16216 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
16217 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016218 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016219 if (tmp != 0) {
16220 /* error code */
16221 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016222 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016223 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016224 NULL, (xmlSchemaTypePtr) facet, facet->node,
16225 "The value '%s' of the facet is not a valid "
16226 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016227 }
16228 ret = -1;
16229 }
16230 break;
16231 }
16232 case XML_SCHEMA_FACET_WHITESPACE:{
16233 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16234 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16235 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16236 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16237 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16238 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16239 } else {
16240 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016241 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
16242 xmlSchemaPCustomErr(ctxt,
16243 XML_SCHEMAP_INVALID_FACET_VALUE,
16244 NULL, (xmlSchemaTypePtr) facet, facet->node,
16245 "The value '%s' of the facet is not a valid",
16246 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016247 }
16248 ret = -1;
16249 }
16250 }
16251 default:
16252 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016253 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016254 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016255}
16256
16257/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016258 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016259 * @typeDecl: the schema type definition
16260 * @ctxt: the schema parser context
16261 *
16262 * Checks the default values types, especially for facets
16263 */
16264static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016265xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16266 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016267{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016268 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016269 /*
16270 * NOTE: It is intended to use the facets list, instead
16271 * of facetSet.
16272 */
16273 if (typeDecl->facets != NULL) {
16274 xmlSchemaFacetPtr facet = typeDecl->facets;
16275
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016276 /*
16277 * Temporarily assign the "schema" to the validation context
16278 * of the parser context. This is needed for NOTATION validation.
16279 */
16280 if (ctxt->vctxt == NULL) {
16281 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16282 return;
16283 }
16284 ctxt->vctxt->schema = ctxt->schema;
16285
Daniel Veillard01fa6152004-06-29 17:04:39 +000016286 while (facet != NULL) {
16287 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16288 facet = facet->next;
16289 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016290
16291 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016292 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016293}
16294
16295/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016296 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016297 * @ctxtMGroup: the searched model group
16298 * @selfMGroup: the second searched model group
16299 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016300 *
16301 * This one is intended to be used by
16302 * xmlSchemaCheckGroupDefCircular only.
16303 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016304 * Returns the particle with the circular model group definition reference,
16305 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016306 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016307static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016308xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 xmlSchemaTreeItemPtr particle)
16310{
16311 xmlSchemaTreeItemPtr circ = NULL;
16312 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016313 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016314
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016315 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016316 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016317 if (term == NULL)
16318 continue;
16319 switch (term->type) {
16320 case XML_SCHEMA_TYPE_GROUP:
16321 gdef = (xmlSchemaModelGroupDefPtr) term;
16322 if (gdef == groupDef)
16323 return (particle);
16324 /*
16325 * Mark this model group definition to avoid infinite
16326 * recursion on circular references not yet examined.
16327 */
16328 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16329 continue;
16330 if (gdef->children != NULL) {
16331 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16332 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16333 gdef->children->children);
16334 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16335 if (circ != NULL)
16336 return (circ);
16337 }
16338 break;
16339 case XML_SCHEMA_TYPE_SEQUENCE:
16340 case XML_SCHEMA_TYPE_CHOICE:
16341 case XML_SCHEMA_TYPE_ALL:
16342 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16343 if (circ != NULL)
16344 return (circ);
16345 break;
16346 default:
16347 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016348 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016349 }
16350 return (NULL);
16351}
16352
16353/**
16354 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016356 * @ctxt: the parser context
16357 * @name: the name
16358 *
16359 * Checks for circular references to model group definitions.
16360 */
16361static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016362xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016363 xmlSchemaParserCtxtPtr ctxt,
16364 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016365{
16366 /*
16367 * Schema Component Constraint: Model Group Correct
16368 * 2 Circular groups are disallowed. That is, within the {particles}
16369 * of a group there must not be at any depth a particle whose {term}
16370 * is the group itself.
16371 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016372 if ((item == NULL) ||
16373 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16374 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016375 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 {
16377 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016378
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016379 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016380 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016381 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016382 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016383 * TODO: The error report is not adequate: this constraint
16384 * is defined for model groups but not definitions, but since
16385 * there cannot be any circular model groups without a model group
16386 * definition (if not using a construction API), we check those
16387 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016388 */
16389 xmlSchemaPCustomErr(ctxt,
16390 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016391 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016392 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016393 "defined", xmlSchemaFormatQName(&str,
16394 item->targetNamespace, item->name));
16395 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016396 /*
16397 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016399 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016400 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016401 }
16402 }
16403}
16404
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016405/**
16406 * xmlSchemaGroupDefTermFixup:
16407 * @item: the particle with a model group definition as term
16408 * @ctxt: the parser context
16409 * @name: the name
16410 *
16411 * Checks for circular references to model group definitions.
16412 * Additionally it
16413 */
16414static void
16415xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
16416 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
16417 const xmlChar * name ATTRIBUTE_UNUSED)
16418{
16419 if ((item == NULL) ||
16420 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16421 (item->children == NULL) ||
16422 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16423 (item->children->children == NULL))
16424 return;
16425 item->children = item->children->children;
16426}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016427
16428/**
16429 * xmlSchemaGetCircAttrGrRef:
16430 * @ctxtGr: the searched attribute group
16431 * @attr: the current attribute list to be processed
16432 *
16433 * This one is intended to be used by
16434 * xmlSchemaCheckSRCAttributeGroupCircular only.
16435 *
16436 * Returns the circular attribute grou reference, otherwise NULL.
16437 */
16438static xmlSchemaAttributeGroupPtr
16439xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16440 xmlSchemaAttributePtr attr)
16441{
16442 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16443 int marked;
16444 /*
16445 * We will search for an attribute group reference which
16446 * references the context attribute group.
16447 */
16448 while (attr != NULL) {
16449 marked = 0;
16450 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16451 gr = (xmlSchemaAttributeGroupPtr) attr;
16452 if (gr->refItem != NULL) {
16453 if (gr->refItem == ctxtGr)
16454 return (gr);
16455 else if (gr->refItem->flags &
16456 XML_SCHEMAS_ATTRGROUP_MARKED) {
16457 attr = attr->next;
16458 continue;
16459 } else {
16460 /*
16461 * Mark as visited to avoid infinite recursion on
16462 * circular references not yet examined.
16463 */
16464 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16465 marked = 1;
16466 }
16467 }
16468 if (gr->attributes != NULL)
16469 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16470 /*
16471 * Unmark the visited group's attributes.
16472 */
16473 if (marked)
16474 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16475 if (circ != NULL)
16476 return (circ);
16477 }
16478 attr = attr->next;
16479 }
16480 return (NULL);
16481}
16482
16483/**
16484 * xmlSchemaCheckSRCAttributeGroupCircular:
16485 * attrGr: the attribute group definition
16486 * @ctxt: the parser context
16487 * @name: the name
16488 *
16489 * Checks for circular references of attribute groups.
16490 */
16491static void
16492xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
16493 xmlSchemaParserCtxtPtr ctxt,
16494 const xmlChar * name ATTRIBUTE_UNUSED)
16495{
16496 /*
16497 * Schema Representation Constraint:
16498 * Attribute Group Definition Representation OK
16499 * 3 Circular group reference is disallowed outside <redefine>.
16500 * That is, unless this element information item's parent is
16501 * <redefine>, then among the [children], if any, there must
16502 * not be an <attributeGroup> with ref [attribute] which resolves
16503 * to the component corresponding to this <attributeGroup>. Indirect
16504 * circularity is also ruled out. That is, when QName resolution
16505 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16506 * any <attributeGroup>s with a ref [attribute] among the [children],
16507 * it must not be the case that a ·QName· is encountered at any depth
16508 * which resolves to the component corresponding to this <attributeGroup>.
16509 */
16510 /*
16511 * Only global components can be referenced.
16512 */
16513 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
16514 (attrGr->attributes == NULL))
16515 return;
16516 else {
16517 xmlSchemaAttributeGroupPtr circ;
16518
16519 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16520 if (circ != NULL) {
16521 /*
16522 * TODO: Report the referenced attr group as QName.
16523 */
16524 xmlSchemaPCustomErr(ctxt,
16525 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16526 NULL, NULL, circ->node,
16527 "Circular reference to the attribute group '%s' "
16528 "defined", attrGr->name);
16529 /*
16530 * NOTE: We will cut the reference to avoid further
16531 * confusion of the processor.
16532 * BADSPEC: The spec should define how to process in this case.
16533 */
16534 circ->attributes = NULL;
16535 circ->refItem = NULL;
16536 }
16537 }
16538}
16539
16540/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016541 * xmlSchemaAttrGrpFixup:
16542 * @attrgrpDecl: the schema attribute definition
16543 * @ctxt: the schema parser context
16544 * @name: the attribute name
16545 *
16546 * Fixes finish doing the computations on the attributes definitions
16547 */
16548static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016549xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016550 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016551{
16552 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016553 name = attrgrp->name;
16554 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016555 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016556 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016557 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016558
Daniel Veillardc0826a72004-08-10 14:17:33 +000016559 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
16560 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016561 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016562 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016563 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016564 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16565 "ref", attrgrp->ref, attrgrp->refNs,
16566 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016567 return;
16568 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016569 attrgrp->refItem = ref;
16570 /*
16571 * Check for self reference!
16572 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016573 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016574 attrgrp->attributes = ref->attributes;
16575 attrgrp->attributeWildcard = ref->attributeWildcard;
16576 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016577}
16578
16579/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016580 * xmlSchemaAttrCheckValConstr:
16581 * @item: an schema attribute declaration/use
16582 * @ctxt: a schema parser context
16583 * @name: the name of the attribute
16584 *
16585 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016586 *
16587 * Fixes finish doing the computations on the attributes definitions
16588 */
16589static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016590xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
16591 xmlSchemaParserCtxtPtr ctxt,
16592 const xmlChar * name ATTRIBUTE_UNUSED)
16593{
16594
16595 /*
16596 * a-props-correct
16597 * Schema Component Constraint: Attribute Declaration Properties Correct
16598 *
16599 * 2 if there is a {value constraint}, the canonical lexical
16600 * representation of its value must be ·valid· with respect
16601 * to the {type definition} as defined in String Valid (§3.14.4).
16602 */
16603
16604 if (item->defValue != NULL) {
16605 int ret;
16606 xmlNodePtr node;
16607 xmlSchemaTypePtr type;
16608
16609 if (item->subtypes == NULL) {
16610 xmlSchemaPErr(ctxt, item->node,
16611 XML_SCHEMAP_INTERNAL,
16612 "Internal error: xmlSchemaCheckAttrValConstr, "
16613 "type is missing... skipping validation of "
16614 "value constraint", NULL, NULL);
16615 return;
16616 }
16617
16618 /*
16619 * TODO: Try to avoid creating a new context.
16620 * TODO: This all is not very performant.
16621 */
16622 type = item->subtypes;
16623 /*
16624 * Ensure there's validation context.
16625 */
16626 if (ctxt->vctxt == NULL) {
16627 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
16628 xmlSchemaPErr(ctxt, item->node,
16629 XML_SCHEMAP_INTERNAL,
16630 "Internal error: xmlSchemaCheckAttrValConstr, "
16631 "creating a new validation context.\n",
16632 NULL, NULL);
16633 return;
16634 }
16635 }
16636
16637 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
16638 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
16639 else
16640 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
16641 ctxt->vctxt->node = node;
16642 ctxt->vctxt->cur = NULL;
16643 /*
16644 * NOTE: This call does not check the content nodes,
16645 * since they are not available:
16646 * facet->node is just the node holding the facet
16647 * definition, *not* the attribute holding the *value*
16648 * of the facet.
16649 */
16650 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
16651 item->defValue, 0, 1, 1, 0);
16652 if (ret == 0) {
16653 /*
16654 * Store the computed value.
16655 */
16656 item->defVal = ctxt->vctxt->value;
16657 ctxt->vctxt->value = NULL;
16658 } else if (ret > 0) {
16659 if (ctxt != NULL) {
16660 xmlSchemaPSimpleTypeErr(ctxt,
16661 XML_SCHEMAP_A_PROPS_CORRECT_2,
16662 NULL, NULL, node,
16663 type, NULL, item->defValue,
16664 NULL, NULL, NULL);
16665 }
16666 } else if (ret < 0) {
16667 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16668 NULL, NULL, node,
16669 "Internal error: xmlSchemaAttrCheckValConstr, "
16670 "failed to validate the value constraint of the "
16671 "attribute decl/use against the type '%s'",
16672 type->name);
16673 }
16674 }
16675}
16676
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016677static xmlSchemaElementPtr
16678xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
16679 xmlSchemaElementPtr ancestor)
16680{
16681 xmlSchemaElementPtr ret;
16682
16683 if (SUBST_GROUP_AFF(ancestor) == NULL)
16684 return (NULL);
16685 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
16686 return (ancestor);
16687
16688 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
16689 return (NULL);
16690 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
16691 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
16692 SUBST_GROUP_AFF(ancestor));
16693 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
16694
16695 return (ret);
16696}
16697
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016698/**
16699 * xmlSchemaCheckElemPropsCorrect:
16700 * @ctxt: a schema parser context
16701 * @decl: the element declaration
16702 * @name: the name of the attribute
16703 *
16704 * Schema Component Constraint:
16705 * Element Declaration Properties Correct (e-props-correct)
16706 *
16707 * STATUS:
16708 * missing: (6)
16709 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016710static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016711xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16712 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016713{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016714 int ret = 0;
16715 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016716 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016717 * SPEC (1) "The values of the properties of an element declaration
16718 * must be as described in the property tableau in The Element
16719 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
16720 * Sub-components (§5.3)."
16721 */
16722 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016723 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016724 /*
16725 * SPEC (3) "If there is a non-·absent· {substitution group
16726 * affiliation}, then {scope} must be global."
16727 */
16728 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
16729 xmlSchemaPCustomErr(pctxt,
16730 XML_SCHEMAP_E_PROPS_CORRECT_3,
16731 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
16732 "Only global element declarations can have a "
16733 "substitution group affiliation", NULL);
16734 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016735 }
16736 /*
16737 * TODO: SPEC (6) "Circular substitution groups are disallowed.
16738 * That is, it must not be possible to return to an element declaration
16739 * by repeatedly following the {substitution group affiliation}
16740 * property."
16741 */
16742 if (head == elemDecl)
16743 circ = head;
16744 else if (SUBST_GROUP_AFF(head) != NULL)
16745 circ = xmlSchemaCheckSubstGroupCircular(head, head);
16746 else
16747 circ = NULL;
16748 if (circ != NULL) {
16749 xmlChar *strA = NULL, *strB = NULL;
16750
16751 xmlSchemaPCustomErrExt(pctxt,
16752 XML_SCHEMAP_E_PROPS_CORRECT_6,
16753 NULL, (xmlSchemaTypePtr) circ, circ->node,
16754 "The element declaration '%s' defines a circular "
16755 "substitution group to element declaration '%s'",
16756 xmlSchemaGetComponentQName(&strA, circ),
16757 xmlSchemaGetComponentQName(&strB, head),
16758 NULL);
16759 FREE_AND_NULL(strA)
16760 FREE_AND_NULL(strB)
16761 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
16762 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016763 /*
16764 * SPEC (4) "If there is a {substitution group affiliation},
16765 * the {type definition}
16766 * of the element declaration must be validly derived from the {type
16767 * definition} of the {substitution group affiliation}, given the value
16768 * of the {substitution group exclusions} of the {substitution group
16769 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
16770 * (if the {type definition} is complex) or as defined in
16771 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
16772 * simple)."
16773 *
16774 * NOTE: {substitution group exclusions} means the values of the
16775 * attribute "final".
16776 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016777
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016778 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
16779 int set = 0;
16780
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016781 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016782 set |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016783 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016784 set |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
16785
16786 if (xmlSchemaCheckCOSDerivedOK(pctxt->schema, typeDef,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016787 ELEM_TYPE(head), set) != 0) {
16788 xmlChar *strA = NULL, *strB = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016789
16790 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
16791 xmlSchemaPCustomErrExt(pctxt,
16792 XML_SCHEMAP_E_PROPS_CORRECT_4,
16793 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016794 "The type definition of element declaration '%s' is not "
16795 "validly derived from the type definition of its "
16796 "substitution group affiliation '%s'",
16797 xmlSchemaGetComponentQName(&strA, elemDecl),
16798 xmlSchemaGetComponentQName(&strB, head),
16799 NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016800 FREE_AND_NULL(strA)
16801 FREE_AND_NULL(strB)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016802 }
16803 }
16804 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016805 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016806 * SPEC (5) "If the {type definition} or {type definition}'s
16807 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016808 * is or is derived from ID then there must not be a {value constraint}.
16809 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016810 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016811 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016812 if ((elemDecl->value != NULL) &&
16813 ((IS_SIMPLE_TYPE(typeDef) &&
16814 xmlSchemaIsDerivedFromBuiltInType(pctxt,
16815 ELEM_TYPE(elemDecl), XML_SCHEMAS_ID)) ||
16816 (IS_COMPLEX_TYPE(typeDef) &&
16817 HAS_SIMPLE_CONTENT(typeDef) &&
16818 xmlSchemaIsDerivedFromBuiltInType(pctxt,
16819 typeDef->contentTypeDef, XML_SCHEMAS_ID)))) {
16820
16821 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
16822 xmlSchemaPCustomErr(pctxt,
16823 XML_SCHEMAP_E_PROPS_CORRECT_5,
16824 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
16825 "The type definition (or type definition's content type) is or "
16826 "is derived from ID; value constraints are not allowed in "
16827 "conjunction with such a type definition", NULL);
16828 } else if (elemDecl->value != NULL) {
16829 int vcret;
16830 xmlNodePtr node = NULL;
16831
16832 /*
16833 * SPEC (2) "If there is a {value constraint}, the canonical lexical
16834 * representation of its value must be ·valid· with respect to the
16835 * {type definition} as defined in Element Default Valid (Immediate)
16836 * (§3.3.6)."
16837 */
16838 if (typeDef == NULL) {
16839 xmlSchemaPErr(pctxt, elemDecl->node,
16840 XML_SCHEMAP_INTERNAL,
16841 "Internal error: xmlSchemaCheckElemPropsCorrect, "
16842 "type is missing... skipping validation of "
16843 "the value constraint", NULL, NULL);
16844 return (-1);
16845 }
16846 /*
16847 * Ensure there's a validation context.
16848 */
16849 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
16850 return (-1);
16851 if (elemDecl->node != NULL) {
16852 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
16853 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
16854 BAD_CAST "fixed");
16855 else
16856 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
16857 BAD_CAST "default");
16858 }
16859 pctxt->vctxt->node = node;
16860 pctxt->vctxt->cur = NULL;
16861 vcret = xmlSchemaCheckCOSValidDefault(pctxt, pctxt->vctxt, typeDef,
16862 elemDecl->value, node);
16863 if (vcret == 0) {
16864 /*
16865 * Consume the computed value.
16866 */
16867 elemDecl->defVal = pctxt->vctxt->value;
16868 pctxt->vctxt->value = NULL;
16869 } else if (vcret < 0) {
16870 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_INTERNAL,
16871 NULL, NULL, node,
16872 "Internal error: xmlSchemaElemCheckValConstr, "
16873 "failed to validate the value constraint of the "
16874 "element declaration '%s'",
16875 elemDecl->name);
16876 ret = vcret;
16877 } else
16878 ret = vcret;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016879 }
16880
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016881 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016882}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016883
16884/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016885 * xmlSchemaCheckElemSubstGroup:
16886 * @ctxt: a schema parser context
16887 * @decl: the element declaration
16888 * @name: the name of the attribute
16889 *
16890 * Schema Component Constraint:
16891 * Substitution Group (cos-equiv-class)
16892 *
16893 * In Libxml2 the subst. groups will be precomputed, in terms of that
16894 * a list will be built for each subst. group head, holding all direct
16895 * referents to this head.
16896 * NOTE that this function needs:
16897 * 1. circular subst. groups to be checked beforehand
16898 * 2. the declaration's type to be derived from the head's type
16899 *
16900 * STATUS:
16901 *
16902 */
16903static void
16904xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
16905 xmlSchemaElementPtr elemDecl)
16906{
16907 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
16908 /* SPEC (1) "Its {abstract} is false." */
16909 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
16910 return;
16911 {
16912 xmlSchemaElementPtr head;
16913 xmlSchemaTypePtr headType, type;
16914 int set, methSet;
16915 /*
16916 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
16917 * {disallowed substitutions} as the blocking constraint, as defined in
16918 * Substitution Group OK (Transitive) (§3.3.6)."
16919 */
16920 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
16921 head = SUBST_GROUP_AFF(head)) {
16922 set = 0;
16923 methSet = 0;
16924 /*
16925 * The blocking constraints.
16926 */
16927 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
16928 continue;
16929 headType = head->subtypes;
16930 type = elemDecl->subtypes;
16931 if (headType == type)
16932 goto add_member;
16933 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
16934 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
16935 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
16936 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
16937 /*
16938 * SPEC: Substitution Group OK (Transitive) (2.3)
16939 * "The set of all {derivation method}s involved in the
16940 * derivation of D's {type definition} from C's {type definition}
16941 * does not intersect with the union of the blocking constraint,
16942 * C's {prohibited substitutions} (if C is complex, otherwise the
16943 * empty set) and the {prohibited substitutions} (respectively the
16944 * empty set) of any intermediate {type definition}s in the
16945 * derivation of D's {type definition} from C's {type definition}."
16946 */
16947 /*
16948 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
16949 * subst.head axis, the methSet does not need to be computed for
16950 * the full depth over and over.
16951 */
16952 /*
16953 * The set of all {derivation method}s involved in the derivation
16954 */
16955 while ((type != NULL) && (type != headType)) {
16956 if ((type->flags &
16957 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
16958 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
16959 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
16960
16961 if ((type->flags &
16962 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
16963 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
16964 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
16965
16966 type = type->baseType;
16967 }
16968 /*
16969 * The {prohibited substitutions} of all intermediate types +
16970 * the head's type.
16971 */
16972 type = elemDecl->subtypes->baseType;
16973 while (type != NULL) {
16974 if (IS_COMPLEX_TYPE(type)) {
16975 if ((type->flags &
16976 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
16977 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
16978 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
16979 if ((type->flags &
16980 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
16981 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
16982 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
16983 } else
16984 break;
16985 if (type == headType)
16986 break;
16987 type = type->baseType;
16988 }
16989 if ((set != 0) &&
16990 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
16991 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
16992 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
16993 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
16994 continue;
16995 }
16996add_member:
16997 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
16998 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
16999 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17000 }
17001 }
17002}
17003
17004/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017005 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017006 * @item: an schema element declaration/particle
17007 * @ctxt: a schema parser context
17008 * @name: the name of the attribute
17009 *
17010 * Validates the value constraints of an element declaration.
17011 *
17012 * Fixes finish doing the computations on the element declarations.
17013 */
17014static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017015xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
17016 xmlSchemaParserCtxtPtr ctxt,
17017 const xmlChar * name ATTRIBUTE_UNUSED)
17018{
17019 if (elemDecl == NULL)
17020 return;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017021 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17022 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017023}
17024
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017025/**
17026 * xmlSchemaMiscRefFixup:
17027 * @item: an schema component
17028 * @ctxt: a schema parser context
17029 * @name: the internal name of the component
17030 *
17031 * Resolves references of misc. schema components.
17032 */
17033static void
17034xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
17035 xmlSchemaParserCtxtPtr ctxt,
17036 const xmlChar * name ATTRIBUTE_UNUSED)
17037{
17038 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
17039 if ((item->children != NULL) &&
17040 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17041 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17042 xmlSchemaTreeItemPtr refItem;
17043 /*
17044 * Resolve the reference.
17045 */
17046 item->children = NULL;
17047 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17048 ref->itemType, ref->name, ref->targetNamespace);
17049 if (refItem == NULL) {
17050 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
17051 NULL, NULL, GET_NODE(item), "ref", ref->name,
17052 ref->targetNamespace, ref->itemType, NULL);
17053 } else {
17054 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17055 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017056 * NOTE that we will assign the model group definition
17057 * itself to the "term" of the particle. This will ease
17058 * the check for circular model group definitions. After
17059 * that the "term" will be assigned the model group of the
17060 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017061 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017062 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017063 } else
17064 item->children = refItem;
17065 }
17066 }
17067 }
17068}
17069
17070
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017071/**
17072 * xmlSchemaAttrFixup:
17073 * @item: an schema attribute declaration/use.
17074 * @ctxt: a schema parser context
17075 * @name: the name of the attribute
17076 *
17077 * Fixes finish doing the computations on attribute declarations/uses.
17078 */
17079static void
17080xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
17081 xmlSchemaParserCtxtPtr ctxt,
17082 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017083{
Daniel Veillardc0826a72004-08-10 14:17:33 +000017084 /*
17085 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017086 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017087 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017088 /*
17089 * The simple type definition corresponding to the <simpleType> element
17090 * information item in the [children], if present, otherwise the simple
17091 * type definition ·resolved· to by the ·actual value· of the type
17092 * [attribute], if present, otherwise the ·simple ur-type definition·.
17093 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017094 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017095 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017096 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17097 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017098 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017099 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017100 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017101
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017102 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17103 item->typeNs);
17104 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017105 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017106 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017107 NULL, (xmlSchemaTypePtr) item, item->node,
17108 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017109 XML_SCHEMA_TYPE_SIMPLE, NULL);
17110 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017111 item->subtypes = type;
17112
17113 } else if (item->ref != NULL) {
17114 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017115
Daniel Veillardc0826a72004-08-10 14:17:33 +000017116 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017117 * We have an attribute use here; assign the referenced
17118 * attribute declaration.
17119 */
17120 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017121 * TODO: Evaluate, what errors could occur if the declaration is not
17122 * found. It might be possible that the "typefixup" might crash if
17123 * no ref declaration was found.
17124 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017125 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
17126 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017127 xmlSchemaPResCompAttrErr(ctxt,
17128 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017129 NULL, (xmlSchemaTypePtr) item, item->node,
17130 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017131 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017132 return;
17133 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017134 item->refDecl = decl;
17135 xmlSchemaAttrFixup(decl, ctxt, NULL);
17136
17137 item->subtypes = decl->subtypes;
17138 /*
17139 * Attribute Use Correct
17140 * au-props-correct.2: If the {attribute declaration} has a fixed
17141 * {value constraint}, then if the attribute use itself has a
17142 * {value constraint}, it must also be fixed and its value must match
17143 * that of the {attribute declaration}'s {value constraint}.
17144 */
17145 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
17146 (item->defValue != NULL)) {
17147 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
17148 (!xmlStrEqual(item->defValue, decl->defValue))) {
17149 xmlSchemaPCustomErr(ctxt,
17150 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17151 NULL, NULL, item->node,
17152 "The value constraint must be fixed "
17153 "and match the referenced attribute "
17154 "declarations's value constraint '%s'",
17155 decl->defValue);
17156 }
17157 /*
17158 * FUTURE: One should change the values of the attr. use
17159 * if ever validation should be attempted even if the
17160 * schema itself was not fully valid.
17161 */
17162 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017163 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017164 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17165 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017166}
17167
17168/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017169 * xmlSchemaResolveIDCKeyRef:
17170 * @idc: the identity-constraint definition
17171 * @ctxt: the schema parser context
17172 * @name: the attribute name
17173 *
17174 * Resolve keyRef references to key/unique IDCs.
17175 */
17176static void
17177xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
17178 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017179 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017180{
17181 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17182 return;
17183 if (idc->ref->name != NULL) {
17184 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
17185 ctxt->schema->idcDef,
17186 idc->ref->name,
17187 idc->ref->targetNamespace);
17188 if (idc->ref->item == NULL) {
17189 /*
17190 * TODO: It is actually not an error to fail to resolve.
17191 */
17192 xmlSchemaPResCompAttrErr(ctxt,
17193 XML_SCHEMAP_SRC_RESOLVE,
17194 NULL, (xmlSchemaTypePtr) idc, idc->node,
17195 "refer", idc->ref->name,
17196 idc->ref->targetNamespace,
17197 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17198 return;
17199 }
17200 }
17201}
17202
17203/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017204 * xmlSchemaParse:
17205 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017206 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017207 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017208 * XML Shema struture which can be used to validate instances.
17209 * *WARNING* this interface is highly subject to change
17210 *
17211 * Returns the internal XML Schema structure built from the resource or
17212 * NULL in case of error
17213 */
17214xmlSchemaPtr
17215xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17216{
17217 xmlSchemaPtr ret = NULL;
17218 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017219 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017220 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017221
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017222 /*
17223 * This one is used if the schema to be parsed was specified via
17224 * the API; i.e. not automatically by the validated instance document.
17225 */
17226
Daniel Veillard4255d502002-04-16 15:50:10 +000017227 xmlSchemaInitTypes();
17228
Daniel Veillard6045c902002-10-09 21:13:59 +000017229 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017230 return (NULL);
17231
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017232 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017233 ctxt->counter = 0;
17234 ctxt->container = NULL;
17235
17236 /*
17237 * First step is to parse the input document into an DOM/Infoset
17238 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017239 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017240 doc = xmlReadFile((const char *) ctxt->URL, NULL,
17241 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017242 if (doc == NULL) {
17243 xmlSchemaPErr(ctxt, NULL,
17244 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017245 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017246 ctxt->URL, NULL);
17247 return (NULL);
17248 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017249 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017250 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17251 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017252 if (doc == NULL) {
17253 xmlSchemaPErr(ctxt, NULL,
17254 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017255 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017256 NULL, NULL);
17257 return (NULL);
17258 }
17259 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017260 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017261 } else if (ctxt->doc != NULL) {
17262 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017263 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017264 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017265 xmlSchemaPErr(ctxt, NULL,
17266 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017267 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017268 NULL, NULL);
17269 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017270 }
17271
17272 /*
17273 * Then extract the root and Schema parse it
17274 */
17275 root = xmlDocGetRootElement(doc);
17276 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017277 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17278 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017279 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017280 if (!preserve) {
17281 xmlFreeDoc(doc);
17282 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017283 return (NULL);
17284 }
17285
17286 /*
17287 * Remove all the blank text nodes
17288 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017289 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017290
17291 /*
17292 * Then do the parsing for good
17293 */
17294 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017295 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017296 if (!preserve) {
17297 xmlFreeDoc(doc);
17298 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017299 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017300 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017301 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017302 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017303 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017304 ctxt->ctxtType = NULL;
17305 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017306
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017307 /*
17308 * Resolve base types of simple/complex types.
17309 */
17310 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
17311
17312 if (ctxt->nberrors != 0)
17313 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017314
17315 if (ret->volatiles != NULL) {
17316 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17317 int i;
17318 xmlSchemaTreeItemPtr item;
17319
17320 for (i = 0; i < list->nbItems; i++) {
17321 item = (xmlSchemaTreeItemPtr) list->items[i];
17322 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17323 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017324 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017325 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017326 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017327 * Then fixup all attributes declarations
17328 */
17329 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017330 /*
17331 * Then fixup all attributes group declarations
17332 */
17333 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17334 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017335 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017336 * Resolve identity-constraint keyRefs.
17337 */
17338 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017339 /*
17340 * Check type defnitions for circular references.
17341 */
17342 xmlHashScan(ret->typeDecl, (xmlHashScanner)
17343 xmlSchemaCheckTypeDefCircular, ctxt);
17344 /*
17345 * Check model groups defnitions for circular references.
17346 */
17347 xmlHashScan(ret->groupDecl, (xmlHashScanner)
17348 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017349 /*
17350 * Set the "term" of particles pointing to model group definitions
17351 * to the contained model group.
17352 */
17353 if (ret->volatiles != NULL) {
17354 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17355 int i;
17356 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017357
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017358 for (i = 0; i < list->nbItems; i++) {
17359 item = (xmlSchemaParticlePtr) list->items[i];
17360 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17361 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17362 }
17363 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017364 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017365 * Check attribute groups for circular references.
17366 */
17367 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017368 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017369 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017370 * Then fix references of element declaration; apply constraints.
17371 */
17372 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017373 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017374 /*
17375 * We will stop here if the schema was not valid to avoid internal errors
17376 * on missing sub-components. This is not conforming to the spec, since it
17377 * allows missing components, but it might make further processing crash.
17378 * So see it as a very strict handling, which might be made more lax in the
17379 * future.
17380 */
17381 if (ctxt->nberrors != 0)
17382 goto exit;
17383 /*
17384 * Then fixup all types properties
17385 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017386 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017387 /*
17388 * Validate the value constraint of attribute declarations/uses.
17389 */
17390 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017391 /*
17392 * Validate the value constraint of element declarations.
17393 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017394 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017395 /*
17396 * Then build the content model for all complex types
17397 */
17398 xmlHashScan(ret->typeDecl,
17399 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017400
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017401exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017402 if (ctxt->nberrors != 0) {
17403 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017404 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017405 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017406 return (ret);
17407}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017408
Daniel Veillard4255d502002-04-16 15:50:10 +000017409/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017410 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017411 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017412 * @err: the error callback
17413 * @warn: the warning callback
17414 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017415 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017416 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017417 */
17418void
17419xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017420 xmlSchemaValidityErrorFunc err,
17421 xmlSchemaValidityWarningFunc warn, void *ctx)
17422{
Daniel Veillard4255d502002-04-16 15:50:10 +000017423 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017424 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017425 ctxt->error = err;
17426 ctxt->warning = warn;
17427 ctxt->userData = ctx;
17428}
17429
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017430/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017431 * xmlSchemaGetParserErrors:
17432 * @ctxt: a XMl-Schema parser context
17433 * @err: the error callback result
17434 * @warn: the warning callback result
17435 * @ctx: contextual data for the callbacks result
17436 *
17437 * Get the callback information used to handle errors for a parser context
17438 *
17439 * Returns -1 in case of failure, 0 otherwise
17440 */
17441int
17442xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17443 xmlSchemaValidityErrorFunc * err,
17444 xmlSchemaValidityWarningFunc * warn, void **ctx)
17445{
17446 if (ctxt == NULL)
17447 return(-1);
17448 if (err != NULL)
17449 *err = ctxt->error;
17450 if (warn != NULL)
17451 *warn = ctxt->warning;
17452 if (ctx != NULL)
17453 *ctx = ctxt->userData;
17454 return(0);
17455}
17456
17457/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017458 * xmlSchemaFacetTypeToString:
17459 * @type: the facet type
17460 *
17461 * Convert the xmlSchemaTypeType to a char string.
17462 *
17463 * Returns the char string representation of the facet type if the
17464 * type is a facet and an "Internal Error" string otherwise.
17465 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017466static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017467xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17468{
17469 switch (type) {
17470 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017471 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017472 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017473 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017474 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017475 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017476 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017477 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017478 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017479 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017480 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017481 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017482 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017483 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017484 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017485 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017486 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017487 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017488 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017489 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017490 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017491 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017492 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017493 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017494 default:
17495 break;
17496 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017497 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017498}
17499
Daniel Veillardc0826a72004-08-10 14:17:33 +000017500static int
17501xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17502{
17503 xmlSchemaTypePtr anc;
17504
17505 /*
17506 * The normalization type can be changed only for types which are derived
17507 * from xsd:string.
17508 */
17509 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017510 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017511 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017512 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017513 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017514 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
17515 /*
17516 * Note that we assume a whitespace of preserve for anySimpleType.
17517 */
17518 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017519 else {
17520 /*
17521 * For all ·atomic· datatypes other than string (and types ·derived·
17522 * by ·restriction· from it) the value of whiteSpace is fixed to
17523 * collapse
17524 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017525 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017526 }
17527 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
17528 /*
17529 * For list types the facet "whiteSpace" is fixed to "collapse".
17530 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017531 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017532 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017533 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017534 } else if (type->facetSet != NULL) {
17535 xmlSchemaTypePtr anyST;
17536 xmlSchemaFacetLinkPtr lin;
17537
17538 /*
17539 * Atomic types.
17540 */
17541 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17542 anc = type->baseType;
17543 do {
17544 /*
17545 * For all ·atomic· datatypes other than string (and types ·derived·
17546 * by ·restriction· from it) the value of whiteSpace is fixed to
17547 * collapse
17548 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017549 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17550 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017551
17552 lin = type->facetSet;
17553 do {
17554 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017555 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017556 }
17557 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017558 } while (lin != NULL);
17559 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
17560 return (XML_SCHEMAS_FACET_REPLACE);
17561 else
17562 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017563 }
17564 anc = anc->baseType;
17565 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017566 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017567 }
17568 return (-1);
17569}
17570
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017571/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000017572 * xmlSchemaValidateFacetsInternal:
17573 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000017574 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000017575 * @facets: the list of facets to check
17576 * @value: the lexical repr of the value to validate
17577 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000017578 * @fireErrors: if 0, only internal errors will be fired;
17579 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000017580 *
17581 * Check a value against all facet conditions
17582 *
17583 * Returns 0 if the element is schemas valid, a positive error code
17584 * number otherwise and -1 in case of internal or API error.
17585 */
17586static int
17587xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017588 xmlSchemaTypePtr type,
17589 const xmlChar * value,
17590 unsigned long length,
17591 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000017592{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017593 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017594 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017595 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017596 xmlSchemaTypePtr tmpType;
17597 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000017598 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017599 xmlSchemaFacetPtr facet;
17600 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017601 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017602
17603 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017604
Daniel Veillardc0826a72004-08-10 14:17:33 +000017605#ifdef DEBUG_UNION_VALIDATION
17606 printf("Facets of type: '%s'\n", (const char *) type->name);
17607 printf(" fireErrors: %d\n", fireErrors);
17608#endif
17609
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017610 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017611 /*
17612 * NOTE: Do not jump away, if the facetSet of the given type is
17613 * empty: until now, "pattern" facets of the *base types* need to
17614 * be checked as well.
17615 */
17616 biType = type->baseType;
17617 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
17618 biType = biType->baseType;
17619 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017620 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017621 "Internal error: xmlSchemaValidateFacetsInternal, "
17622 "the base type axis of the given type '%s' does not resolve to "
17623 "a built-in type.\n",
17624 type->name, NULL);
17625 return (-1);
17626 }
17627
17628 if (type->facetSet != NULL) {
17629 facetLink = type->facetSet;
17630 while (facetLink != NULL) {
17631 facet = facetLink->facet;
17632 /*
17633 * Skip the pattern "whiteSpace": it is used to
17634 * format the character content beforehand.
17635 */
17636 switch (facet->type) {
17637 case XML_SCHEMA_FACET_WHITESPACE:
17638 case XML_SCHEMA_FACET_PATTERN:
17639 case XML_SCHEMA_FACET_ENUMERATION:
17640 break;
17641 case XML_SCHEMA_FACET_LENGTH:
17642 case XML_SCHEMA_FACET_MINLENGTH:
17643 case XML_SCHEMA_FACET_MAXLENGTH:
17644 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
17645 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017646 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017647 len = length;
17648 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017649 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
17650 (xmlSchemaValType) biType->builtInType,
17651 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017652 break;
17653 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017654 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
17655 biType->builtInType, value, ctxt->value, ws);
17656 /*
17657 * ret = xmlSchemaValidateFacet(biType, facet, value,
17658 * ctxt->value);
17659 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017660 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017661 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017662 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017663 "Internal error: xmlSchemaValidateFacetsInternal, "
17664 "validating facet of type '%s'.\n",
17665 type->name, NULL);
17666 break;
17667 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017668 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017669 type, facet, NULL, NULL, NULL, NULL);
17670 }
17671
17672 facetLink = facetLink->next;
17673 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017674
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017675 }
17676
Daniel Veillardc0826a72004-08-10 14:17:33 +000017677 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017678 xmlSchemaWhitespaceValueType fws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017679 int found = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017680 /*
17681 * Process enumerations. Facet values are in the value space
17682 * of the defining type's base type. This seems to be a bug in the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017683 * XML Schema 1.0 spec. Use the whitespace type of the base type.
17684 * Only the first set of enumerations in the ancestor-or-self axis
17685 * is used for validation.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017686 */
17687 tmpType = type;
17688 do {
17689 /*
17690 * Use the whitespace type of the base type.
17691 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017692 fws = (xmlSchemaWhitespaceValueType)
17693 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017694 retFacet = 0;
17695 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
17696 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017697 continue;
17698 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017699 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
17700 biType->builtInType, value, ctxt->value, ws);
17701 if (retFacet == 0)
17702 break;
17703 else if (retFacet < 0) {
17704 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17705 "Internal error: xmlSchemaValidateFacetsInternal, "
17706 "validating enumeration facet '%s' of type '%s'.\n",
17707 facet->value, tmpType->name);
17708 ret = -1;
17709 break;
17710 }
17711 }
17712 if (retFacet <= 0)
17713 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017714 tmpType = tmpType->baseType;
17715 } while ((! found) && (tmpType != NULL) &&
17716 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017717 if (retFacet > 0) {
Kasimier T. Buchcik53b5e052005-03-24 11:05:13 +000017718 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017719 if (fireErrors) {
17720 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
17721 NULL, NULL, NULL, NULL);
17722 }
17723 }
17724 }
17725
17726 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017727 /*
17728 * Process patters. Pattern facets are ORed at type level
17729 * and ANDed if derived. Walk the base type axis.
17730 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017731 tmpType = type;
17732 facet = NULL;
17733 do {
17734 retFacet = 0;
17735 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017736 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017737 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
17738 continue;
17739 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
17740 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017741 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017742 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017743 else if (retFacet < 0) {
17744 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17745 "Internal error: xmlSchemaValidateFacetsInternal, "
17746 "validating 'pattern' facet '%s' of type '%s'.\n",
17747 facetLink->facet->value, tmpType->name);
17748 ret = -1;
17749 break;
17750 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000017751 /* Save the last non-validating facet. */
17752 facet = facetLink->facet;
17753 }
17754 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017755 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017756 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017757 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017758 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017759 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
17760 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017761 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017762 NULL, NULL, NULL, NULL);
17763 }
17764 }
17765 }
17766
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017767 return (ret);
17768}
17769
Daniel Veillard4255d502002-04-16 15:50:10 +000017770/************************************************************************
17771 * *
17772 * Simple type validation *
17773 * *
17774 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017775
Daniel Veillard4255d502002-04-16 15:50:10 +000017776
17777/************************************************************************
17778 * *
17779 * DOM Validation code *
17780 * *
17781 ************************************************************************/
17782
Daniel Veillard4255d502002-04-16 15:50:10 +000017783static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017784 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000017785 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017786static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017787 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017788 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017789 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000017790
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017791static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017792static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017793
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017794/**
17795 * xmlSchemaGetFreshElemInfo:
17796 * @vctxt: the schema validation context
17797 *
17798 * Creates/reuses and initializes the element info item for
17799 * the currect tree depth.
17800 *
17801 * Returns the element info item or NULL on API or internal errors.
17802 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017803static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017804xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
17805 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017806{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017807 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017808
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017809 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017810 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017811 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017812 "an inconsistent depth encountered.\n",
17813 NULL, NULL);
17814 return (NULL);
17815 }
17816 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017817 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
17818 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017819 if (vctxt->elemInfos == NULL) {
17820 xmlSchemaVErrMemory(vctxt,
17821 "allocating the element info array", NULL);
17822 return (NULL);
17823 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017824 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017825 vctxt->sizeElemInfos = 10;
17826 } else if (vctxt->sizeElemInfos == vctxt->depth) {
17827 int i = vctxt->sizeElemInfos;
17828
17829 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017830 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017831 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017832 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017833 if (vctxt->elemInfos == NULL) {
17834 xmlSchemaVErrMemory(vctxt,
17835 "re-allocating the element info array", NULL);
17836 return (NULL);
17837 }
17838 /*
17839 * We need the new memory to be NULLed.
17840 * TODO: Use memset instead?
17841 */
17842 for (; i < vctxt->sizeElemInfos; i++)
17843 vctxt->elemInfos[i] = NULL;
17844 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017845 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017846
17847 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017848 info = (xmlSchemaNodeInfoPtr)
17849 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017850 if (info == NULL) {
17851 xmlSchemaVErrMemory(vctxt,
17852 "allocating an element info", NULL);
17853 return (NULL);
17854 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017855 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017856 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017857 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017858 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017859
17860 return (info);
17861}
Daniel Veillard3646d642004-06-02 19:19:14 +000017862
17863/**
17864 * xmlSchemaFreeAttrStates:
17865 * @state: a list of attribute states
17866 *
17867 * Free the given list of attribute states
17868 *
17869 */
17870static void
17871xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
17872{
17873 xmlSchemaAttrStatePtr tmp;
17874 while (state != NULL) {
17875 tmp = state;
17876 state = state->next;
17877 xmlFree(tmp);
17878 }
17879}
17880
Daniel Veillard4255d502002-04-16 15:50:10 +000017881/**
17882 * xmlSchemaRegisterAttributes:
17883 * @ctxt: a schema validation context
17884 * @attrs: a list of attributes
17885 *
17886 * Register the list of attributes as the set to be validated on that element
17887 *
17888 * Returns -1 in case of error, 0 otherwise
17889 */
17890static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017891xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
17892{
Daniel Veillard3646d642004-06-02 19:19:14 +000017893 xmlSchemaAttrStatePtr tmp;
17894
17895 ctxt->attr = NULL;
17896 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000017897 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017898 if ((attrs->ns != NULL) &&
17899 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
17900 attrs = attrs->next;
17901 continue;
17902 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017903 tmp = (xmlSchemaAttrStatePtr)
17904 xmlMalloc(sizeof(xmlSchemaAttrState));
17905 if (tmp == NULL) {
17906 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
17907 return (-1);
17908 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017909 tmp->attr = attrs;
17910 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
17911 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017912 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000017913 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017914 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000017915 else
17916 ctxt->attrTop->next = tmp;
17917 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017918 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017919 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017920 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017921}
17922
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017923#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000017924/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017925 * xmlSchemaValidateCheckNodeList
17926 * @nodelist: the list of nodes
17927 *
17928 * Check the node list is only made of text nodes and entities pointing
17929 * to text nodes
17930 *
17931 * Returns 1 if true, 0 if false and -1 in case of error
17932 */
17933static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017934xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
17935{
Daniel Veillard4255d502002-04-16 15:50:10 +000017936 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017937 if (nodelist->type == XML_ENTITY_REF_NODE) {
17938 TODO /* implement recursion in the entity content */
17939 }
17940 if ((nodelist->type != XML_TEXT_NODE) &&
17941 (nodelist->type != XML_COMMENT_NODE) &&
17942 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000017943 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017944 return (0);
17945 }
17946 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017947 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017948 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017949}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017950#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000017951
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017952static void
17953xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17954{
17955 int i, nbItems;
17956 xmlSchemaTypePtr item, *items;
17957
17958
17959 /*
17960 * During the Assemble of the schema ctxt->curItems has
17961 * been filled with the relevant new items. Fix those up.
17962 */
17963 nbItems = ctxt->assemble->nbItems;
17964 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
17965
17966 for (i = 0; i < nbItems; i++) {
17967 item = items[i];
17968 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017969 case XML_SCHEMA_TYPE_COMPLEX:
17970 case XML_SCHEMA_TYPE_SIMPLE:
17971 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
17972 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017973 case XML_SCHEMA_TYPE_ATTRIBUTE:
17974 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17975 break;
17976 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017977 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017978 NULL, NULL, NULL);
17979 break;
17980 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17981 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
17982 ctxt, NULL);
17983 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017984 case XML_SCHEMA_TYPE_PARTICLE:
17985 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017986 default:
17987 break;
17988 }
17989 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017990 if (ctxt->nberrors != 0)
17991 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017992 /*
17993 * Circularity checks.
17994 */
17995 for (i = 0; i < nbItems; i++) {
17996 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017997 switch (item->type) {
17998 case XML_SCHEMA_TYPE_COMPLEX:
17999 case XML_SCHEMA_TYPE_SIMPLE:
18000 xmlSchemaCheckTypeDefCircular(
18001 (xmlSchemaTypePtr) item, ctxt, NULL);
18002 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018003 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018004 xmlSchemaCheckGroupDefCircular(
18005 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018006 break;
18007 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18008 xmlSchemaCheckAttributeGroupCircular(
18009 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18010 break;
18011 default:
18012 break;
18013 }
18014 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018015 if (ctxt->nberrors != 0)
18016 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018017 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018018 * Set the "term" of particles pointing to model group definitions
18019 * to the contained model group.
18020 */
18021 for (i = 0; i < nbItems; i++) {
18022 item = items[i];
18023 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18024 (((xmlSchemaParticlePtr) item)->children != NULL) &&
18025 (((xmlSchemaParticlePtr) item)->children->type ==
18026 XML_SCHEMA_TYPE_GROUP)) {
18027 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18028 ctxt, NULL);
18029 }
18030 }
18031 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018032 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018033 */
18034 for (i = 0; i < nbItems; i++) {
18035 item = items[i];
18036 switch (item->type) {
18037 case XML_SCHEMA_TYPE_SIMPLE:
18038 case XML_SCHEMA_TYPE_COMPLEX:
18039 xmlSchemaTypeFixup(item, ctxt, NULL);
18040 break;
18041 default:
18042 break;
18043 }
18044 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018045 if (ctxt->nberrors != 0)
18046 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018047 /*
18048 * Validate value contraint values.
18049 */
18050 for (i = 0; i < nbItems; i++) {
18051 item = items[i];
18052 switch (item->type) {
18053 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018054 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18055 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018056 break;
18057 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018058 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018059 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018060 break;
18061 default:
18062 break;
18063 }
18064 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018065 if (ctxt->nberrors != 0)
18066 return;
18067 /*
18068 * Build the content model for complex types.
18069 */
18070 for (i = 0; i < nbItems; i++) {
18071 item = items[i];
18072 switch (item->type) {
18073 case XML_SCHEMA_TYPE_COMPLEX:
18074 xmlSchemaBuildContentModel(item, ctxt, NULL);
18075 break;
18076 default:
18077 break;
18078 }
18079 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018080}
18081
18082/**
18083 * xmlSchemaAssembleByLocation:
18084 * @pctxt: a schema parser context
18085 * @vctxt: a schema validation context
18086 * @schema: the existing schema
18087 * @node: the node that fired the assembling
18088 * @nsName: the namespace name of the new schema
18089 * @location: the location of the schema
18090 *
18091 * Expands an existing schema by an additional schema.
18092 *
18093 * Returns 0 if the new schema is correct, a positive error code
18094 * number otherwise and -1 in case of an internal or API error.
18095 */
18096static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018097xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
18098 xmlSchemaPtr schema,
18099 xmlNodePtr node,
18100 const xmlChar *nsName,
18101 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018102{
18103 const xmlChar *targetNs, *oldtns;
18104 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018105 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018106 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018107 xmlSchemaParserCtxtPtr pctxt;
18108
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018109 /*
18110 * This should be used:
18111 * 1. on <import>(s)
18112 * 2. if requested by the validated instance
18113 * 3. if requested via the API
18114 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018115 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018116 return (-1);
18117 /*
18118 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018119 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018120 if ((vctxt->pctxt == NULL) &&
18121 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
18122 xmlSchemaVErr(vctxt, node,
18123 XML_SCHEMAV_INTERNAL,
18124 "Internal error: xmlSchemaAssembleByLocation, "
18125 "failed to create a temp. parser context.\n",
18126 NULL, NULL);
18127 return (-1);
18128 }
18129 pctxt = vctxt->pctxt;
18130 /*
18131 * Set the counter to produce unique names for anonymous items.
18132 */
18133 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 /*
18135 * Acquire the schema document.
18136 */
18137 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
18138 nsName, location, &doc, &targetNs, 0);
18139 if (ret != 0) {
18140 if (doc != NULL)
18141 xmlFreeDoc(doc);
18142 } else if (doc != NULL) {
18143 docElem = xmlDocGetRootElement(doc);
18144 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018145 * Create new assemble info.
18146 */
18147 if (pctxt->assemble == NULL) {
18148 pctxt->assemble = xmlSchemaNewAssemble();
18149 if (pctxt->assemble == NULL) {
18150 xmlSchemaVErrMemory(vctxt,
18151 "Memory error: xmlSchemaAssembleByLocation, "
18152 "allocating assemble info", NULL);
18153 xmlFreeDoc(doc);
18154 return (-1);
18155 }
18156 }
18157 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018158 * Save and reset the context & schema.
18159 */
18160 oldflags = schema->flags;
18161 oldtns = schema->targetNamespace;
18162 olddoc = schema->doc;
18163
18164 xmlSchemaClearSchemaDefaults(schema);
18165 schema->targetNamespace = targetNs;
18166 /* schema->nbCurItems = 0; */
18167 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018168 pctxt->ctxtType = NULL;
18169 pctxt->parentItem = NULL;
18170
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018171 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18172 if (pctxt->nberrors != 0) {
18173 vctxt->nberrors += pctxt->nberrors;
18174 goto finally;
18175 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018176 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018177 if (pctxt->nberrors != 0) {
18178 vctxt->nberrors += pctxt->nberrors;
18179 goto finally;
18180 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018181 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018182 if (pctxt->nberrors != 0)
18183 vctxt->nberrors += pctxt->nberrors;
18184finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018185 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018186 * Set the counter of items.
18187 */
18188 schema->counter = pctxt->counter;
18189 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018190 * Free the list of assembled components.
18191 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018192 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018193 /*
18194 * Restore the context & schema.
18195 */
18196 schema->flags = oldflags;
18197 schema->targetNamespace = oldtns;
18198 schema->doc = olddoc;
18199 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018200 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018201 return (ret);
18202}
18203
18204/**
18205 * xmlSchemaAssembleByXSIAttr:
18206 * @vctxt: a schema validation context
18207 * @xsiAttr: an xsi attribute
18208 * @noNamespace: whether a schema with no target namespace is exptected
18209 *
18210 * Expands an existing schema by an additional schema using
18211 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18212 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18213 * must be set to 1.
18214 *
18215 * Returns 0 if the new schema is correct, a positive error code
18216 * number otherwise and -1 in case of an internal or API error.
18217 */
18218static int
18219xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
18220 xmlAttrPtr xsiAttr,
18221 int noNamespace)
18222{
18223 xmlChar *value;
18224 const xmlChar *cur, *end;
18225 const xmlChar *nsname = NULL, *location;
18226 int count = 0;
18227 int ret = 0;
18228
18229 if (xsiAttr == NULL) {
18230 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
18231 NULL, NULL,
18232 "Internal error: xmlSchemaAssembleByXSIAttr, "
18233 "bad arguments", NULL);
18234 return (-1);
18235 }
18236 /*
18237 * Parse the value; we will assume an even number of values
18238 * to be given (this is how Xerces and XSV work).
18239 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018240 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018241 cur = value;
18242 do {
18243 if (noNamespace != 1) {
18244 /*
18245 * Get the namespace name.
18246 */
18247 while (IS_BLANK_CH(*cur))
18248 cur++;
18249 end = cur;
18250 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18251 end++;
18252 if (end == cur)
18253 break;
18254 count++;
18255 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
18256 cur = end;
18257 }
18258 /*
18259 * Get the URI.
18260 */
18261 while (IS_BLANK_CH(*cur))
18262 cur++;
18263 end = cur;
18264 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18265 end++;
18266 if (end == cur)
18267 break;
18268 count++;
18269 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018270 cur = end;
18271 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018272 xsiAttr->parent, nsname, location);
18273 if (ret == -1) {
18274 xmlSchemaVCustomErr(vctxt,
18275 XML_SCHEMAV_INTERNAL,
18276 (xmlNodePtr) xsiAttr, NULL,
18277 "Internal error: xmlSchemaAssembleByXSIAttr, "
18278 "assembling schemata", NULL);
18279 if (value != NULL)
18280 xmlFree(value);
18281 return (-1);
18282 }
18283 } while (*cur != 0);
18284 if (value != NULL)
18285 xmlFree(value);
18286 return (ret);
18287}
18288
18289/**
18290 * xmlSchemaAssembleByXSIElem:
18291 * @vctxt: a schema validation context
18292 * @elem: an element node possibly holding xsi attributes
18293 * @noNamespace: whether a schema with no target namespace is exptected
18294 *
18295 * Assembles an existing schema by an additional schema using
18296 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
18297 * of the given @elem.
18298 *
18299 * Returns 0 if the new schema is correct, a positive error code
18300 * number otherwise and -1 in case of an internal or API error.
18301 */
18302static int
18303xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
18304 xmlNodePtr elem)
18305{
18306 int ret = 0, retNs = 0;
18307 xmlAttrPtr attr;
18308
18309 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
18310 if (attr != NULL) {
18311 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
18312 if (retNs == -1)
18313 return (-1);
18314 }
18315 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
18316 if (attr != NULL) {
18317 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
18318 if (ret == -1)
18319 return (-1);
18320 }
18321 if (retNs != 0)
18322 return (retNs);
18323 else
18324 return (ret);
18325}
18326
Daniel Veillard4255d502002-04-16 15:50:10 +000018327/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018328 * xmlSchemaValidateCallback:
18329 * @ctxt: a schema validation context
18330 * @name: the name of the element detected (might be NULL)
18331 * @type: the type
18332 *
18333 * A transition has been made in the automata associated to an element
18334 * content model
18335 */
18336static void
18337xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018338 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018339 xmlSchemaBasicItemPtr item, xmlNodePtr node)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018340{
Daniel Veillard4255d502002-04-16 15:50:10 +000018341 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018342
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018343 /*
18344 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
18345 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018346 ctxt->node = node;
18347 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018348
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018349 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018350
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018351 /*
18352 * Assemble new schemata using xsi.
18353 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018354 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018355 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018356
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018357 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18358 if (ret == -1) {
18359 xmlSchemaVCustomErr(ctxt,
18360 XML_SCHEMAV_INTERNAL,
18361 ctxt->node, NULL,
18362 "Internal error: xmlSchemaValidateElement, "
18363 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018364 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365 }
18366 /*
18367 * NOTE: We won't react on schema parser errors here.
18368 * TODO: But a warning would be nice.
18369 */
18370 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018371 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018372 case XML_SCHEMA_TYPE_ELEMENT: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018373#ifdef DEBUG_CONTENT
18374 xmlGenericError(xmlGenericErrorContext,
18375 "xmlSchemaValidateCallback: %s, %s, %s\n",
18376 name, ((xmlSchemaElementPtr) item)->name, node->name);
18377#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018378 xmlSchemaValidateElementByDeclaration(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018379 (xmlSchemaElementPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018380 break;
18381 }
18382 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018383#ifdef DEBUG_CONTENT
18384 xmlGenericError(xmlGenericErrorContext,
18385 "xmlSchemaValidateCallback: %s, <any>, %s\n",
18386 name, node->name);
18387#endif
18388 xmlSchemaValidateElementByWildcard(ctxt,
18389 (xmlSchemaWildcardPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018390 break;
18391 default:
18392 break;
18393 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018394leave:
18395
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018396 xmlSchemaEndElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000018397 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018398}
Daniel Veillard4255d502002-04-16 15:50:10 +000018399
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018400static int
18401xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18402 const xmlChar *value,
18403 xmlSchemaValPtr *val,
18404 xmlNodePtr node)
18405{
18406 int ret;
18407
18408 ret = xmlValidateQName(value, 1);
18409 if (ret != 0)
18410 return (ret);
18411
18412 {
18413 xmlChar *uri = NULL;
18414 xmlChar *local = NULL;
18415 xmlChar *prefix;
18416
18417 local = xmlSplitQName2(value, &prefix);
18418 if (prefix != NULL) {
18419 xmlNsPtr ns;
18420
18421 /*
18422 * TODO: Make this streamable.
18423 */
18424 if ((node == NULL) || (node->doc == NULL)) {
18425 xmlFree(prefix);
18426 xmlFree(local);
18427 return (3);
18428 }
18429
18430 ns = xmlSearchNs(node->doc, node, prefix);
18431 if (ns == NULL) {
18432 xmlFree(prefix);
18433 xmlFree(local);
18434 return (1);
18435 }
18436 }
18437 if (prefix != NULL) {
18438 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
18439 ret = 1;
18440 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
18441 NULL) == NULL)
18442 ret = 1;
18443
18444 if ((ret == 0) && (val != NULL)) {
18445 if (prefix != NULL) {
18446 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
18447 BAD_CAST xmlStrdup(uri));
18448 local = NULL;
18449 } else
18450 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
18451 NULL);
18452 if (*val == NULL)
18453 ret = -1;
18454 }
18455 if (local != NULL)
18456 xmlFree(local);
18457 }
18458
18459 return (ret);
18460}
18461
Daniel Veillard01fa6152004-06-29 17:04:39 +000018462/**
18463 * xmlSchemaValidateSimpleTypeValue:
18464 * @ctxt: a schema validation context
18465 * @value: the value to be validated
18466 * @fireErrors: shall errors be reported?
18467 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018468 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018469 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000018470 *
18471 * Validates a value by the given type (user derived or built-in).
18472 *
18473 * Returns 0 if the value is valid, a positive error code
18474 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000018475 */
18476static int
18477xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018478 xmlSchemaTypePtr type,
18479 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018480 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018481 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018482 int normalize,
18483 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018484{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018485 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018486 int ret = 0;
18487 xmlChar *normValue = NULL;
18488 int wtsp;
18489
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018490 node = ctxt->node;
18491 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018492 wtsp = ctxt->valueWS;
18493 /*
18494 * Normalize the value.
18495 */
18496 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018497 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018498 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
18499
18500 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018501 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018502 normValue = xmlSchemaCollapseString(value);
18503 else
18504 normValue = xmlSchemaWhiteSpaceReplace(value);
18505 ctxt->valueWS = norm;
18506 if (normValue != NULL)
18507 value = (const xmlChar *) normValue;
18508 }
18509 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018510 /*
18511 * The nodes of a content must be checked only once,
18512 * this is not working since list types will fire this
18513 * multiple times.
18514 */
18515 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
18516 xmlNodePtr cur = ctxt->cur;
18517
18518 do {
18519 switch (cur->type) {
18520 case XML_TEXT_NODE:
18521 case XML_CDATA_SECTION_NODE:
18522 case XML_PI_NODE:
18523 case XML_COMMENT_NODE:
18524 case XML_XINCLUDE_START:
18525 case XML_XINCLUDE_END:
18526 break;
18527 case XML_ENTITY_REF_NODE:
18528 case XML_ENTITY_NODE:
18529 /* TODO: Scour the entities for illegal nodes. */
18530 TODO break;
18531 case XML_ELEMENT_NODE: {
18532 /* NOTE: Changed to an internal error, since the
18533 * existence of an element node will be already checked in
18534 * xmlSchemaValidateElementBySimpleType and in
18535 * xmlSchemaValidateElementByComplexType.
18536 */
18537 xmlSchemaVCustomErr(ctxt,
18538 XML_SCHEMAV_INTERNAL,
18539 /* XML_SCHEMAS_ERR_INVALIDELEM, */
18540 node, type,
18541 "Element '%s' found in simple type content",
18542 cur->name);
18543 return (XML_SCHEMAV_INTERNAL);
18544 }
18545 case XML_ATTRIBUTE_NODE:
18546 case XML_DOCUMENT_NODE:
18547 case XML_DOCUMENT_TYPE_NODE:
18548 case XML_DOCUMENT_FRAG_NODE:
18549 case XML_NOTATION_NODE:
18550 case XML_HTML_DOCUMENT_NODE:
18551 case XML_DTD_NODE:
18552 case XML_ELEMENT_DECL:
18553 case XML_ATTRIBUTE_DECL:
18554 case XML_ENTITY_DECL:
18555 case XML_NAMESPACE_DECL:
18556#ifdef LIBXML_DOCB_ENABLED
18557 case XML_DOCB_DOCUMENT_NODE:
18558#endif
18559 xmlSchemaVCustomErr(ctxt,
18560 XML_SCHEMAV_INTERNAL,
18561 /* XML_SCHEMAS_ERR_INVALIDELEM, */
18562 node, NULL,
18563 "Node of unexpected type found in simple type content",
18564 NULL);
18565 return (XML_SCHEMAV_INTERNAL);
18566 }
18567 cur = cur->next;
18568 } while (cur != NULL);
18569 }
18570
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018571 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018572
18573 if (ctxt->value != NULL) {
18574 xmlSchemaFreeValue(ctxt->value);
18575 ctxt->value = NULL;
18576 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018577 /*
18578 * STREAM-READ-CHILDREN.
18579 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018580 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
18581 (ctxt->schema != NULL)) {
18582 /*
18583 * NOTATIONs need to be processed here, since they need
18584 * to lookup in the hashtable of NOTATION declarations.
18585 */
18586 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
18587 } else
18588 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018589 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018590 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
18591 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
18592 else
18593 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018594 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018595 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018596 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018597 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018598 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018599 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018600 } else if ((ctxt->value == NULL) &&
18601 (type->builtInType == XML_SCHEMAS_STRING) &&
18602 (ctxt->nodeInfo != NULL) &&
18603 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018604 xmlChar *valdup;
18605 /*
18606 * Create a precomputed string value for "string" as well if
18607 * requested.
18608 */
18609 valdup = xmlStrdup(value);
18610 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
18611 BAD_CAST valdup);
18612 if ((valdup != NULL) && (ctxt->value == NULL))
18613 xmlFree(valdup);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018614 }
18615 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
18616 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
18617 * a literal in the ·lexical space· of {base type definition}
18618 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018619 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018620 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018621 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018622 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018623 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018624 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018625 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018626 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018627 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018628 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018629 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018630 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018631 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018632 */
18633 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018634 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018635 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018636 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018637 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018638 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018639 type->name, NULL);
18640 } else if (ret > 0) {
18641 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018642 /*
18643 Disabled, since the facet validation already reports errors.
18644 if (fireErrors)
18645 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18646 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018647 }
18648 }
18649 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18650
18651 xmlSchemaTypePtr tmpType;
18652 const xmlChar *cur, *end;
18653 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018654 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018655
18656 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
18657 * of white space separated tokens, each of which ·match·es a literal
18658 * in the ·lexical space· of {item type definition}
18659 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000018660
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000018661 if (value == NULL)
18662 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000018663 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018664 cur = value;
18665 do {
18666 while (IS_BLANK_CH(*cur))
18667 cur++;
18668 end = cur;
18669 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18670 end++;
18671 if (end == cur)
18672 break;
18673 tmp = xmlStrndup(cur, end - cur);
18674 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018675 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018676 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018677 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018678 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018679 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18680 "validating an item of list simple type '%s'\n",
18681 type->name, NULL);
18682 break;
18683 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018684 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018685 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018686 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018687 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018688 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018689 cur = end;
18690 } while (*cur != 0);
18691 /*
18692 * Check facets.
18693 */
18694 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018695 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018696 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018697 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018698 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018699 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018700 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018701 value, len, fireErrors);
18702 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018703 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018704 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18705 "validating facets of list simple type '%s'\n",
18706 type->name, NULL);
18707 } else if (ret > 0) {
18708 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018709 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018710 Disabled, since the facet validation already reports errors.
18711 if (fireErrors)
18712 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018713 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018714 }
18715
Daniel Veillard01fa6152004-06-29 17:04:39 +000018716 }
18717 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
18718 xmlSchemaTypeLinkPtr memberLink;
18719
18720 /*
18721 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
18722 * not apply directly; however, the normalization behavior of ·union·
18723 * types is controlled by the value of whiteSpace on that one of the
18724 * ·memberTypes· against which the ·union· is successfully validated.
18725 *
18726 * This means that the value is normalized by the first validating
18727 * member type, then the facets of the union type are applied. This
18728 * needs changing of the value!
18729 */
18730
18731 /*
18732 * 1.2.3 if {variety} is ·union· then the string must ·match· a
18733 * literal in the ·lexical space· of at least one member of
18734 * {member type definitions}
18735 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018736#ifdef DEBUG_UNION_VALIDATION
18737 printf("Union ST : '%s'\n", (const char *) type->name);
18738 printf(" fireErrors : %d\n", fireErrors);
18739 printf(" applyFacets: %d\n", applyFacets);
18740#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000018741 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
18742 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018743 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018744 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018745 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018746 type->name, NULL);
18747 ret = -1;
18748 }
18749 if (ret == 0) {
18750 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018751 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
18752 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018753 if ((ret <= 0) || (ret == 0))
18754 break;
18755 memberLink = memberLink->next;
18756 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018757 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018758 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018759 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018760 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018761 type->name, NULL);
18762 } else if (ret > 0) {
18763 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018764 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018765 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018766 }
18767 }
18768 /*
18769 * Apply facets (pattern, enumeration).
18770 */
18771 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
18772 int mws;
18773 /*
18774 * The normalization behavior of ·union· types is controlled by
18775 * the value of whiteSpace on that one of the ·memberTypes·
18776 * against which the ·union· is successfully validated.
18777 */
18778 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018779 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018780 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18781 "the value was already normalized for the union simple "
18782 "type '%s'.\n", type->name, NULL);
18783 }
18784 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
18785 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018786 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018787 normValue = xmlSchemaCollapseString(value);
18788 else
18789 normValue = xmlSchemaWhiteSpaceReplace(value);
18790 if (normValue != NULL)
18791 value = (const xmlChar *) normValue;
18792 }
18793
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018794 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018795 value, 0, fireErrors);
18796 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018797 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018798 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18799 "validating facets of union simple type '%s'\n",
18800 type->name, NULL);
18801 } else if (ret > 0) {
18802 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
18803 /*
18804 if (fireErrors)
18805 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18806 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018807 }
18808 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018809 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018810 ctxt->valueWS = wtsp;
18811 if (normValue != NULL)
18812 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018813 return (ret);
18814}
18815
18816/**
18817 * xmlSchemaValidateSimpleTypeElement:
18818 * @ctxt: a schema validation context
18819 * @node: the element node to be validated.
18820 *
18821 * Validate the element against a simple type.
18822 *
18823 * Returns 0 if the element is valid, a positive error code
18824 * number otherwise and -1 in case of an internal or API error.
18825 */
18826static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018827xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018828 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018829 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018830 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018831{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018832 xmlSchemaTypePtr oldtype;
18833 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018834 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018835 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018836 int ret = 0, retval = 0;
18837
Daniel Veillard01fa6152004-06-29 17:04:39 +000018838 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018839 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
18840 "Internal error: xmlSchemaValidateElementBySimpleType, "
18841 "bad arguments", NULL);
18842 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018843 }
18844
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018845 oldtype = ctxt->type;
18846 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018847 /*
18848 * cvc-type: 3.1.2 The element information item must have no element
18849 * information item [children].
18850 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018851 /*
18852 * STREAM: Child nodes are processed.
18853 */
18854 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018855 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018856 /*
18857 * TODO: Entities, will they produce elements as well?
18858 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018859 if (cur->type == XML_ELEMENT_NODE) {
18860 xmlSchemaVCustomErr(ctxt,
18861 XML_SCHEMAV_CVC_TYPE_3_1_2,
18862 node, type,
18863 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018864 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018865 }
18866 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018867 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018868
Daniel Veillard01fa6152004-06-29 17:04:39 +000018869 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018870 * cvc-type 3.1.1:
18871 *
18872 * The attributes of must be empty, excepting those whose namespace name
18873 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
18874 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018875 */
18876 /*
18877 * STREAM: Attribute nodes are processed.
18878 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018879 attr = node->properties;
18880 while (attr != NULL) {
18881 if ((attr->ns == NULL) ||
18882 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
18883 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
18884 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
18885 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
18886 (!xmlStrEqual
18887 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018888 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018889 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
18890 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018891 }
18892 attr = attr->next;
18893 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018894 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018895 * This will skip validation if the type is 'anySimpleType' and
18896 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018897 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018898 if ((! isNil) &&
18899 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018900 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
18901 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018902 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018903
18904 value = xmlNodeGetContent(node);
18905 /*
18906 * NOTE: This call will not check the content nodes, since
18907 * this should be checked here already.
18908 */
18909 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
18910 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018911 if (value != NULL)
18912 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018913 if (retval != 0)
18914 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000018915 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018916 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018917 return (ret);
18918}
Daniel Veillard4255d502002-04-16 15:50:10 +000018919
18920/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018921 * xmlSchemaValQNameAcquire:
18922 * @value: the lexical represantation of the QName value
18923 * @node: the node to search for the corresponding namespace declaration
18924 * @nsName: the resulting namespace name if found
18925 *
18926 * Checks that a value conforms to the lexical space of the type QName;
18927 * if valid, the corresponding namespace name is searched and retured
18928 * as a copy in @nsName. The local name is returned in @localName as
18929 * a copy.
18930 *
18931 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
18932 * namespace declaration was found in scope; -1 in case of an internal or
18933 * API error.
18934 */
18935static int
18936xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
18937 xmlChar **nsName, xmlChar **localName)
18938{
18939 int ret;
18940 xmlChar *local = NULL;
18941
18942 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
18943 return (-1);
18944 *nsName = NULL;
18945 *localName = NULL;
18946 ret = xmlValidateQName(value, 1);
18947 if (ret == 0) {
18948 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018949 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018950
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018951 /*
18952 * NOTE: xmlSplitQName2 will return a duplicated
18953 * string.
18954 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018955 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018956 if (local == NULL)
18957 local = xmlStrdup(value);
18958 ns = xmlSearchNs(node->doc, node, prefix);
18959 /*
18960 * A namespace need not to be found if the prefix is NULL.
18961 */
18962 if (ns != NULL) {
18963 /*
18964 * TODO: Is it necessary to duplicate the URI here?
18965 */
18966 *nsName = xmlStrdup(ns->href);
18967 } else if (prefix != NULL) {
18968 xmlFree(prefix);
18969 if (local != NULL)
18970 xmlFree(local);
18971 return (2);
18972 }
18973 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018974 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018975 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018976 } else
18977 return (1);
18978 return (ret);
18979}
18980
18981/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018982 * xmlSchemaHasElemContent:
18983 * @node: the node
18984 *
18985 * Scours the content of the given node for element
18986 * nodes.
18987 *
18988 * Returns 1 if an element node is found,
18989 * 0 otherwise.
18990 */
18991static int
18992xmlSchemaHasElemContent(xmlNodePtr node)
18993{
18994 if (node == NULL)
18995 return (0);
18996 node = node->children;
18997 while (node != NULL) {
18998 if (node->type == XML_ELEMENT_NODE)
18999 return (1);
19000 node = node->next;
19001 }
19002 return (0);
19003}
19004/**
19005 * xmlSchemaHasElemOrCharContent:
19006 * @node: the node
19007 *
19008 * Scours the content of the given node for element
19009 * and character nodes.
19010 *
19011 * Returns 1 if an element or character node is found,
19012 * 0 otherwise.
19013 */
19014static int
19015xmlSchemaHasElemOrCharContent(xmlNodePtr node)
19016{
19017 if (node == NULL)
19018 return (0);
19019 node = node->children;
19020 while (node != NULL) {
19021 switch (node->type) {
19022 case XML_ELEMENT_NODE:
19023 /*
19024 * TODO: Ask Daniel if these are all character nodes.
19025 */
19026 case XML_TEXT_NODE:
19027 case XML_CDATA_SECTION_NODE:
19028 /*
19029 * TODO: How XML_ENTITY_NODEs evaluated?
19030 */
19031 case XML_ENTITY_REF_NODE:
19032 case XML_ENTITY_NODE:
19033 return (1);
19034 break;
19035 default:
19036 break;
19037 }
19038 node = node->next;
19039 }
19040 return (0);
19041}
19042
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019043/************************************************************************
19044 * *
19045 * Identity-constraints (IDC) *
19046 * *
19047 ************************************************************************/
19048
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019049/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019050 * xmlSchemaAugmentIDC:
19051 * @idcDef: the IDC definition
19052 *
19053 * Creates an augmented IDC definition item.
19054 *
19055 * Returns the item, or NULL on internal errors.
19056 */
19057static void
19058xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
19059 xmlSchemaValidCtxtPtr vctxt)
19060{
19061 xmlSchemaIDCAugPtr aidc;
19062
19063 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
19064 if (aidc == NULL) {
19065 xmlSchemaVErrMemory(vctxt,
19066 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
19067 NULL);
19068 return;
19069 }
19070 aidc->bubbleDepth = -1;
19071 aidc->def = idcDef;
19072 aidc->next = NULL;
19073 if (vctxt->aidcs == NULL)
19074 vctxt->aidcs = aidc;
19075 else {
19076 aidc->next = vctxt->aidcs;
19077 vctxt->aidcs = aidc;
19078 }
19079}
19080
19081/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019082 * xmlSchemaIDCNewBinding:
19083 * @idcDef: the IDC definition of this binding
19084 *
19085 * Creates a new IDC binding.
19086 *
19087 * Returns the new binding in case of succeeded, NULL on internal errors.
19088 */
19089static xmlSchemaPSVIIDCBindingPtr
19090xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
19091{
19092 xmlSchemaPSVIIDCBindingPtr ret;
19093
19094 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
19095 sizeof(xmlSchemaPSVIIDCBinding));
19096 if (ret == NULL) {
19097 xmlSchemaVErrMemory(NULL,
19098 "allocating a PSVI IDC binding item", NULL);
19099 return (NULL);
19100 }
19101 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
19102 ret->definition = idcDef;
19103 return (ret);
19104}
19105
19106/**
19107 * xmlSchemaIDCStoreNodeTableItem:
19108 * @vctxt: the WXS validation context
19109 * @item: the IDC node table item
19110 *
19111 * The validation context is used to store an IDC node table items.
19112 * They are stored to avoid copying them if IDC node-tables are merged
19113 * with corresponding parent IDC node-tables (bubbling).
19114 *
19115 * Returns 0 if succeeded, -1 on internal errors.
19116 */
19117static int
19118xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
19119 xmlSchemaPSVIIDCNodePtr item)
19120{
19121 /*
19122 * Add to gobal list.
19123 */
19124 if (vctxt->idcNodes == NULL) {
19125 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19126 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
19127 if (vctxt->idcNodes == NULL) {
19128 xmlSchemaVErrMemory(vctxt,
19129 "allocating the IDC node table item list", NULL);
19130 return (-1);
19131 }
19132 vctxt->sizeIdcNodes = 20;
19133 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
19134 vctxt->sizeIdcNodes *= 2;
19135 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19136 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
19137 sizeof(xmlSchemaPSVIIDCNodePtr));
19138 if (vctxt->idcNodes == NULL) {
19139 xmlSchemaVErrMemory(vctxt,
19140 "re-allocating the IDC node table item list", NULL);
19141 return (-1);
19142 }
19143 }
19144 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
19145
19146 return (0);
19147}
19148
19149/**
19150 * xmlSchemaIDCStoreKey:
19151 * @vctxt: the WXS validation context
19152 * @item: the IDC key
19153 *
19154 * The validation context is used to store an IDC key.
19155 *
19156 * Returns 0 if succeeded, -1 on internal errors.
19157 */
19158static int
19159xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
19160 xmlSchemaPSVIIDCKeyPtr key)
19161{
19162 /*
19163 * Add to gobal list.
19164 */
19165 if (vctxt->idcKeys == NULL) {
19166 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19167 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
19168 if (vctxt->idcKeys == NULL) {
19169 xmlSchemaVErrMemory(vctxt,
19170 "allocating the IDC key storage list", NULL);
19171 return (-1);
19172 }
19173 vctxt->sizeIdcKeys = 40;
19174 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
19175 vctxt->sizeIdcKeys *= 2;
19176 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19177 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
19178 sizeof(xmlSchemaPSVIIDCKeyPtr));
19179 if (vctxt->idcKeys == NULL) {
19180 xmlSchemaVErrMemory(vctxt,
19181 "re-allocating the IDC key storage list", NULL);
19182 return (-1);
19183 }
19184 }
19185 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
19186
19187 return (0);
19188}
19189
19190/**
19191 * xmlSchemaIDCAppendNodeTableItem:
19192 * @bind: the IDC binding
19193 * @ntItem: the node-table item
19194 *
19195 * Appends the IDC node-table item to the binding.
19196 *
19197 * Returns 0 on success and -1 on internal errors.
19198 */
19199static int
19200xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19201 xmlSchemaPSVIIDCNodePtr ntItem)
19202{
19203 if (bind->nodeTable == NULL) {
19204 bind->sizeNodes = 10;
19205 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19206 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19207 if (bind->nodeTable == NULL) {
19208 xmlSchemaVErrMemory(NULL,
19209 "allocating an array of IDC node-table items", NULL);
19210 return(-1);
19211 }
19212 } else if (bind->sizeNodes <= bind->nbNodes) {
19213 bind->sizeNodes *= 2;
19214 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19215 xmlRealloc(bind->nodeTable, bind->sizeNodes *
19216 sizeof(xmlSchemaPSVIIDCNodePtr));
19217 if (bind->nodeTable == NULL) {
19218 xmlSchemaVErrMemory(NULL,
19219 "re-allocating an array of IDC node-table items", NULL);
19220 return(-1);
19221 }
19222 }
19223 bind->nodeTable[bind->nbNodes++] = ntItem;
19224 return(0);
19225}
19226
19227/**
19228 * xmlSchemaIDCAquireBinding:
19229 * @vctxt: the WXS validation context
19230 * @matcher: the IDC matcher
19231 *
19232 * Looks up an PSVI IDC binding, for the IDC definition and
19233 * of the given matcher. If none found, a new one is created
19234 * and added to the IDC table.
19235 *
19236 * Returns an IDC binding or NULL on internal errors.
19237 */
19238static xmlSchemaPSVIIDCBindingPtr
19239xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19240 xmlSchemaIDCMatcherPtr matcher)
19241{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019242 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019243
19244 info = vctxt->elemInfos[matcher->depth];
19245
19246 if (info->idcTable == NULL) {
19247 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19248 if (info->idcTable == NULL)
19249 return (NULL);
19250 return(info->idcTable);
19251 } else {
19252 xmlSchemaPSVIIDCBindingPtr bind = NULL;
19253
19254 bind = info->idcTable;
19255 do {
19256 if (bind->definition == matcher->aidc->def)
19257 return(bind);
19258 if (bind->next == NULL) {
19259 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19260 if (bind->next == NULL)
19261 return (NULL);
19262 return(bind->next);
19263 }
19264 bind = bind->next;
19265 } while (bind != NULL);
19266 }
19267 return (NULL);
19268}
19269
19270/**
19271 * xmlSchemaIDCFreeKey:
19272 * @key: the IDC key
19273 *
19274 * Frees an IDC key together with its compiled value.
19275 */
19276static void
19277xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19278{
19279 if (key->compValue != NULL)
19280 xmlSchemaFreeValue(key->compValue);
19281 xmlFree(key);
19282}
19283
19284/**
19285 * xmlSchemaIDCFreeBinding:
19286 *
19287 * Frees an IDC binding. Note that the node table-items
19288 * are not freed.
19289 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019290static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019291xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19292{
19293 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019294 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19295 int i;
19296 /*
19297 * Node-table items for keyrefs are not stored globally
19298 * to the validation context, since they are not bubbled.
19299 * We need to free them here.
19300 */
19301 for (i = 0; i < bind->nbNodes; i++) {
19302 xmlFree(bind->nodeTable[i]->keys);
19303 xmlFree(bind->nodeTable[i]);
19304 }
19305 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019306 xmlFree(bind->nodeTable);
19307 }
19308 xmlFree(bind);
19309}
19310
19311/**
19312 * xmlSchemaIDCFreeIDCTable:
19313 * @bind: the first IDC binding in the list
19314 *
19315 * Frees an IDC table, i.e. all the IDC bindings in the list.
19316 */
19317static void
19318xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19319{
19320 xmlSchemaPSVIIDCBindingPtr prev;
19321
19322 while (bind != NULL) {
19323 prev = bind;
19324 bind = bind->next;
19325 xmlSchemaIDCFreeBinding(prev);
19326 }
19327}
19328
19329/**
19330 * xmlSchemaIDCFreeMatcherList:
19331 * @matcher: the first IDC matcher in the list
19332 *
19333 * Frees a list of IDC matchers.
19334 */
19335static void
19336xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19337{
19338 xmlSchemaIDCMatcherPtr next;
19339
19340 while (matcher != NULL) {
19341 next = matcher->next;
19342 if (matcher->keySeqs != NULL) {
19343 int i;
19344 for (i = 0; i < matcher->sizeKeySeqs; i++)
19345 if (matcher->keySeqs[i] != NULL)
19346 xmlFree(matcher->keySeqs[i]);
19347 xmlFree(matcher->keySeqs);
19348 }
19349 xmlFree(matcher);
19350 matcher = next;
19351 }
19352}
19353
19354/**
19355 * xmlSchemaAreValuesEqual:
19356 * @ta: the first type
19357 * @a: the first value
19358 * @tb: the second type
19359 * @b: the second value
19360 *
19361 * Compares two values.
19362 *
19363 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
19364 */
19365static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019366xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
19367 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019368 xmlSchemaValPtr a,
19369 xmlSchemaTypePtr tb,
19370 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019371{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019372 /* Same user derived/built-in derived/built-in primitive types. */
19373 if (ta == tb)
19374 goto compareValue;
19375
19376 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019377 * Note that comparison with anySimpleTypes with be supported for
19378 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019379 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019380#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019381 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
19382 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19383 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019384#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019385
19386 /*
19387 * 4.2.1 equal (data-types)
19388 *
19389 * the ·value space·s of all ·primitive· datatypes are disjoint
19390 * (they do not share any values)
19391 */
19392 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
19393 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
19394 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
19395 return(0);
19396
19397 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19398 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
19399 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19400 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
19401 TODO
19402 return(0);
19403 }
19404 /*
19405 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
19406 * T then the ·value space· of T' is a subset of the ·value space· of T.
19407 */
19408 /*
19409 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
19410 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
19411 */
19412
19413 {
19414 xmlSchemaTypePtr pta = ta, ptb = tb;
19415
19416 /* Note that we will compare the primitives here. */
19417 while ((pta->builtInType == 0) ||
19418 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19419 pta = pta->baseType;
19420 while ((ptb->builtInType == 0) ||
19421 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19422 ptb = ptb->baseType;
19423 if (pta == ptb)
19424 goto compareValue;
19425 return(0);
19426 }
19427compareValue:
19428 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019429 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019430 int aws, bws;
19431
19432 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
19433 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
19434
19435 ret = xmlSchemaCompareValuesWhtsp(
19436 a, (xmlSchemaWhitespaceValueType) aws,
19437 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019438 if (ret == 0)
19439 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019440 else if (ret == -2) {
19441 xmlSchemaVErr(vctxt, vctxt->node,
19442 XML_SCHEMAV_INTERNAL,
19443 "Internal error: xmlSchemaAreValuesEqual, "
19444 "failed to compare the values.\n",
19445 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019446 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019447 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019448 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019449 }
19450}
19451
19452/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019453 * xmlSchemaIDCAddStateObject:
19454 * @vctxt: the WXS validation context
19455 * @matcher: the IDC matcher
19456 * @sel: the XPath information
19457 * @parent: the parent "selector" state object if any
19458 * @type: "selector" or "field"
19459 *
19460 * Creates/reuses and activates state objects for the given
19461 * XPath information; if the XPath expression consists of unions,
19462 * multiple state objects are created for every unioned expression.
19463 *
19464 * Returns 0 on success and -1 on internal errors.
19465 */
19466static int
19467xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19468 xmlSchemaIDCMatcherPtr matcher,
19469 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019470 int type)
19471{
19472 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019473
19474 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019475 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019476 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019477 if (vctxt->xpathStatePool != NULL) {
19478 sto = vctxt->xpathStatePool;
19479 vctxt->xpathStatePool = sto->next;
19480 sto->next = NULL;
19481 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019482 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019483 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019484 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019485 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19486 if (sto == NULL) {
19487 xmlSchemaVErrMemory(NULL,
19488 "allocating an IDC state object", NULL);
19489 return (-1);
19490 }
19491 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19492 }
19493 /*
19494 * Add to global list.
19495 */
19496 if (vctxt->xpathStates != NULL)
19497 sto->next = vctxt->xpathStates;
19498 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019499
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019500 /*
19501 * Free the old xpath validation context.
19502 */
19503 if (sto->xpathCtxt != NULL)
19504 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19505
19506 /*
19507 * Create a new XPath (pattern) validation context.
19508 */
19509 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19510 (xmlPatternPtr) sel->xpathComp);
19511 if (sto->xpathCtxt == NULL) {
19512 xmlSchemaVErr(vctxt, vctxt->node,
19513 XML_SCHEMAV_INTERNAL,
19514 "Internal error: xmlSchemaIDCAddStateObject, "
19515 "failed to create the XPath validation context.\n",
19516 NULL, NULL);
19517 return (-1);
19518 }
19519 sto->type = type;
19520 sto->depth = vctxt->depth;
19521 sto->matcher = matcher;
19522 sto->sel = sel;
19523 sto->nbHistory = 0;
19524
19525#if DEBUG_IDC
19526 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19527 sto->sel->xpath);
19528#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019529 return (0);
19530}
19531
19532/**
19533 * xmlSchemaXPathEvaluate:
19534 * @vctxt: the WXS validation context
19535 * @nodeType: the nodeType of the current node
19536 *
19537 * Evaluates all active XPath state objects.
19538 *
19539 * Returns the number of IC "field" state objects which resolved to
19540 * this node, 0 if none resolved and -1 on internal errors.
19541 */
19542static int
19543xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019544 xmlElementType nodeType)
19545{
19546 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019547 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019548
19549 if (vctxt->xpathStates == NULL)
19550 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019551
19552 if (nodeType == XML_ATTRIBUTE_NODE)
19553 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019554#if DEBUG_IDC
19555 {
19556 xmlChar *str = NULL;
19557 xmlGenericError(xmlGenericErrorContext,
19558 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019559 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19560 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019561 FREE_AND_NULL(str)
19562 }
19563#endif
19564 /*
19565 * Process all active XPath state objects.
19566 */
19567 first = vctxt->xpathStates;
19568 sto = first;
19569 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019570#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019571 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019572 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19573 sto->matcher->aidc->def->name, sto->sel->xpath);
19574 else
19575 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19576 sto->matcher->aidc->def->name, sto->sel->xpath);
19577#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019578 if (nodeType == XML_ELEMENT_NODE)
19579 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
19580 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
19581 else
19582 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
19583 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
19584
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019585 if (res == -1) {
19586 xmlSchemaVErr(vctxt, vctxt->node,
19587 XML_SCHEMAV_INTERNAL,
19588 "Internal error: xmlSchemaXPathEvaluate, "
19589 "failed to evaluate a node.\n",
19590 NULL, NULL);
19591 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019592 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019593 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019594 goto next_sto;
19595 /*
19596 * Full match.
19597 */
19598#if DEBUG_IDC
19599 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019600 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019601#endif
19602 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019603 * Register a match in the state object history.
19604 */
19605 if (sto->history == NULL) {
19606 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19607 if (sto->history == NULL) {
19608 xmlSchemaVErrMemory(NULL,
19609 "allocating the state object history", NULL);
19610 return(-1);
19611 }
19612 sto->sizeHistory = 10;
19613 } else if (sto->sizeHistory <= sto->nbHistory) {
19614 sto->sizeHistory *= 2;
19615 sto->history = (int *) xmlRealloc(sto->history,
19616 sto->sizeHistory * sizeof(int));
19617 if (sto->history == NULL) {
19618 xmlSchemaVErrMemory(NULL,
19619 "re-allocating the state object history", NULL);
19620 return(-1);
19621 }
19622 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019623 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019624
19625#ifdef DEBUG_IDC
19626 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19627 vctxt->depth);
19628#endif
19629
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019630 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19631 xmlSchemaIDCSelectPtr sel;
19632 /*
19633 * Activate state objects for the IDC fields of
19634 * the IDC selector.
19635 */
19636#if DEBUG_IDC
19637 xmlGenericError(xmlGenericErrorContext, "IDC: "
19638 "activating field states\n");
19639#endif
19640 sel = sto->matcher->aidc->def->fields;
19641 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019642 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19643 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19644 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019645 sel = sel->next;
19646 }
19647 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19648 /*
19649 * An IDC key node was found.
19650 */
19651#if DEBUG_IDC
19652 xmlGenericError(xmlGenericErrorContext,
19653 "IDC: key found\n");
19654#endif
19655 /*
19656 * Notify that the character value of this node is
19657 * needed.
19658 */
19659 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019660 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019661 resolved++;
19662 }
19663next_sto:
19664 if (sto->next == NULL) {
19665 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019666 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019667 */
19668 head = first;
19669 sto = vctxt->xpathStates;
19670 } else
19671 sto = sto->next;
19672 }
19673 return (resolved);
19674}
19675
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019676static const xmlChar *
19677xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr ctxt,
19678 xmlChar **buf,
19679 xmlSchemaPSVIIDCKeyPtr *seq,
19680 int count)
19681{
19682 int i, res;
19683 const xmlChar *value = NULL;
19684
19685 *buf = xmlStrdup(BAD_CAST "[");
19686 for (i = 0; i < count; i++) {
19687 *buf = xmlStrcat(*buf, BAD_CAST "'");
19688 res = xmlSchemaGetCanonValueWhtsp(seq[i]->compValue, &value,
19689 (xmlSchemaWhitespaceValueType)
19690 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
19691 if (res == 0)
19692 *buf = xmlStrcat(*buf, value);
19693 else {
19694 xmlSchemaVErr(ctxt, ctxt->node,
19695 XML_SCHEMAV_INTERNAL,
19696 "Internal error: xmlSchemaFormatIDCKeySequence, "
19697 "failed to compute canonical value.\n",
19698 NULL, NULL);
19699 *buf = xmlStrcat(*buf, BAD_CAST "???");
19700 }
19701 if (i < count -1)
19702 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19703 else
19704 *buf = xmlStrcat(*buf, BAD_CAST "'");
19705 if (value != NULL) {
19706 xmlFree((xmlChar *) value);
19707 value = NULL;
19708 }
19709 }
19710 *buf = xmlStrcat(*buf, BAD_CAST "]");
19711
19712 return (BAD_CAST *buf);
19713}
19714
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019715/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019716 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019717 * @vctxt: the WXS validation context
19718 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019719 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019720 *
19721 * Processes and pops the history items of the IDC state objects.
19722 * IDC key-sequences are validated/created on IDC bindings.
19723 *
19724 * Returns 0 on success and -1 on internal errors.
19725 */
19726static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019727xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019728 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019729{
19730 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019731 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019732 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019733 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019734
19735 if (vctxt->xpathStates == NULL)
19736 return (0);
19737 sto = vctxt->xpathStates;
19738
19739#if DEBUG_IDC
19740 {
19741 xmlChar *str = NULL;
19742 xmlGenericError(xmlGenericErrorContext,
19743 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019744 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19745 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019746 FREE_AND_NULL(str)
19747 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019748#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019749 /*
19750 * Evaluate the state objects.
19751 */
19752 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019753 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019754#if DEBUG_IDC
19755 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19756 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019757#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019758 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019759 goto deregister_check;
19760
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019761 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019762
19763 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019764 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019765 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019766 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019767 sto = sto->next;
19768 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019769 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019770 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19771 if (! IS_SIMPLE_TYPE(type)) {
19772 /*
19773 * Not qualified if the field resolves to a node of non
19774 * simple type.
19775 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019776 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019777 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019778 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019779 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19780 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019781 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019782
19783 sto->nbHistory--;
19784 goto deregister_check;
19785 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019786 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019787 /*
19788 * Failed to provide the normalized value; maby
19789 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019790 */
19791 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019792 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019793 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019794 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19795 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019796 "was either invalid or something strange happend",
19797 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019798 /*
19799 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019800 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019801 "Internal error: xmlSchemaXPathProcessHistory, "
19802 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019803 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019804 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019805 sto->nbHistory--;
19806 goto deregister_check;
19807 } else {
19808 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19809 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019810 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019811
19812 /*
19813 * The key will be anchored on the matcher's list of
19814 * key-sequences. The position in this list is determined
19815 * by the target node's depth relative to the matcher's
19816 * depth of creation (i.e. the depth of the scope element).
19817 */
19818 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019819 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019820
19821 /*
19822 * Create/grow the array of key-sequences.
19823 */
19824 if (matcher->keySeqs == NULL) {
19825 if (pos > 9)
19826 matcher->sizeKeySeqs = pos * 2;
19827 else
19828 matcher->sizeKeySeqs = 10;
19829 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19830 xmlMalloc(matcher->sizeKeySeqs *
19831 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19832 if (matcher->keySeqs == NULL) {
19833 xmlSchemaVErrMemory(NULL,
19834 "allocating an array of key-sequences",
19835 NULL);
19836 return(-1);
19837 }
19838 memset(matcher->keySeqs, 0,
19839 matcher->sizeKeySeqs *
19840 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19841 } else if (pos >= matcher->sizeKeySeqs) {
19842 int i = matcher->sizeKeySeqs;
19843
19844 matcher->sizeKeySeqs *= 2;
19845 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19846 xmlRealloc(matcher->keySeqs,
19847 matcher->sizeKeySeqs *
19848 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019849 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019850 xmlSchemaVErrMemory(NULL,
19851 "reallocating an array of key-sequences",
19852 NULL);
19853 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019854 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019855 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019856 * The array needs to be NULLed.
19857 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019858 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019859 for (; i < matcher->sizeKeySeqs; i++)
19860 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019861 }
19862
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019863 /*
19864 * Get/create the key-sequence.
19865 */
19866 keySeq = matcher->keySeqs[pos];
19867 if (keySeq == NULL) {
19868 goto create_sequence;
19869 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019870 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019871 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019872 * cvc-identity-constraint:
19873 * 3 For each node in the ·target node set· all
19874 * of the {fields}, with that node as the context
19875 * node, evaluate to either an empty node-set or
19876 * a node-set with exactly one member, which must
19877 * have a simple type.
19878 *
19879 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019880 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019881 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019882 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019883 vctxt->nodeInfo,
19884 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019885 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019886 "with more than one member",
19887 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019888 sto->nbHistory--;
19889 goto deregister_check;
19890 } else {
19891 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019892 }
19893 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019894
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019895create_sequence:
19896 /*
19897 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019898 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019899 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19900 matcher->aidc->def->nbFields *
19901 sizeof(xmlSchemaPSVIIDCKeyPtr));
19902 if (keySeq == NULL) {
19903 xmlSchemaVErrMemory(NULL,
19904 "allocating an IDC key-sequence", NULL);
19905 return(-1);
19906 }
19907 memset(keySeq, 0, matcher->aidc->def->nbFields *
19908 sizeof(xmlSchemaPSVIIDCKeyPtr));
19909 matcher->keySeqs[pos] = keySeq;
19910create_key:
19911 /*
19912 * Created a key once per node only.
19913 */
19914 if (key == NULL) {
19915 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19916 sizeof(xmlSchemaPSVIIDCKey));
19917 if (key == NULL) {
19918 xmlSchemaVErrMemory(NULL,
19919 "allocating a IDC key", NULL);
19920 xmlFree(keySeq);
19921 matcher->keySeqs[pos] = NULL;
19922 return(-1);
19923 }
19924 /*
19925 * Consume the compiled value.
19926 */
19927 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019928 key->compValue = vctxt->nodeInfo->value;
19929 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019930 /*
19931 * Store the key in a global list.
19932 */
19933 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19934 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019935 return (-1);
19936 }
19937 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019938 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019939 }
19940 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019941
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019942 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19943 xmlSchemaPSVIIDCBindingPtr bind;
19944 xmlSchemaPSVIIDCNodePtr ntItem;
19945 xmlSchemaIDCMatcherPtr matcher;
19946 xmlSchemaIDCPtr idc;
19947 int pos, i, j, nbKeys;
19948 /*
19949 * Here we have the following scenario:
19950 * An IDC 'selector' state object resolved to a target node,
19951 * during the time this target node was in the
19952 * ancestor-or-self axis, the 'field' state object(s) looked
19953 * out for matching nodes to create a key-sequence for this
19954 * target node. Now we are back to this target node and need
19955 * to put the key-sequence, together with the target node
19956 * itself, into the node-table of the corresponding IDC
19957 * binding.
19958 */
19959 matcher = sto->matcher;
19960 idc = matcher->aidc->def;
19961 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019962 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019963 /*
19964 * Check if the matcher has any key-sequences at all, plus
19965 * if it has a key-sequence for the current target node.
19966 */
19967 if ((matcher->keySeqs == NULL) ||
19968 (matcher->sizeKeySeqs <= pos)) {
19969 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19970 goto selector_key_error;
19971 else
19972 goto selector_leave;
19973 }
19974
19975 keySeq = &(matcher->keySeqs[pos]);
19976 if (*keySeq == NULL) {
19977 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19978 goto selector_key_error;
19979 else
19980 goto selector_leave;
19981 }
19982
19983 for (i = 0; i < nbKeys; i++) {
19984 if ((*keySeq)[i] == NULL) {
19985 /*
19986 * Not qualified, if not all fields did resolve.
19987 */
19988 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19989 /*
19990 * All fields of a "key" IDC must resolve.
19991 */
19992 goto selector_key_error;
19993 }
19994 goto selector_leave;
19995 }
19996 }
19997 /*
19998 * All fields did resolve.
19999 */
20000
20001 /*
20002 * 4.1 If the {identity-constraint category} is unique(/key),
20003 * then no two members of the ·qualified node set· have
20004 * ·key-sequences· whose members are pairwise equal, as
20005 * defined by Equal in [XML Schemas: Datatypes].
20006 *
20007 * Get the IDC binding from the matcher and check for
20008 * duplicate key-sequences.
20009 */
20010 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
20011 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
20012 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020013 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020014
20015 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020016 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020017 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020018 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020019 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020020 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020021 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020022 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020023 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020024 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020025 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
20026 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020027 if (res == -1) {
20028 return (-1);
20029 } else if (res == 0)
20030 break;
20031 }
20032 if (res == 1) {
20033 /*
20034 * Duplicate found.
20035 */
20036 break;
20037 }
20038 i++;
20039 } while (i < bind->nbNodes);
20040 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020041 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020042 /*
20043 * TODO: Try to report the key-sequence.
20044 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020045 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020046 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020047 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020048 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020049 "Duplicate key-sequence %s",
20050 xmlSchemaFormatIDCKeySequence(vctxt, &str,
20051 (*keySeq), nbKeys), NULL);
20052 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020053 goto selector_leave;
20054 }
20055 }
20056 /*
20057 * Add a node-table item to the IDC binding.
20058 */
20059 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
20060 sizeof(xmlSchemaPSVIIDCNode));
20061 if (ntItem == NULL) {
20062 xmlSchemaVErrMemory(NULL,
20063 "allocating an IDC node-table item", NULL);
20064 xmlFree(*keySeq);
20065 *keySeq = NULL;
20066 return(-1);
20067 }
20068 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
20069
20070 /*
20071 * Store the node-table item on global list.
20072 */
20073 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
20074 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
20075 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020076 xmlFree(*keySeq);
20077 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020078 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020079 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020080 }
20081 /*
20082 * Init the node-table item. Consume the key-sequence.
20083 */
20084 ntItem->node = vctxt->node;
20085 ntItem->keys = *keySeq;
20086 *keySeq = NULL;
20087 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
20088 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20089 /*
20090 * Free the item, since keyref items won't be
20091 * put on a global list.
20092 */
20093 xmlFree(ntItem->keys);
20094 xmlFree(ntItem);
20095 }
20096 return (-1);
20097 }
20098
20099 goto selector_leave;
20100selector_key_error:
20101 /*
20102 * 4.2.1 (KEY) The ·target node set· and the
20103 * ·qualified node set· are equal, that is, every
20104 * member of the ·target node set· is also a member
20105 * of the ·qualified node set· and vice versa.
20106 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020107 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020108 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020109 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020110 (xmlSchemaTypePtr) idc,
20111 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020112 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020113selector_leave:
20114 /*
20115 * Free the key-sequence if not added to the IDC table.
20116 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020117 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020118 xmlFree(*keySeq);
20119 *keySeq = NULL;
20120 }
20121 } /* if selector */
20122
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020123 sto->nbHistory--;
20124
20125deregister_check:
20126 /*
20127 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020128 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020129 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020130#if DEBUG_IDC
20131 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
20132 sto->sel->xpath);
20133#endif
20134 if (vctxt->xpathStates != sto) {
20135 xmlSchemaVErr(vctxt, vctxt->node,
20136 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020137 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020138 "The state object to be removed is not the first "
20139 "in the list.\n",
20140 NULL, NULL);
20141 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020142 nextsto = sto->next;
20143 /*
20144 * Unlink from the list of active XPath state objects.
20145 */
20146 vctxt->xpathStates = sto->next;
20147 sto->next = vctxt->xpathStatePool;
20148 /*
20149 * Link it to the pool of reusable state objects.
20150 */
20151 vctxt->xpathStatePool = sto;
20152 sto = nextsto;
20153 } else
20154 sto = sto->next;
20155 } /* while (sto != NULL) */
20156 return (0);
20157}
20158
20159/**
20160 * xmlSchemaIDCRegisterMatchers:
20161 * @vctxt: the WXS validation context
20162 * @elemDecl: the element declaration
20163 *
20164 * Creates helper objects to evaluate IDC selectors/fields
20165 * successively.
20166 *
20167 * Returns 0 if OK and -1 on internal errors.
20168 */
20169static int
20170xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
20171 xmlSchemaElementPtr elemDecl)
20172{
20173 xmlSchemaIDCMatcherPtr matcher, last = NULL;
20174 xmlSchemaIDCPtr idc, refIdc;
20175 xmlSchemaIDCAugPtr aidc;
20176
20177 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
20178 if (idc == NULL)
20179 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020180
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020181#if DEBUG_IDC
20182 {
20183 xmlChar *str = NULL;
20184 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020185 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020186 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20187 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020188 FREE_AND_NULL(str)
20189 }
20190#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020191 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020192 xmlSchemaVErr(vctxt, vctxt->node,
20193 XML_SCHEMAV_INTERNAL,
20194 "Internal error: xmlSchemaIDCRegisterMatchers: "
20195 "The chain of IDC matchers is expected to be empty.\n",
20196 NULL, NULL);
20197 return (-1);
20198 }
20199 do {
20200 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20201 /*
20202 * Since IDCs bubbles are expensive we need to know the
20203 * depth at which the bubbles should stop; this will be
20204 * the depth of the top-most keyref IDC. If no keyref
20205 * references a key/unique IDC, the bubbleDepth will
20206 * be -1, indicating that no bubbles are needed.
20207 */
20208 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
20209 if (refIdc != NULL) {
20210 /*
20211 * Lookup the augmented IDC.
20212 */
20213 aidc = vctxt->aidcs;
20214 while (aidc != NULL) {
20215 if (aidc->def == refIdc)
20216 break;
20217 aidc = aidc->next;
20218 }
20219 if (aidc == NULL) {
20220 xmlSchemaVErr(vctxt, vctxt->node,
20221 XML_SCHEMAV_INTERNAL,
20222 "Internal error: xmlSchemaIDCRegisterMatchers: "
20223 "Could not find an augmented IDC item for an IDC "
20224 "definition.\n",
20225 NULL, NULL);
20226 return (-1);
20227 }
20228 if ((aidc->bubbleDepth == -1) ||
20229 (vctxt->depth < aidc->bubbleDepth))
20230 aidc->bubbleDepth = vctxt->depth;
20231 }
20232 }
20233 /*
20234 * Lookup the augmented IDC item for the IDC definition.
20235 */
20236 aidc = vctxt->aidcs;
20237 while (aidc != NULL) {
20238 if (aidc->def == idc)
20239 break;
20240 aidc = aidc->next;
20241 }
20242 if (aidc == NULL) {
20243 xmlSchemaVErr(vctxt, vctxt->node,
20244 XML_SCHEMAV_INTERNAL,
20245 "Internal error: xmlSchemaIDCRegisterMatchers: "
20246 "Could not find an augmented IDC item for an IDC definition.\n",
20247 NULL, NULL);
20248 return (-1);
20249 }
20250 /*
20251 * Create an IDC matcher for every IDC definition.
20252 */
20253 matcher = (xmlSchemaIDCMatcherPtr)
20254 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20255 if (matcher == NULL) {
20256 xmlSchemaVErrMemory(vctxt,
20257 "allocating an IDC matcher", NULL);
20258 return (-1);
20259 }
20260 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20261 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020262 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020263 else
20264 last->next = matcher;
20265 last = matcher;
20266
20267 matcher->type = IDC_MATCHER;
20268 matcher->depth = vctxt->depth;
20269 matcher->aidc = aidc;
20270#if DEBUG_IDC
20271 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20272#endif
20273 /*
20274 * Init the automaton state object.
20275 */
20276 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020277 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020278 return (-1);
20279
20280 idc = idc->next;
20281 } while (idc != NULL);
20282 return (0);
20283}
20284
20285/**
20286 * xmlSchemaBubbleIDCNodeTables:
20287 * @depth: the current tree depth
20288 *
20289 * Merges IDC bindings of an element at @depth into the corresponding IDC
20290 * bindings of its parent element. If a duplicate note-table entry is found,
20291 * both, the parent node-table entry and child entry are discarded from the
20292 * node-table of the parent.
20293 *
20294 * Returns 0 if OK and -1 on internal errors.
20295 */
20296static int
20297xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20298{
20299 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020300 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20301 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020302 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20303 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020304 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020305 int duplTop;
20306
20307 /*
20308 * The node table has the following sections:
20309 *
20310 * O --> old node-table entries (first)
20311 * O
20312 * + --> new node-table entries
20313 * +
20314 * % --> new duplicate node-table entries
20315 * %
20316 * # --> old duplicate node-table entries
20317 * # (last)
20318 *
20319 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020320 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020321 if (bind == NULL) {
20322 /* Fine, no table, no bubbles. */
20323 return (0);
20324 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020325
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020326 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20327 /*
20328 * Walk all bindings; create new or add to existing bindings.
20329 * Remove duplicate key-sequences.
20330 */
20331start_binding:
20332 while (bind != NULL) {
20333 /*
20334 * Skip keyref IDCs.
20335 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020336 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20337 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020338 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020339 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020340 /*
20341 * Check if the key/unique IDC table needs to be bubbled.
20342 */
20343 aidc = vctxt->aidcs;
20344 do {
20345 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020346 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020347 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020348 bind = bind->next;
20349 goto start_binding;
20350 }
20351 break;
20352 }
20353 aidc = aidc->next;
20354 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020355
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020356 if (parTable != NULL)
20357 parBind = *parTable;
20358 while (parBind != NULL) {
20359 /*
20360 * Search a matching parent binding for the
20361 * IDC definition.
20362 */
20363 if (parBind->definition == bind->definition) {
20364
20365 /*
20366 * Compare every node-table entry of the child node,
20367 * i.e. the key-sequence within, ...
20368 */
20369 oldNum = parBind->nbNodes; /* Skip newly added items. */
20370 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020371 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020372
20373 for (i = 0; i < bind->nbNodes; i++) {
20374 node = bind->nodeTable[i];
20375 if (node == NULL)
20376 continue;
20377 /*
20378 * ...with every key-sequence of the parent node, already
20379 * evaluated to be a duplicate key-sequence.
20380 */
20381 if (parBind->nbDupls != 0) {
20382 j = bind->nbNodes + newDupls;
20383 while (j < duplTop) {
20384 parNode = parBind->nodeTable[j];
20385 for (k = 0; k < bind->definition->nbFields; k++) {
20386 key = node->keys[k];
20387 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020388 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020389 key->compValue,
20390 parKey->type, parKey->compValue);
20391 if (ret == -1) {
20392 /* TODO: Internal error */
20393 return(-1);
20394 } else if (ret == 0)
20395 break;
20396
20397 }
20398 if (ret == 1)
20399 /* Duplicate found. */
20400 break;
20401 j++;
20402 }
20403 if (j != duplTop) {
20404 /* Duplicate found. */
20405 continue;
20406 }
20407 }
20408 /*
20409 * ... and with every key-sequence of the parent node.
20410 */
20411 j = 0;
20412 while (j < oldNum) {
20413 parNode = parBind->nodeTable[j];
20414 /*
20415 * Compare key by key.
20416 */
20417 for (k = 0; k < parBind->definition->nbFields; k++) {
20418 key = node->keys[k];
20419 parKey = parNode->keys[k];
20420
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020421 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020422 key->compValue,
20423 parKey->type, parKey->compValue);
20424 if (ret == -1) {
20425 /* TODO: Internal error */
20426 } else if (ret == 0)
20427 break;
20428
20429 }
20430 if (ret == 1)
20431 /*
20432 * The key-sequences are equal.
20433 */
20434 break;
20435 j++;
20436 }
20437 if (j != oldNum) {
20438 /*
20439 * Handle duplicates.
20440 */
20441 newDupls++;
20442 oldNum--;
20443 parBind->nbNodes--;
20444 /*
20445 * Move last old item to pos of duplicate.
20446 */
20447 parBind->nodeTable[j] =
20448 parBind->nodeTable[oldNum];
20449
20450 if (parBind->nbNodes != oldNum) {
20451 /*
20452 * If new items exist, move last new item to
20453 * last of old items.
20454 */
20455 parBind->nodeTable[oldNum] =
20456 parBind->nodeTable[parBind->nbNodes];
20457 }
20458 /*
20459 * Move duplicate to last pos of new/old items.
20460 */
20461 parBind->nodeTable[parBind->nbNodes] = parNode;
20462
20463 } else {
20464 /*
20465 * Add the node-table entry (node and key-sequence) of
20466 * the child node to the node table of the parent node.
20467 */
20468 if (parBind->nodeTable == NULL) {
20469 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020470 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020471 if (parBind->nodeTable == NULL) {
20472 xmlSchemaVErrMemory(NULL,
20473 "allocating IDC list of node-table items", NULL);
20474 return(-1);
20475 }
20476 parBind->sizeNodes = 1;
20477 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020478 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020479 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20480 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20481 sizeof(xmlSchemaPSVIIDCNodePtr));
20482 if (parBind->nodeTable == NULL) {
20483 xmlSchemaVErrMemory(NULL,
20484 "re-allocating IDC list of node-table items", NULL);
20485 return(-1);
20486 }
20487 }
20488
20489 /*
20490 * Move first old duplicate to last position
20491 * of old duplicates +1.
20492 */
20493 if (parBind->nbDupls != 0) {
20494 parBind->nodeTable[duplTop] =
20495 parBind->nodeTable[parBind->nbNodes + newDupls];
20496 }
20497 /*
20498 * Move first new duplicate to last position of
20499 * new duplicates +1.
20500 */
20501 if (newDupls != 0) {
20502 parBind->nodeTable[parBind->nbNodes + newDupls] =
20503 parBind->nodeTable[parBind->nbNodes];
20504 }
20505 /*
20506 * Append the new node-table entry to the 'new node-table
20507 * entries' section.
20508 */
20509 parBind->nodeTable[parBind->nbNodes] = node;
20510 parBind->nbNodes++;
20511 duplTop++;
20512 }
20513 }
20514 parBind->nbDupls += newDupls;
20515 break;
20516 }
20517 if (parBind->next == NULL)
20518 lastParBind = parBind;
20519 parBind = parBind->next;
20520 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020521 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020522 /*
20523 * No binding for the IDC was found: create a new one and
20524 * copy all node-tables.
20525 */
20526 parBind = xmlSchemaIDCNewBinding(bind->definition);
20527 if (parBind == NULL)
20528 return(-1);
20529
20530 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20531 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
20532 if (parBind->nodeTable == NULL) {
20533 xmlSchemaVErrMemory(NULL,
20534 "allocating an array of IDC node-table items", NULL);
20535 xmlSchemaIDCFreeBinding(parBind);
20536 return(-1);
20537 }
20538 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020539 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020540 memcpy(parBind->nodeTable, bind->nodeTable,
20541 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020542 if (*parTable == NULL)
20543 *parTable = parBind;
20544 else
20545 lastParBind->next = parBind;
20546 }
20547 bind = bind->next;
20548 }
20549 return (0);
20550}
20551
20552/**
20553 * xmlSchemaCheckCVCIDCKeyRef:
20554 * @vctxt: the WXS validation context
20555 * @elemDecl: the element declaration
20556 *
20557 * Check the cvc-idc-keyref constraints.
20558 */
20559static int
20560xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
20561{
20562 xmlSchemaPSVIIDCBindingPtr refbind, bind;
20563
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020564 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020565 /*
20566 * Find a keyref.
20567 */
20568 while (refbind != NULL) {
20569 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20570 int i, j, k, res;
20571 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
20572 xmlSchemaPSVIIDCKeyPtr refKey, key;
20573
20574 /*
20575 * Find the referred key/unique.
20576 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020577 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020578 do {
20579 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
20580 bind->definition)
20581 break;
20582 bind = bind->next;
20583 } while (bind != NULL);
20584
20585 /*
20586 * Search for a matching key-sequences.
20587 */
20588 for (i = 0; i < refbind->nbNodes; i++) {
20589 res = 0;
20590 if (bind != NULL) {
20591 refKeys = refbind->nodeTable[i]->keys;
20592 for (j = 0; j < bind->nbNodes; j++) {
20593 keys = bind->nodeTable[j]->keys;
20594 for (k = 0; k < bind->definition->nbFields; k++) {
20595 refKey = refKeys[k];
20596 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020597 res = xmlSchemaAreValuesEqual(vctxt,
20598 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020599 refKey->type, refKey->compValue);
20600 if (res == 0)
20601 break;
20602 else if (res == -1) {
20603 return (-1);
20604 }
20605 }
20606 if (res == 1) {
20607 /*
20608 * Match found.
20609 */
20610 break;
20611 }
20612 }
20613 }
20614 if (res == 0) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020615 xmlChar *str = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020616 /* TODO: Report the key-sequence. */
20617 xmlSchemaVCustomErr(vctxt,
20618 XML_SCHEMAV_CVC_IDC,
20619 refbind->nodeTable[i]->node,
20620 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020621 "No match found for key reference %s",
20622 xmlSchemaFormatIDCKeySequence(vctxt, &str,
20623 refbind->nodeTable[i]->keys,
20624 refbind->definition->nbFields));
20625 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020626 }
20627 }
20628 }
20629 refbind = refbind->next;
20630 }
20631 return (0);
20632}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020633
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020634/**
20635 * xmlSchemaBeginElement:
20636 * @vctxt: the WXS validation context
20637 *
20638 * Just a temporary workaround to simulate streaming validation
20639 * a bit.
20640 */
20641static void
20642xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
20643{
20644 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020645 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
20646 vctxt->nodeInfo->node = vctxt->node;
20647 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020648 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020649 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020650 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020651 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020652}
20653
20654/**
20655 * xmlSchemaEndElement:
20656 * @vctxt: the WXS validation context
20657 *
20658 * Just a temporary workaround to simulate streaming validation
20659 * a bit.
20660 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020661static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020662xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
20663{
20664 if (vctxt->depth < 0) {
20665 /* TODO: raise error? */
20666 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020667 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020668 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020669 /*
20670 * Evaluate the history of changes of active state objects.
20671 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020672 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
20673 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020674
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020675 if (vctxt->nodeInfo->value != NULL) {
20676 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20677 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020678 }
20679 /*
20680 * TODO: 6 The element information item must be ·valid· with respect to each of
20681 * the {identity-constraint definitions} as per Identity-constraint
20682 * Satisfied (§3.11.4).
20683 */
20684 /*
20685 * Validate IDC keyrefs.
20686 */
20687 xmlSchemaCheckCVCIDCKeyRef(vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020688
20689 /*
20690 * Merge/free the IDC table.
20691 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020692 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020693#ifdef DEBUG_IDC
20694 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020695 vctxt->nodeInfo->namespaceName,
20696 vctxt->nodeInfo->localName,
20697 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020698#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020699 if (vctxt->depth > 0) {
20700 /*
20701 * Merge the IDC node table with the table of the parent node.
20702 */
20703 xmlSchemaBubbleIDCNodeTables(vctxt);
20704 }
20705 /*
20706 * TODO: Don't free the PSVI IDC tables if they are
20707 * requested for the PSVI.
20708 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020709 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020710 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020711 }
20712
20713 /*
20714 * Cleanup IDC matchers.
20715 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020716 if (vctxt->nodeInfo->idcMatchers != NULL) {
20717 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
20718 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020719 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020720
20721 /*
20722 * Skip further processing if we are on the validation root.
20723 */
20724 if (vctxt->depth == 0) {
20725 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020726 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020727 }
20728
20729 /*
20730 * Reset the bubbleDepth if needed.
20731 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020732 if (vctxt->aidcs != NULL) {
20733 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
20734 do {
20735 if (aidc->bubbleDepth == vctxt->depth) {
20736 /*
20737 * A bubbleDepth of a key/unique IDC matches the current
20738 * depth, this means that we are leaving the scope of the
20739 * top-most keyref IDC.
20740 */
20741 aidc->bubbleDepth = -1;
20742 }
20743 aidc = aidc->next;
20744 } while (aidc != NULL);
20745 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020746 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020747 /*
20748 * Clear the current elemInfo.
20749 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020750 if (vctxt->nodeInfo->value != NULL) {
20751 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20752 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020753 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020754 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
20755 vctxt->node = vctxt->nodeInfo->node;
20756
20757 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020758}
20759
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020760/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020761 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000020762 * @ctxt: a schema validation context
20763 * @node: the top node.
20764 *
20765 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020766 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000020767 *
20768 * Returns 0 if the element is schemas valid, a positive error code
20769 * number otherwise and -1 in case of internal or API error.
20770 */
20771static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020772xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
20773 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020774{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020775 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020776 int ret = 0;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020777 xmlSchemaTypePtr actualType = NULL, localType = NULL, type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020778 xmlAttrPtr attr;
20779 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020780 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020781
20782 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020783 * This one is called by xmlSchemaValidateElementByWildcardInternal,
20784 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020785 * Note that @elemDecl will be the declaration and never the
20786 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020787 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020788
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020789 if (ctxt == NULL) {
20790 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
20791 "Internal error: xmlSchemaValidateElementByDeclaration, "
20792 "bad arguments.\n",
20793 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020794 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020795 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020796
20797 elem = ctxt->node;
20798
20799 /*
20800 * cvc-elt (3.3.4) : 1
20801 */
20802 if (elemDecl == NULL) {
20803 xmlSchemaVCustomErr(ctxt,
20804 XML_SCHEMAV_CVC_ELT_1,
20805 elem, NULL,
20806 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020807 /*
20808 * Evaluate IDCs even if an error occured.
20809 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020810 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020811 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020812 return (ctxt->err);
20813 }
20814 /*
20815 * cvc-elt (3.3.4) : 2
20816 */
20817 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20818 xmlSchemaVCustomErr(ctxt,
20819 XML_SCHEMAV_CVC_ELT_2,
20820 elem, NULL,
20821 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020822 /*
20823 * Evaluate IDCs even if an error occured.
20824 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020825 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020826 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020827 return (ctxt->err);
20828 }
20829
20830 /*
20831 * cvc-elt (3.3.4) : 3
20832 * Handle 'xsi:nil'.
20833 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020834
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020835 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020836 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020837 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20838 ctxt->node = (xmlNodePtr) attr;
20839 ctxt->cur = attr->children;
20840 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
20841 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20842 BAD_CAST attrValue, 1, 1, 1, 1);
20843 ctxt->node = elem;
20844 ctxt->type = (xmlSchemaTypePtr) elemDecl;
20845 if (ret < 0) {
20846 xmlSchemaVCustomErr(ctxt,
20847 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020848 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020849 "Internal error: xmlSchemaValidateElementByDeclaration, "
20850 "validating the attribute 'xsi:nil'", NULL);
20851 if (attrValue != NULL)
20852 xmlFree(attrValue);
20853 return (-1);
20854 }
20855 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020856 /*
20857 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020858 */
20859 xmlSchemaVCustomErr(ctxt,
20860 XML_SCHEMAV_CVC_ELT_3_1,
20861 elem, NULL,
20862 "The element is not 'nillable'", NULL);
20863 } else {
20864 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020865 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020866 ret = 0;
20867 /*
20868 * cvc-elt (3.3.4) : 3.2.1
20869 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020870 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
20871 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020872 xmlSchemaVCustomErr(ctxt,
20873 XML_SCHEMAV_CVC_ELT_3_2_1,
20874 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020875 elem, (xmlSchemaTypePtr) elemDecl,
20876 "The 'nilled' element must have no character or "
20877 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020878 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
20879 }
20880 /*
20881 * cvc-elt (3.3.4) : 3.2.2
20882 */
20883 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
20884 (elemDecl->value != NULL)) {
20885 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
20886 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020887 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020888 "There is a fixed value constraint defined for "
20889 "the 'nilled' element", NULL);
20890 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
20891 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020892 if (ret == 0)
20893 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020894 }
20895 }
20896 if (attrValue != NULL)
20897 xmlFree(attrValue);
20898 }
20899
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020900 type = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020901 actualType = type;
20902
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020903 /*
20904 * cvc-elt (3.3.4) : 4
20905 * Handle 'xsi:type'.
20906 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020907
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020908 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
20909 if (attr != NULL) {
20910 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020911
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020912 /*
20913 * TODO: We should report a *warning* that the type was overriden
20914 * by the instance.
20915 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020916
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020917 /*
20918 * cvc-elt (3.3.4) : 4.1
20919 */
20920 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20921 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
20922 &nsName, &local);
20923 if (ret < 0) {
20924 xmlSchemaVCustomErr(ctxt,
20925 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020926 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020927 "Internal error: xmlSchemaValidateElementByDeclaration, "
20928 "validating the attribute 'xsi:type'", NULL);;
20929 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020930 FREE_AND_NULL(nsName)
20931 FREE_AND_NULL(local)
20932 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020933 } else if (ret == 1) {
20934 xmlSchemaVSimpleTypeErr(ctxt,
20935 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20936 (xmlNodePtr) attr, attrValue,
20937 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
20938 } else if (ret == 2) {
20939 xmlSchemaVCustomErr(ctxt,
20940 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20941 (xmlNodePtr) attr,
20942 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20943 "The QName value '%s' has no "
20944 "corresponding namespace declaration in scope",
20945 attrValue);
20946 } else {
20947 /*
20948 * cvc-elt (3.3.4) : 4.2
20949 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020950 localType = xmlSchemaGetType(ctxt->schema, local, nsName);
20951 if (localType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020952 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020954 xmlSchemaVCustomErr(ctxt,
20955 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020956 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020957 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020958 "The value '%s' of the xsi:type attribute does not "
20959 "resolve to a type definition",
20960 xmlSchemaFormatQName(&strA, nsName, local));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020961 FREE_AND_NULL(strA);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020962 } else {
20963 int set = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020964 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020965 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20966 * "The ·local type definition· must be validly
20967 * derived from the {type definition} given the union of
20968 * the {disallowed substitutions} and the {type definition}'s
20969 * {prohibited substitutions}, as defined in
20970 * Type Derivation OK (Complex) (§3.4.6)
20971 * (if it is a complex type definition),
20972 * or given {disallowed substitutions} as defined in Type
20973 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20974 * definition)."
20975 *
20976 * {disallowed substitutions}: the "block" on the element decl.
20977 * {prohibited substitutions}: the "block" on the type def.
20978 */
20979 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20980 (type->flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20981 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
20982
20983 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20984 (type->flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20985 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
20986
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020987 if (xmlSchemaCheckCOSDerivedOK(ctxt->schema, localType,
20988 type, set) != 0) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020989 xmlChar *strA = NULL, *strB = NULL;
20990
20991 xmlSchemaVCustomErrExt(ctxt,
20992 /* TODO: Error code */
20993 XML_SCHEMAV_CVC_ELT_4_2, elem, localType,
20994 "The xsi:type definition '%s' is not validly derived from "
20995 "the type definition '%s'",
20996 xmlSchemaFormatQName(&strA,
20997 localType->targetNamespace,
20998 localType->name),
20999 xmlSchemaFormatQName(&strB,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021000 ELEM_TYPE(elemDecl)->targetNamespace,
21001 ELEM_TYPE(elemDecl)->name), NULL);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021002 FREE_AND_NULL(strA)
21003 FREE_AND_NULL(strB)
21004 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021005 }
21006 }
21007 FREE_AND_NULL(attrValue)
21008 FREE_AND_NULL(nsName)
21009 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021010 }
21011 /* TODO: Change the handling of missing types according to
21012 * the spec.
21013 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021014 if (localType != NULL)
21015 actualType = localType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021016 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021017 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021018 XML_SCHEMAV_CVC_TYPE_1,
21019 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021020 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021021 /*
21022 * Evaluate IDCs even if an error occured.
21023 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021024 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021025 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021026 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021027 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021028
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021029 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021030 * Remember the actual-type definition.
21031 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021032 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021033
21034 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021035 * TODO: Since this should be already checked by the content model automaton,
21036 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
21037 * has been changed to XML_SCHEMAV_INTERNAL.
21038 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021039 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000021040 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021041 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021042 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021043 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021044 "Element %s: missing child %s\n",
21045 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021046 }
21047 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021048 }
21049 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021050 /*
21051 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021052 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021053 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000021054 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021055 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021056 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021057 "Element %s: missing child %s found %s\n",
21058 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021059 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021060 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021061 */
21062 if (elemHasContent == -1)
21063 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021064
21065 /*
21066 * IDC: Register identity-constraint XPath matchers.
21067 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021068 if (elemDecl->idcs != NULL)
21069 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
21070 /*
21071 * Evaluate IDCs.
21072 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021073 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021074 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021075 /*
21076 * cvc-elt (3.3.4) : 5
21077 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021078 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021079 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021080 * cvc-elt (3.3.4) : 5.1
21081 * If the declaration has a {value constraint},
21082 * the item has neither element nor character [children] and
21083 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021084 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021085 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
21086 /*
21087 * cvc-elt (3.3.4) : 5.1.1
21088 * If the ·actual type definition· is a ·local type definition·
21089 * then the canonical lexical representation of the {value constraint}
21090 * value must be a valid default for the ·actual type definition· as
21091 * defined in Element Default Valid (Immediate) (§3.3.6).
21092 */
21093 /*
21094 * NOTE: 'local' above means types aquired by xsi:type.
21095 */
21096 ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021097 if (actualType != ELEM_TYPE(elemDecl)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021098 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
21099 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021100 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021101 if (ret < 0) {
21102 xmlSchemaVCustomErr(ctxt,
21103 XML_SCHEMAV_INTERNAL,
21104 elem, actualType,
21105 "Internal error: xmlSchemaValidateElementByDeclaration, "
21106 "validating a default value", NULL);
21107 return (-1);
21108 }
21109 }
21110 /*
21111 * cvc-elt (3.3.4) : 5.1.2
21112 * The element information item with the canonical lexical
21113 * representation of the {value constraint} value used as its
21114 * ·normalized value· must be ·valid· with respect to the
21115 * ·actual type definition· as defined by Element Locally Valid (Type)
21116 * (§3.3.4).
21117 */
21118 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021119 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021120 * done above.
21121 */
21122 if (ret == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021123 if (actualType != ELEM_TYPE(elemDecl))
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021124 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021125 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021126 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021127 ctxt->node = elem;
21128 if (ret < 0) {
21129 xmlSchemaVCustomErr(ctxt,
21130 XML_SCHEMAV_INTERNAL,
21131 elem, actualType,
21132 "Internal error: xmlSchemaValidateElementByDeclaration, "
21133 "validating against the type", NULL);
21134 return (-1);
21135 }
21136 /*
21137 * PSVI: Create a text node on the instance element.
21138 */
21139 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
21140 xmlNodePtr textChild;
21141
21142 textChild = xmlNewText(elemDecl->value);
21143 if (textChild == NULL) {
21144 xmlSchemaVCustomErr(ctxt,
21145 XML_SCHEMAV_INTERNAL,
21146 elem, actualType,
21147 "Internal error: xmlSchemaValidateElementByDeclaration, "
21148 "could not create a default text node for the instance",
21149 NULL);
21150 } else
21151 xmlAddChild(elem, textChild);
21152 }
21153 }
21154
21155 } else {
21156 /*
21157 * 5.2.1 The element information item must be ·valid· with respect
21158 * to the ·actual type definition· as defined by Element Locally
21159 * Valid (Type) (§3.3.4).
21160 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021161 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
21162 /*
21163 * Consume the computed value for IDCs, ect. Note that default
21164 * values are not supported yet.
21165 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021166 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021167 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021168 ctxt->value = NULL;
21169 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021170 ctxt->node = elem;
21171 if (ret < 0) {
21172 xmlSchemaVCustomErr(ctxt,
21173 XML_SCHEMAV_INTERNAL,
21174 elem, actualType,
21175 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021176 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021177 return (-1);
21178 }
21179 /*
21180 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
21181 * not applied, all of the following must be true:
21182 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021183 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
21184 /*
21185 * 5.2.2.1 The element information item must have no element
21186 * information item [children].
21187 *
21188 * TODO REDUNDANT: If the actual type exists, the above call to
21189 * xmlSchemaValidateElementByType will already check for element
21190 * nodes.
21191 */
21192 if (xmlSchemaHasElemContent(elem)) {
21193 xmlSchemaVCustomErr(ctxt,
21194 XML_SCHEMAV_CVC_ELT_5_2_2_1,
21195 elem, (xmlSchemaTypePtr) elemDecl,
21196 "Elements in the content are not allowed if it is "
21197 "constrained by a fixed value", NULL);
21198 } else {
21199 /*
21200 * 5.2.2.2 The appropriate case among the following must
21201 * be true:
21202 */
21203
21204 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
21205 xmlChar *value;
21206 /*
21207 * 5.2.2.2.1 If the {content type} of the ·actual type
21208 * definition· is mixed, then the *initial value* of the
21209 * item must match the canonical lexical representation
21210 * of the {value constraint} value.
21211 *
21212 * ... the *initial value* of an element information
21213 * item is the string composed of, in order, the
21214 * [character code] of each character information item in
21215 * the [children] of that element information item.
21216 */
21217 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21218 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21219 /*
21220 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021221 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021222 */
21223 xmlSchemaVCustomErr(ctxt,
21224 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
21225 elem, (xmlSchemaTypePtr) elemDecl,
21226 "The value does not match the cononical "
21227 "lexical representation of the fixed constraint",
21228 NULL);
21229 }
21230 if (value != NULL)
21231 xmlFree(value);
21232 } else if ((actualType->contentType ==
21233 XML_SCHEMA_CONTENT_SIMPLE) ||
21234 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
21235 xmlChar *value;
21236
21237 /*
21238 * 5.2.2.2.2 If the {content type} of the ·actual type
21239 * definition· is a simple type definition, then the
21240 * *actual value* of the item must match the canonical
21241 * lexical representation of the {value constraint} value.
21242 */
21243 /*
21244 * TODO: *actual value* is the normalized value, impl. this.
21245 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021246 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021247 *
21248 */
21249 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21250 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21251 xmlSchemaVCustomErr(ctxt,
21252 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
21253 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021254 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021255 "lexical representation of the fixed constraint",
21256 NULL);
21257 }
21258 if (value != NULL)
21259 xmlFree(value);
21260
21261 }
21262 /*
21263 * TODO: What if the content type is not 'mixed' or simple?
21264 */
21265
21266 }
21267
21268 }
21269 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021270 /*
21271 * TODO: 7 If the element information item is the ·validation root·, it must be
21272 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
21273 */
21274
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021275 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021276}
21277
Daniel Veillard4255d502002-04-16 15:50:10 +000021278/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021279 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021280 * @ctxt: a schema validation context
21281 * @node: the top node.
21282 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021283 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
21284 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021285 *
21286 * Returns 0 if the element is valid, a positive error code
21287 * number otherwise and -1 in case of an internal error.
21288 */
21289static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021290xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
21291 xmlSchemaWildcardPtr wild,
21292 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021293{
21294 const xmlChar *uri;
21295 int ret = 0;
21296 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021297
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021298 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021299 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
21300 if (ret == -1) {
21301 xmlSchemaVCustomErr(ctxt,
21302 XML_SCHEMAV_INTERNAL,
21303 ctxt->node, NULL,
21304 "Internal error: xmlSchemaValidateElement, "
21305 "assembling schema by xsi", NULL);
21306 return (-1);
21307 }
21308 /*
21309 * NOTE: We won't react on schema parser errors here.
21310 * TODO: But a warning would be nice.
21311 */
21312 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021313 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
21314 xmlSchemaElementPtr decl = NULL;
21315
21316 if (node->ns != NULL)
21317 decl = xmlHashLookup3(ctxt->schema->elemDecl,
21318 node->name, node->ns->href, NULL);
21319 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021320 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
21321 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021322 if (decl != NULL) {
21323 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021324 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021325 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021326 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021327 "Internal error: xmlSchemaValidateAnyInternal, "
21328 "validating an element in the context of a wildcard.",
21329 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000021330 }
21331 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021332 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21333 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021334 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021335 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021336 /*
21337 * Evaluate IDCs even if a validation error occured.
21338 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021339 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021340 return(-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021341
Daniel Veillardc0826a72004-08-10 14:17:33 +000021342 return (ctxt->err);
21343 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021344 /*
21345 * Evaluate IDCs; we need to know if an IDC field resolves to
21346 * such a node. This node has no type definition and will
21347 * definitely result in an IDC validation error if an IDC field
21348 * resolves.
21349 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021350 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021351 return(-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021352 }
21353 if (node->children != NULL) {
21354 child = node->children;
21355 do {
21356 if (child->type == XML_ELEMENT_NODE) {
21357 if (child->ns != NULL)
21358 uri = child->ns->href;
21359 else
21360 uri = NULL;
21361 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021362 /* TODO: error code. */
21363 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021364 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021365 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000021366 return (ctxt->err);
21367 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021368
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021369 ctxt->node = child;
21370 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021371
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021372 /*
21373 * Recurse over the children.
21374 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021375 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
21376 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021377 if (ret == -1)
21378 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021379
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021380 if (xmlSchemaEndElement(ctxt) == -1)
21381 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021382
Daniel Veillardc0826a72004-08-10 14:17:33 +000021383 if (ret != 0)
21384 return (ret);
21385 }
21386 child = child->next;
21387 } while (child != NULL);
21388 }
21389 return (0);
21390}
21391
21392/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021393 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021394 * @ctxt: a schema validation context
21395 *
21396 * Returns 0 if the element is valid, a positive error code
21397 * number otherwise and -1 in case of an internal or API error.
21398 */
21399static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021400xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021401 xmlSchemaWildcardPtr wild)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021402{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021403
21404 if ((wild == NULL) || (wild->type != XML_SCHEMA_TYPE_ANY) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021405 (ctxt->node == NULL)) {
21406 xmlSchemaVCustomErr(ctxt,
21407 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
21408 "Internal error: xmlSchemaValidateElementByWildcard, "
21409 "bad arguments", NULL);
21410 return (-1);
21411 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021412 if (wild->negNsSet != NULL) {
21413 /*
21414 * Workaround for negated namespaces.
21415 */
21416 if (ctxt->node->ns != NULL) {
21417 if (xmlSchemaMatchesWildcardNs(wild, ctxt->node->ns->href) == 0) {
21418 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21419 return (XML_SCHEMAV_ELEMENT_CONTENT);
21420 }
21421 } else if (xmlSchemaMatchesWildcardNs(wild, NULL) == 0) {
21422 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21423 return (XML_SCHEMAV_ELEMENT_CONTENT);
21424 }
21425 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021426 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021427 wild, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000021428}
21429
21430/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021431 * xmlSchemaValidateElementByAnyType:
William M. Brack2f2a6632004-08-20 23:09:47 +000021432 * @ctxt: a schema validation context
21433 * @node: the current element
21434 *
21435 * This one validates the content of an element of the type
21436 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
21437 * thus elements in the subtree will be validated, if a corresponding
21438 * declaration in the schema exists.
21439 *
21440 * Returns 0 if the element and its subtree is valid, a positive error code
21441 * otherwise and -1 in case of an internal or API error.
21442 */
21443static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021444xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
21445 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000021446{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021447 xmlSchemaTypePtr oldtype;
21448 xmlNodePtr top, cur;
21449 xmlSchemaElementPtr decl;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021450 int skipContent, ret, insub = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021451
21452 if ((type == NULL) || (ctxt->node == NULL))
21453 return (-1);
21454
21455 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021456 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021457
21458 oldtype = ctxt->type;
21459 top = ctxt->node;
21460 /*
21461 * STREAM: Child nodes are processed.
21462 */
21463 cur = ctxt->node->children;
21464 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021465 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021466 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021467 /*
21468 * The process contents of the wildcard is "lax", thus
21469 * we need to validate the element if a declaration
21470 * exists.
21471 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021472 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021473 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021474 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000021475 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021476 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
21477 ctxt->node = cur;
21478
21479 if (insub) {
21480 /*
21481 * BEGIN element.
21482 */
21483 xmlSchemaBeginElement(ctxt);
21484 } else
21485 insub = 1;
21486
21487 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021488 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
21489 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000021490 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021491 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000021492 "Internal error: xmlSchemaValidateAnyTypeContent, "
21493 "validating an element in the context of a wildcard.",
21494 NULL, NULL);
21495 return (ret);
21496 } else if (ret > 0)
21497 return (ret);
21498 skipContent = 1;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021499 } else {
21500 /*
21501 * IDCs.
21502 */
21503 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
21504 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000021505 }
21506 }
21507 /*
21508 * Browse the full subtree, deep first.
21509 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021510 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021511 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021512 cur = cur->children;
21513 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021514 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021515 cur = cur->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021516 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021517 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021518 while (cur != top) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021519 if (cur->type == XML_ELEMENT_NODE) {
21520 /*
21521 * END element.
21522 */
21523 xmlSchemaEndElement(ctxt);
21524 }
21525 if (cur->parent != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021526 cur = cur->parent;
21527 if ((cur != top) && (cur->next != NULL)) {
21528 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000021529 break;
21530 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021531 if (cur->parent == NULL) {
21532 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000021533 break;
21534 }
21535 }
21536 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021537 if (cur == top)
21538 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000021539 } else
21540 break;
21541 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021542 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000021543 return (0);
21544}
21545
21546/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021547 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000021548 * @ctxt: a schema validation context
21549 * @node: the top node.
21550 *
21551 * Validate the content of an element expected to be a complex type type
21552 * xmlschema-1.html#cvc-complex-type
21553 * Validation Rule: Element Locally Valid (Complex Type)
21554 *
21555 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000021556 * number otherwise and -1 in case of internal or API error.
21557 * Note on reported errors: Although it might be nice to report
21558 * the name of the simple/complex type, used to validate the content
21559 * of a node, it is quite unnecessary: for global defined types
21560 * the local name of the element is equal to the NCName of the type,
21561 * for local defined types it makes no sense to output the internal
21562 * computed name of the type. TODO: Instead, one should attach the
21563 * struct of the type involved to the error handler - this allows
21564 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000021565 */
21566static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021567xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021568 xmlSchemaTypePtr type,
21569 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021570{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021571 xmlSchemaTypePtr oldtype;
21572 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021573 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000021574 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021575 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000021576
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021577 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
21578 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021579
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021580 oldtype = ctxt->type;
21581 ctxt->type = type;
21582 elem = ctxt->node;
21583
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021584 /*
21585 * Verify the attributes
21586 */
21587 /*
21588 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021589 */
21590 /* NOTE: removed, since a check for abstract is
21591 * done in the cvc-type constraint.
21592 *
21593 *
21594 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
21595 * xmlSchemaVComplexTypeErr(ctxt,
21596 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
21597 * elem, type,
21598 * "The type definition is abstract");
21599 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
21600 *}
21601 */
21602
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021603 attrs = ctxt->attr;
21604 attrTop = ctxt->attrTop;
21605 /*
21606 * STREAM: Attribute nodes are processed.
21607 */
21608 xmlSchemaRegisterAttributes(ctxt, elem->properties);
21609 xmlSchemaValidateAttributes(ctxt, elem, type);
21610 if (ctxt->attr != NULL)
21611 xmlSchemaFreeAttributeStates(ctxt->attr);
21612 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021613 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021614
21615 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021616 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021617 * model was defined. Somehow ->contModel is always not NULL
21618 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021619 * TODO: Check if the obove still occurs.
21620 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021621 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021622 case XML_SCHEMA_CONTENT_EMPTY: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021623 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021624 * 1 If the {content type} is empty, then the element information
21625 * item has no character or element information item [children].
21626 */
21627 /*
21628 * TODO: Is the entity stuff correct?
21629 */
21630 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
21631 xmlSchemaVComplexTypeErr(ctxt,
21632 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
21633 elem, type,
21634 "Character or element content is not allowed, "
21635 "because the content type is empty");
21636 }
21637 break;
21638 }
21639 case XML_SCHEMA_CONTENT_MIXED:
21640 /*
21641 * Some speedups for anyType or types derived directly from it.
21642 */
21643 if (IS_ANYTYPE(type)) {
21644 /*
21645 * Corresponds to <element name="foo" [type="xsd:anyType"]/>.
21646 */
21647 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21648 /* TODO: Handle -1. */
21649 break;
21650 }
21651 if (IS_ANYTYPE(type->baseType) &&
21652 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
21653 (type->subtypes == type->baseType->subtypes)) {
21654 /*
21655 * Corresponds to an <extension> of anyType.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021656 */
21657 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
21658 /* TODO: Handle -1. */
21659 break;
21660 }
21661 /* No break on purpose. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021662 case XML_SCHEMA_CONTENT_ELEMENTS: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021663 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021664 xmlChar *values[10];
21665 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021666 /*
21667 * SPEC (2.4) If the {content type} is element-only or mixed,
21668 * then the sequence of the element information item's
21669 * element information item [children], if any, taken in
21670 * order, is ·valid· with respect to the {content type}'s
21671 * particle, as defined in Element Sequence Locally Valid
21672 * (Particle) (§3.9.4).
21673 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021674 /*
21675 * Content model check initialization.
21676 */
21677 if (type->contModel != NULL) {
21678 oldregexp = ctxt->regexp;
21679 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
21680 (xmlRegExecCallbacks)
21681 xmlSchemaValidateCallback, ctxt);
21682#ifdef DEBUG_AUTOMATA
21683 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
21684#endif
21685 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021686 /*
21687 * STREAM: Children are processed.
21688 */
21689 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021690 while (child != NULL) {
21691 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021692 if (child->ns != NULL)
21693 nsUri = child->ns->href;
21694 else
21695 nsUri = NULL;
21696 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021697 child->name, nsUri, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021698 if (ctxt->err == XML_SCHEMAV_INTERNAL)
21699 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021700 if (ctxt->flags & XML_SCHEMA_VALID_INVALID_NEG_WILDCARD) {
21701 ctxt->flags ^= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21702 ret = -1;
21703 }
21704 /*
21705 * URGENT TODO: Could we anchor an error report
21706 * here to notify of invalid elements?
21707 * TODO: Perhaps it would be better to report
21708 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021709 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021710#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000021711 if (ret < 0)
21712 xmlGenericError(xmlGenericErrorContext,
21713 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000021714 else
21715 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000021716 " --> %s\n", child->name);
21717#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021718 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021719 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
21720 &values[0], &terminal);
21721 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021722 XML_SCHEMAV_ELEMENT_CONTENT,
21723 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021724 "This element is not expected",
21725 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021726 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021727 /*
21728 * Note that this will skip further validation of the
21729 * content.
21730 */
21731 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021732 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021733 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
21734 /*
21735 * TODO: Ask Daniel if this are all character nodes.
21736 */
21737 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
21738 (child->type == XML_ENTITY_NODE) ||
21739 (child->type == XML_ENTITY_REF_NODE) ||
21740 (child->type == XML_CDATA_SECTION_NODE))) {
21741 /*
21742 * 2.3 If the {content type} is element-only, then the
21743 * element information item has no character information
21744 * item [children] other than those whose [character
21745 * code] is defined as a white space in [XML 1.0 (Second
21746 * Edition)].
21747 */
William M. Brack2f2a6632004-08-20 23:09:47 +000021748 xmlSchemaVComplexTypeErr(ctxt,
21749 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021750 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021751 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021752 "because the content type is element-only");
21753 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021754 break;
21755 }
21756 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021757 }
21758 /*
21759 * Content model check finalization.
21760 */
21761 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021762 if (ret == 0) {
21763 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021764 &values[0], &terminal);
Daniel Veillard0e460da2005-03-30 22:47:10 +000021765 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021766 * If a next value still exists, It does not have to
Daniel Veillard0e460da2005-03-30 22:47:10 +000021767 * mean that there's an element missing, since it
21768 * might be an optional element. So double check it.
21769 */
21770 ret = xmlRegExecPushString(ctxt->regexp,
21771 NULL, NULL);
21772 if (ret <= 0) {
21773 ret = 1;
21774 xmlSchemaVComplexTypeElemErr(ctxt,
21775 XML_SCHEMAV_ELEMENT_CONTENT,
21776 elem, type, "Missing child element(s)",
21777 nbval, nbneg, values);
21778 } else
21779 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021780#ifdef DEBUG_AUTOMATA
Daniel Veillard0e460da2005-03-30 22:47:10 +000021781 xmlGenericError(xmlGenericErrorContext,
21782 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021783#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021784#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021785 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021786 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021787 "Element %s content check succeeded\n",
21788 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021789#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021790 }
21791 xmlRegFreeExecCtxt(ctxt->regexp);
21792 ctxt->regexp = oldregexp;
21793 }
21794 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021795 break;
21796 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021797 case XML_SCHEMA_CONTENT_BASIC:
21798 /*
21799 * If the simple content was already validated
21800 * (e.g. a default value), the content need not
21801 * to be validated again.
21802 */
21803 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021804 xmlChar *value = NULL;
21805 /*
21806 * We hit a complexType with a simpleContent resolving
21807 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000021808 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021809 /*
21810 * 2.2 If the {content type} is a simple type definition,
21811 * then the element information item has no element
21812 * information item [children], and the ·normalized value·
21813 * of the element information item is ·valid· with respect
21814 * to that simple type definition as defined by String
21815 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021816 */
21817 /*
21818 * STREAM: Children are processed.
21819 */
21820 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021821 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021822 /*
21823 * TODO: Could the entity stuff produce elements
21824 * as well?
21825 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021826 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021827 xmlSchemaVComplexTypeErr(ctxt,
21828 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021829 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021830 "Element content is not allowed, because "
21831 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000021832 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21833 break;
21834 }
21835 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021836 }
21837 ctxt->node = elem;
21838 ctxt->cur = elem->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021839 if (ret != 0) {
21840 FREE_AND_NULL(value)
21841 break;
21842 }
21843 /*
21844 * Validate the character content against a simple type.
21845 */
21846 if (elem->children == NULL)
21847 value = NULL;
21848 else
21849 value = xmlNodeGetContent(elem);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021850 /*
21851 * NOTE: This call won't check the correct types of the
21852 * content nodes, since this should be done here.
21853 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021854 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
21855 type->contentTypeDef, value, 1, 1, 1, 0);
21856 if (ret > 0) {
21857 /*
21858 * NOTE: Although an error will be reported by
21859 * xmlSchemaValidateSimpleTypeValue, the spec wants
21860 * a specific complex type error to be reported
21861 * additionally.
21862 */
21863 xmlSchemaVComplexTypeErr(ctxt,
21864 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
21865 elem, type,
21866 "The character content is not valid");
21867 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21868 } else if (ret < 0) {
21869 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
21870 "Internal error: xmlSchemaValidateComplexType, "
21871 "Element '%s': Error while validating character "
21872 "content against complex type '%s'.\n",
21873 elem->name, type->name);
21874 if (value != NULL)
21875 xmlFree(value);
21876 ctxt->type = oldtype;
21877 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021878 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021879 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021880 xmlFree(value);
21881
Daniel Veillard01fa6152004-06-29 17:04:39 +000021882 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021883 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021884 default:
21885 TODO xmlGenericError(xmlGenericErrorContext,
21886 "unimplemented content type %d\n",
21887 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000021888 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021889 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021890 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021891}
21892
21893/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021894 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000021895 * @ctxt: a schema validation context
21896 * @elem: an element
21897 * @type: the list of type declarations
21898 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021899 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000021900 *
21901 * Returns 0 if the element is schemas valid, a positive error code
21902 * number otherwise and -1 in case of internal or API error.
21903 */
21904static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021905xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021906 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021907 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021908 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021909{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021910 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000021911
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021912
21913 if ((ctxt == NULL) || (type == NULL)) {
21914 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
21915 "Internal error: xmlSchemaValidateElementByType, "
21916 "bad arguments", NULL);
21917 return (-1);
21918 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021919 /*
21920 * This one is called by "xmlSchemaValidateElementByDeclaration".
21921 * It will forward to the proper validation
21922 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021923 */
21924 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021925 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021926 XML_SCHEMAV_CVC_TYPE_1,
21927 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021928 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021929 return (XML_SCHEMAV_CVC_TYPE_1);
21930 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021931
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021932 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021933 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021934 XML_SCHEMAV_CVC_TYPE_2,
21935 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021936 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021937 return (XML_SCHEMAV_CVC_TYPE_2);
21938 }
21939
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021940 switch (type->type) {
21941 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021942 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
21943 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021944 break;
21945 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021946 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021947 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021948 break;
21949 case XML_SCHEMA_TYPE_BASIC:
21950 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
21951 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21952 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021953 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021954 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021955 break;
21956 default:
21957 ret = -1;
21958 break;
21959 }
21960 if (ret == -1)
21961 return (-1);
21962 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021963 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000021964}
21965
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021966static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021967xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021968 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021969 const xmlChar *value,
21970 xmlSchemaValPtr *val)
21971{
21972 xmlSchemaTypePtr prim;
21973
21974 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021975 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021976 XML_SCHEMAV_INTERNAL,
21977 "Internal error: xmlSchemaPostCreateVal, "
21978 "bad arguments", NULL, NULL);
21979 return (-1);
21980 }
21981 /*
21982 * Only string or anySimpleType values are expected to be post-created.
21983 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021984 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021985 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
21986 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21987 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021988 if (value == NULL)
21989 /* TODO: Can this happen at all? */
21990 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
21991 xmlStrdup(BAD_CAST ""));
21992 else
21993 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
21994 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021995 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021996 XML_SCHEMAV_INTERNAL,
21997 "Internal error: xmlSchemaPostCreateVal, "
21998 "failed to create the value", NULL, NULL);
21999 return (-1);
22000 }
22001 return (0);
22002 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022003 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022004 XML_SCHEMAV_INTERNAL,
22005 "Internal error: xmlSchemaPostCreateVal, "
22006 "the given type is not supported", NULL, NULL);
22007 return (-1);
22008}
22009
22010static int
22011xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022012 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022013{
22014 xmlChar *value;
22015 const xmlChar *defValue;
22016 xmlSchemaValPtr defVal;
22017 int fixed;
22018 int ret;
22019
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022020 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022021 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
22022 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
22023 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022024 vctxt->node = vctxt->attrInfo->node;
22025 vctxt->cur = vctxt->node->children;
22026 /* STREAM */
22027 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022028
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022029 /*
22030 * NOTE: This call also checks the content nodes for correct type.
22031 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022032 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022033 value, 1, 1, 1, 1);
22034
22035 /*
22036 * Handle 'fixed' attributes.
22037 */
22038 if (ret > 0) {
22039 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
22040 /*
22041 * NOTE: Fixed value constraints will be not
22042 * applied if the value was invalid, because:
22043 * 1. The validation process does not return a precomputed
22044 * value.
22045 * 2. An invalid value implies a violation of a fixed
22046 * value constraint.
22047 */
22048 } else if (ret == 0) {
22049 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022050 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022051 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022052 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022053
22054 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022055 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022056 /*
22057 * cvc-au : Attribute Locally Valid (Use)
22058 * For an attribute information item to be·valid·
22059 * with respect to an attribute use its ·normalized
22060 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022061 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022062 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022063 *
22064 * TODO: Use somehow the *normalized* value and the *canonical*
22065 * fixed value. This here compares the canonical values of both.
22066 * The normalized value of, for example, a float type can differ
22067 * from its canonical representation. This all means that a fixed
22068 * value can only be OK, if it's present in the canonical form in
22069 * the instance.
22070 * NOTE: Since the value for string and anySimpleType is not always
22071 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022072 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022073 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022074 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022075 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022076 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022077 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
22078 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022079 ret = -1;
22080 goto exit;
22081 }
22082 value = NULL;
22083 }
22084 if (defVal == NULL) {
22085 xmlChar *str;
22086
22087 /*
22088 * Post-create the default/fixed value.
22089 */
22090 if (defValue == NULL)
22091 str = xmlStrdup(BAD_CAST "");
22092 else
22093 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022094 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
22095 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022096 ret = -1;
22097 FREE_AND_NULL(str)
22098 goto exit;
22099 }
22100 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
22101 }
22102 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
22103 (xmlSchemaWhitespaceValueType) ws,
22104 defVal,
22105 (xmlSchemaWhitespaceValueType) ws) != 0)
22106 {
22107 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022108 }
22109 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022110 }
22111exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022112 if (value != NULL) {
22113 xmlFree(value);
22114 }
22115 return (ret);
22116}
22117
Daniel Veillard4255d502002-04-16 15:50:10 +000022118/**
22119 * xmlSchemaValidateAttributes:
22120 * @ctxt: a schema validation context
22121 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000022122 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000022123 *
22124 * Validate the attributes of an element.
22125 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000022126 * 1. Existent, invalid attributes are reported in the form
22127 * "prefix:localName".
22128 * Reason: readability - it is easier to find the actual XML
22129 * representation of the attributes QName.
22130 * 2. Missing attributes are reported in the form
22131 * {"URI", "localName"}.
22132 * This is necessary, since the the prefix need not to be declared
22133 * at all, and thus is not computable.
22134 *
Daniel Veillard4255d502002-04-16 15:50:10 +000022135 * Returns 0 if the element is schemas valid, a positive error code
22136 * number otherwise and -1 in case of internal or API error.
22137 */
22138static int
Daniel Veillard3646d642004-06-02 19:19:14 +000022139xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022140{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022141 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000022142 int ret;
22143 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022144 const xmlChar *defValue;
22145 xmlSchemaValPtr defVal;
22146 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022147 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000022148 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000022149 int found;
William M. Brack803812b2004-06-03 02:11:24 +000022150 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022151 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022152 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000022153#ifdef DEBUG_ATTR_VALIDATION
22154 int redundant = 0;
22155#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000022156
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022157
Daniel Veillardc0826a72004-08-10 14:17:33 +000022158 /*
22159 * Allow all attributes if the type is anyType.
22160 */
22161 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
22162 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022163
22164 oldnode = ctxt->node;
22165 if (type != NULL)
22166 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000022167 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000022168 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022169 attrDecl = attrUse->attr;
22170#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022171 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000022172 printf("attr use - use: %d\n", attrDecl->occurs);
22173#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022174 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022175
22176 if (curState->decl == attrUse->attr) {
22177#ifdef DEBUG_ATTR_VALIDATION
22178 redundant = 1;
22179#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022180 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022181 attr = curState->attr;
22182#ifdef DEBUG_ATTR_VALIDATION
22183 printf("attr - name: %s\n", attr->name);
22184 if (attr->ns != NULL)
22185 printf("attr - ns: %s\n", attr->ns->href);
22186 else
22187 printf("attr - ns: none\n");
22188#endif
22189 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022190 if (attr == NULL)
22191 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022192 if (attrDecl->ref != NULL) {
22193 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022194 continue;
22195 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022196 if ((attrDecl->refNs == NULL) ||
22197 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022198 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022199 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022200 continue;
22201 }
22202 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000022203 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022204 continue;
22205 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022206 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022207 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022208 if (attr->ns == NULL) {
22209 /*
William M. Bracke7091952004-05-11 15:09:58 +000022210 * accept an unqualified attribute only if the target
22211 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022212 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022213 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000022214 /*
22215 * This check was removed, since the target namespace
22216 * was evaluated during parsing and already took
22217 * "attributeFormDefault" into account.
22218 */
22219 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022220 continue;
22221 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000022222 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022223 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022224 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022225 attr->ns->href))
22226 continue;
22227 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022228 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022229#ifdef DEBUG_ATTR_VALIDATION
22230 printf("found\n");
22231#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022232 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000022233 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022234 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22235 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022236 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022237 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022238 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022239 if (!found) {
22240 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
22241 xmlSchemaAttrStatePtr tmp;
22242
Daniel Veillard3646d642004-06-02 19:19:14 +000022243#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022244 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022245#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022246 /*
22247 * Add a new dummy attribute state.
22248 */
22249 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
22250 if (tmp == NULL) {
22251 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
22252 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022253 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022254 }
22255 tmp->attr = NULL;
22256 tmp->state = XML_SCHEMAS_ATTR_MISSING;
22257 tmp->decl = attrDecl;
22258 tmp->next = NULL;
22259
22260 if (reqAttrStates == NULL) {
22261 reqAttrStates = tmp;
22262 reqAttrStatesTop = tmp;
22263 } else {
22264 reqAttrStatesTop->next = tmp;
22265 reqAttrStatesTop = tmp;
22266 }
22267 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
22268 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
22269 &fixed, &defValue, &defVal))) {
22270 xmlSchemaAttrStatePtr tmp;
22271 /*
22272 * Handle non existent default/fixed attributes.
22273 */
22274 tmp = (xmlSchemaAttrStatePtr)
22275 xmlMalloc(sizeof(xmlSchemaAttrState));
22276 if (tmp == NULL) {
22277 xmlSchemaVErrMemory(ctxt,
22278 "registering schema specified attributes", NULL);
22279 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022280 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022281 }
22282 tmp->attr = NULL;
22283 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
22284 tmp->decl = attrDecl;
22285 tmp->value = defValue;
22286 tmp->next = NULL;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022287 if (defAttrStatesTop == NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022288 defAttrStates = tmp;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022289 else
22290 defAttrStatesTop->next = tmp;
22291 defAttrStatesTop = tmp;
22292 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022293 }
22294 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000022295 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022296 /*
22297 * Add required attributes to the attribute states of the context.
22298 */
22299 if (reqAttrStates != NULL) {
22300 if (ctxt->attr == NULL) {
22301 ctxt->attr = reqAttrStates;
22302 } else {
22303 ctxt->attrTop->next = reqAttrStates;
22304 }
22305 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000022306 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022307 /*
22308 * Process wildcards.
22309 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022310
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022311 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022312#ifdef DEBUG_ATTR_VALIDATION
22313 xmlSchemaWildcardNsPtr ns;
22314 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022315 if (type->attributeWildcard->processContents ==
22316 XML_SCHEMAS_ANY_LAX)
22317 printf("processContents: lax\n");
22318 else if (type->attributeWildcard->processContents ==
22319 XML_SCHEMAS_ANY_STRICT)
22320 printf("processContents: strict\n");
22321 else
22322 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022323 if (type->attributeWildcard->any)
22324 printf("type: any\n");
22325 else if (type->attributeWildcard->negNsSet != NULL) {
22326 printf("type: negated\n");
22327 if (type->attributeWildcard->negNsSet->value == NULL)
22328 printf("ns: (absent)\n");
22329 else
22330 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
22331 } else if (type->attributeWildcard->nsSet != NULL) {
22332 printf("type: set\n");
22333 ns = type->attributeWildcard->nsSet;
22334 while (ns != NULL) {
22335 if (ns->value == NULL)
22336 printf("ns: (absent)\n");
22337 else
22338 printf("ns: %s\n", ns->value);
22339 ns = ns->next;
22340 }
22341 } else
22342 printf("empty\n");
22343
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022344
22345#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000022346 curState = ctxt->attr;
22347 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022348 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
22349 if (curState->attr->ns != NULL)
22350 nsURI = curState->attr->ns->href;
22351 else
22352 nsURI = NULL;
22353 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
22354 nsURI)) {
22355 /*
22356 * Handle processContents.
22357 */
22358 if ((type->attributeWildcard->processContents ==
22359 XML_SCHEMAS_ANY_LAX) ||
22360 (type->attributeWildcard->processContents ==
22361 XML_SCHEMAS_ANY_STRICT)) {
22362
22363 attr = curState->attr;
22364 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022365 attr->name, nsURI);
22366 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022367 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022368 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022369 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22370 /* TODO
22371 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
22372 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022373 } else if (type->attributeWildcard->processContents ==
22374 XML_SCHEMAS_ANY_LAX) {
22375 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022376 } else
22377 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022378 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000022379 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022380 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022381 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022382 curState = curState->next;
22383 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022384 }
22385
Daniel Veillardc0826a72004-08-10 14:17:33 +000022386 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022387 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022388
22389 /*
22390 * Validate the value of the attribute.
22391 */
22392 if (ctxt->value != NULL) {
22393 xmlSchemaFreeValue(ctxt->value);
22394 ctxt->value = NULL;
22395 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022396 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022397 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022398 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022399 switch (curState->state) {
22400 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022401
22402 /*
22403 * Create an attribute info if needed.
22404 */
22405 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022406 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22407 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022408 if (ctxt->attrInfo == NULL) {
22409 xmlSchemaVErrMemory(ctxt,
22410 "allocating an attribute info", NULL);
22411 goto fatal_exit;
22412 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000022413 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022414 }
22415 /*
22416 * Init the attribute info.
22417 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000022418 if (ctxt->attrInfo->value != NULL) {
22419 xmlSchemaFreeValue(ctxt->attrInfo->value);
22420 ctxt->attrInfo->value = NULL;
22421 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022422 ctxt->attrInfo->flags = 0;
22423 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
22424 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022425 if (curState->decl != NULL)
22426 ctxt->attrInfo->typeDef = curState->decl->subtypes;
22427 else
22428 ctxt->attrInfo->typeDef = NULL;
22429 if (curState->attr->ns != NULL)
22430 ctxt->attrInfo->namespaceName =
22431 curState->attr->ns->href;
22432 else
22433 ctxt->attrInfo->namespaceName = NULL;
22434 ctxt->attrInfo->localName = curState->attr->name;
22435
22436 ctxt->nodeInfo = ctxt->attrInfo;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022437 /*
22438 * Evaluate IDCs.
22439 */
22440 if (ctxt->xpathStates != NULL) {
22441 ret = xmlSchemaXPathEvaluate(ctxt,
22442 XML_ATTRIBUTE_NODE);
22443 if (ret == -1)
22444 goto fatal_exit;
22445 }
22446
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022447 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022448 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022449 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022450 if ((ret != 0) && (ctxt->value != NULL)) {
22451 xmlSchemaFreeValue(ctxt->value);
22452 ctxt->value = NULL;
22453 }
22454 /* No break on purpose. */
22455 case XML_SCHEMAS_ATTR_CHECKED:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022456 if (ctxt->xpathStates != NULL) {
22457 /*
22458 * Evaluate IDCs.
22459 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022460 if (ctxt->value != NULL) {
22461 ctxt->attrInfo->value = ctxt->value;
22462 ctxt->value = NULL;
22463 }
22464 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22465 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022466 }
22467 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022468 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022469 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022470 }
22471 curState = curState->next;
22472 }
22473
22474 /*
22475 * Report missing and illegal attributes.
22476 */
22477 curState = ctxt->attr;
22478 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000022479 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
22480 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022481 if (curState->decl != NULL) {
22482 if (curState->decl->ref != NULL)
22483 attrDecl = curState->decl->refDecl;
22484 else
22485 attrDecl = curState->decl;
22486 } else
22487 attrDecl = NULL;
22488 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
22489 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
22490 } else if (curState->state ==
22491 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
22492 xmlSchemaVCustomErr(ctxt,
22493 XML_SCHEMAV_CVC_ATTRIBUTE_2,
22494 (xmlNodePtr) attr,
22495 (xmlSchemaTypePtr) attrDecl,
22496 "The type definition is absent",
22497 NULL);
22498 } else if (curState->state ==
22499 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
22500 xmlSchemaVCustomErr(ctxt,
22501 XML_SCHEMAV_CVC_AU,
22502 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
22503 "The value does not match the fixed value "
22504 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022505 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
22506 xmlSchemaVWildcardErr(ctxt,
22507 XML_SCHEMAV_CVC_WILDCARD,
22508 (xmlNodePtr) attr,
22509 type->attributeWildcard,
22510 "No global attribute declaration found, but "
22511 "stipulated by the strict processContents of "
22512 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022513 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000022514 /* TODO: "prohibited" won't ever be touched here!.
22515 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
22516 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022517 /*
22518 * TODO: One might report different error messages
22519 * for the following errors.
22520 */
22521 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000022522 xmlSchemaVIllegalAttrErr(ctxt,
22523 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
22524 } else {
22525 xmlSchemaVIllegalAttrErr(ctxt,
22526 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
22527 }
22528 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022529 }
22530 curState = curState->next;
22531 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022532 }
22533
22534 /*
22535 * Add missing default/fixed attributes.
22536 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022537 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022538 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022539
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022540 while (curState != NULL) {
22541 attrDecl = curState->decl;
22542 if (attrDecl->ref != NULL)
22543 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022544 /*
22545 * Evaluate IDCs on default attributes.
22546 */
22547 if (ctxt->xpathStates != NULL) {
22548 /*
22549 * Create an attribute info if needed.
22550 */
22551 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022552 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22553 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022554 if (ctxt->attrInfo == NULL) {
22555 xmlSchemaVErrMemory(ctxt,
22556 "allocating an attribute info", NULL);
22557 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022558 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022559 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022560 }
22561 /*
22562 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022563 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022564 */
22565 ctxt->attrInfo->flags = 0;
22566 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
22567 ctxt->attrInfo->node = NULL;
22568 ctxt->attrInfo->typeDef = attrDecl->subtypes;
22569 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
22570 ctxt->attrInfo->localName = attrDecl->name;
22571
22572 ctxt->nodeInfo = ctxt->attrInfo;
22573
22574 ret = xmlSchemaXPathEvaluate(ctxt,
22575 XML_ATTRIBUTE_NODE);
22576 if (ret == -1)
22577 goto fatal_exit;
22578 if (ctxt->attrInfo->value != NULL) {
22579 xmlSchemaFreeValue(ctxt->attrInfo->value);
22580 ctxt->attrInfo->value = NULL;
22581 }
22582 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022583 /*
22584 * IDCs will consume the precomputed default value,
22585 * so we need to clone it somehow.
22586 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022587 /*
22588 * string or anySimpleType does not create a precomputed value
22589 * by default, so it will be created here on demand.
22590 * TODO: default/fixed attributes are a bit unoptimized:
22591 * the string value will be hold by ->defValue and inside
22592 * the precomputed value.
22593 */
22594 if (attrDecl->defVal == NULL) {
22595 xmlChar *str = xmlStrdup(attrDecl->defValue);
22596
22597 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022598 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022599 str,
22600 &(attrDecl->defVal)) == -1) {
22601 FREE_AND_NULL(str)
22602 goto fatal_exit;
22603 }
22604 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022605 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
22606 /* TODO: error on NULL return. */
22607 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022608
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022609 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22610 goto fatal_exit;
22611 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022612
22613 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
22614 /*
22615 * PSVI: Add a new attribute node to the current element.
22616 */
22617 if (attrDecl->targetNamespace == NULL) {
22618 xmlNewProp(elem, attrDecl->name, curState->value);
22619 } else {
22620 xmlNsPtr ns;
22621
22622 ns = xmlSearchNsByHref(elem->doc, elem,
22623 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022624 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022625 xmlChar prefix[12];
22626 int counter = 1;
22627
22628 attr = curState->attr;
22629 /*
22630 * Create a namespace declaration on the validation
22631 * root node if no namespace declaration is in scope.
22632 */
22633 snprintf((char *) prefix, sizeof(prefix), "p");
22634 /*
22635 * This is somehow not performant, since the ancestor
22636 * axis beyond @elem will be searched as well.
22637 */
22638 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
22639 while (ns != NULL) {
22640 if (counter > 1000) {
22641 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
22642 XML_SCHEMAV_INTERNAL,
22643 "Internal error: xmlSchemaValidateAttributes, "
22644 "could not compute a ns prefix for "
22645 "default/fixed attribute '%s'.\n",
22646 attrDecl->name, NULL);
22647
22648 break;
22649 }
22650 snprintf((char *) prefix,
22651 sizeof(prefix), "p%d", counter++);
22652 ns = xmlSearchNs(elem->doc, elem,
22653 BAD_CAST prefix);
22654 }
22655 if (ns == NULL) {
22656 ns = xmlNewNs(ctxt->validationRoot,
22657 attrDecl->targetNamespace, BAD_CAST prefix);
22658 xmlNewNsProp(elem, ns, attrDecl->name,
22659 curState->value);
22660 }
22661 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022662 xmlNewNsProp(elem, ns, attrDecl->name,
22663 curState->value);
22664 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022665 }
22666 }
22667 curState = curState->next;
22668 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022669 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022670 ret = ctxt->err;
22671 goto exit;
22672
22673fatal_exit:
22674 ret = -1;
22675
22676exit:
22677
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022678 if (defAttrStates != NULL)
22679 xmlSchemaFreeAttributeStates(defAttrStates);
22680
Daniel Veillard3646d642004-06-02 19:19:14 +000022681#ifdef DEBUG_ATTR_VALIDATION
22682 if (redundant)
22683 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022684 "xmlSchemaValidateAttributes: redundant call by "
22685 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000022686#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022687 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022688 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022689 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022690}
22691
22692/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022693 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000022694 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000022695 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022696 * The starting point of the validation, called by
22697 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000022698 *
22699 * Returns 0 if the element is schemas valid, a positive error code
22700 * number otherwise and -1 in case of internal or API error.
22701 */
22702static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022703xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022704{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022705 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022706 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022707
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022708 ctxt->err = 0;
22709 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022710 if (ctxt->schema == NULL) {
22711 /*
22712 * No schema was specified at time of creation of the validation
22713 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
22714 * of the instance to build a schema.
22715 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022716 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022717 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
22718 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022719 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
22720 if (ctxt->schema == NULL)
22721 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022722 ctxt->xsiAssemble = 1;
22723 } else
22724 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022725 /*
22726 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000022727 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022728 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022729 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
22730 if (ret == -1) {
22731 xmlSchemaVCustomErr(ctxt,
22732 XML_SCHEMAV_INTERNAL,
22733 ctxt->node, NULL,
22734 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022735 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022736 }
22737 /*
22738 * NOTE: We won't react on schema parser errors here.
22739 * TODO: But a warning would be nice.
22740 */
22741 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022742 if (ret != -1) {
22743 if (ctxt->node->ns != NULL)
22744 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
22745 ctxt->node->ns->href);
22746 else
22747 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
22748
22749 if (elemDecl == NULL) {
22750 xmlSchemaVCustomErr(ctxt,
22751 XML_SCHEMAV_CVC_ELT_1,
22752 ctxt->node, NULL,
22753 "No matching global declaration available", NULL);
22754 ret = XML_SCHEMAV_CVC_ELT_1;
22755 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022756 /*
22757 * Augment the IDC definitions.
22758 */
22759 if (ctxt->schema->idcDef != NULL) {
22760 xmlHashScan(ctxt->schema->idcDef,
22761 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
22762 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022763 ctxt->depth = -1;
22764 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022765 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022766 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022767 if (ret < 0) {
22768 xmlSchemaVCustomErr(ctxt,
22769 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
22770 "Internal error: xmlSchemaValidateElement, "
22771 "calling validation by declaration", NULL);
22772 }
22773 }
22774 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022775
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022776 if (ctxt->xsiAssemble) {
22777 if (ctxt->schema != NULL) {
22778 xmlSchemaFree(ctxt->schema);
22779 ctxt->schema = NULL;
22780 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022781 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022782 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022783 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022784}
22785
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022786
Daniel Veillard4255d502002-04-16 15:50:10 +000022787/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022788 * xmlSchemaValidateOneElement:
22789 * @ctxt: a schema validation context
22790 * @elem: an element node
22791 *
22792 * Validate a branch of a tree, starting with the given @elem.
22793 *
22794 * Returns 0 if the element and its subtree is valid, a positive error
22795 * code number otherwise and -1 in case of an internal or API error.
22796 */
22797int
22798xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
22799{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022800 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022801 return (-1);
22802
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022803 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022804 xmlSchemaVErr(ctxt, NULL,
22805 XML_SCHEMAV_INTERNAL,
22806 "API error: xmlSchemaValidateOneElement, "
22807 "no schema specified.\n", NULL, NULL);
22808 return (-1);
22809 }
22810
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022811 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022812 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022813 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022814 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000022815}
22816
22817/************************************************************************
22818 * *
22819 * SAX Validation code *
22820 * *
22821 ************************************************************************/
22822
22823/************************************************************************
22824 * *
22825 * Validation interfaces *
22826 * *
22827 ************************************************************************/
22828
22829/**
22830 * xmlSchemaNewValidCtxt:
22831 * @schema: a precompiled XML Schemas
22832 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022833 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000022834 *
22835 * Returns the validation context or NULL in case of error
22836 */
22837xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022838xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
22839{
Daniel Veillard4255d502002-04-16 15:50:10 +000022840 xmlSchemaValidCtxtPtr ret;
22841
22842 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
22843 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022844 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000022845 return (NULL);
22846 }
22847 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000022848 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000022849 return (ret);
22850}
22851
22852/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022853 * xmlSchemaClearValidCtxt:
22854 * @ctxt: the schema validation context
22855 *
22856 * Free the resources associated to the schema validation context;
22857 * leaves some fields alive intended for reuse of the context.
22858 */
22859static void
22860xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
22861{
22862 if (vctxt == NULL)
22863 return;
22864
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022865 vctxt->flags = 0;
22866
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022867 vctxt->validationRoot = NULL;
22868 if (vctxt->attr != NULL) {
22869 xmlSchemaFreeAttributeStates(vctxt->attr);
22870 vctxt->attr = NULL;
22871 }
22872 if (vctxt->value != NULL) {
22873 xmlSchemaFreeValue(vctxt->value);
22874 vctxt->value = NULL;
22875 }
22876 /*
22877 * Augmented IDC information.
22878 */
22879 if (vctxt->aidcs != NULL) {
22880 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
22881 do {
22882 next = cur->next;
22883 xmlFree(cur);
22884 cur = next;
22885 } while (cur != NULL);
22886 vctxt->aidcs = NULL;
22887 }
22888 if (vctxt->idcNodes != NULL) {
22889 int i;
22890 xmlSchemaPSVIIDCNodePtr item;
22891
22892 for (i = 0; i < vctxt->nbIdcNodes; i++) {
22893 item = vctxt->idcNodes[i];
22894 xmlFree(item->keys);
22895 xmlFree(item);
22896 }
22897 xmlFree(vctxt->idcNodes);
22898 vctxt->idcNodes = NULL;
22899 }
22900 /*
22901 * Note that we won't delete the XPath state pool here.
22902 */
22903 if (vctxt->xpathStates != NULL) {
22904 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
22905 vctxt->xpathStates = NULL;
22906 }
22907 if (vctxt->attrInfo != NULL) {
22908 if (vctxt->attrInfo->value != NULL) {
22909 xmlSchemaFreeValue(vctxt->attrInfo->value);
22910 }
22911 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
22912 }
22913 if (vctxt->elemInfos != NULL) {
22914 int i;
22915 xmlSchemaNodeInfoPtr info;
22916
22917 for (i = 0; i < vctxt->sizeElemInfos; i++) {
22918 info = vctxt->elemInfos[i];
22919 if (info == NULL)
22920 break;
22921 if (info->value != NULL) {
22922 xmlSchemaFreeValue(info->value);
22923 info->value = NULL;
22924 }
22925 if (info->idcMatchers != NULL) {
22926 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
22927 info->idcMatchers = NULL;
22928 }
22929 if (info->idcTable != NULL) {
22930 xmlSchemaIDCFreeIDCTable(info->idcTable);
22931 info->idcTable = NULL;
22932 }
22933 }
22934 }
22935}
22936
22937/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022938 * xmlSchemaFreeValidCtxt:
22939 * @ctxt: the schema validation context
22940 *
22941 * Free the resources associated to the schema validation context
22942 */
22943void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022944xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
22945{
Daniel Veillard4255d502002-04-16 15:50:10 +000022946 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022947 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022948 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000022949 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000022950 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022951 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022952 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022953 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022954 if (ctxt->idcNodes != NULL) {
22955 int i;
22956 xmlSchemaPSVIIDCNodePtr item;
22957
22958 for (i = 0; i < ctxt->nbIdcNodes; i++) {
22959 item = ctxt->idcNodes[i];
22960 xmlFree(item->keys);
22961 xmlFree(item);
22962 }
22963 xmlFree(ctxt->idcNodes);
22964 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022965 if (ctxt->idcKeys != NULL) {
22966 int i;
22967 for (i = 0; i < ctxt->nbIdcKeys; i++)
22968 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
22969 xmlFree(ctxt->idcKeys);
22970 }
22971
22972 if (ctxt->xpathStates != NULL)
22973 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
22974 if (ctxt->xpathStatePool != NULL)
22975 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
22976
22977 /*
22978 * Augmented IDC information.
22979 */
22980 if (ctxt->aidcs != NULL) {
22981 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
22982 do {
22983 next = cur->next;
22984 xmlFree(cur);
22985 cur = next;
22986 } while (cur != NULL);
22987 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022988 if (ctxt->attrInfo != NULL) {
22989 if (ctxt->attrInfo->value != NULL)
22990 xmlSchemaFreeValue(ctxt->attrInfo->value);
22991 xmlFree(ctxt->attrInfo);
22992 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022993 if (ctxt->elemInfos != NULL) {
22994 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022995 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022996
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022997 for (i = 0; i < ctxt->sizeElemInfos; i++) {
22998 info = ctxt->elemInfos[i];
22999 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023000 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023001 if (info->value != NULL)
23002 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023003 if (info->idcMatchers != NULL)
23004 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023005 if (info->idcTable != NULL)
23006 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023007 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023008 * TODO: Don't know if those will have to be freed if in streaming
23009 * mode.
23010 *
23011 * xmlFree(info->localName);
23012 * if (info->namespaceName != NULL)
23013 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023014 */
23015 xmlFree(info);
23016 }
23017 xmlFree(ctxt->elemInfos);
23018 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023019 xmlFree(ctxt);
23020}
23021
23022/**
23023 * xmlSchemaSetValidErrors:
23024 * @ctxt: a schema validation context
23025 * @err: the error function
23026 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023027 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023028 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023029 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023030 */
23031void
23032xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023033 xmlSchemaValidityErrorFunc err,
23034 xmlSchemaValidityWarningFunc warn, void *ctx)
23035{
Daniel Veillard4255d502002-04-16 15:50:10 +000023036 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023037 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023038 ctxt->error = err;
23039 ctxt->warning = warn;
23040 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023041 if (ctxt->pctxt != NULL)
23042 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023043}
23044
23045/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023046 * xmlSchemaGetValidErrors:
23047 * @ctxt: a XML-Schema validation context
23048 * @err: the error function result
23049 * @warn: the warning function result
23050 * @ctx: the functions context result
23051 *
23052 * Get the error and warning callback informations
23053 *
23054 * Returns -1 in case of error and 0 otherwise
23055 */
23056int
23057xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23058 xmlSchemaValidityErrorFunc * err,
23059 xmlSchemaValidityWarningFunc * warn, void **ctx)
23060{
23061 if (ctxt == NULL)
23062 return (-1);
23063 if (err != NULL)
23064 *err = ctxt->error;
23065 if (warn != NULL)
23066 *warn = ctxt->warning;
23067 if (ctx != NULL)
23068 *ctx = ctxt->userData;
23069 return (0);
23070}
23071
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023072
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023073/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023074 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023075 * @ctxt: a schema validation context
23076 * @options: a combination of xmlSchemaValidOption
23077 *
23078 * Sets the options to be used during the validation.
23079 *
23080 * Returns 0 in case of success, -1 in case of an
23081 * API error.
23082 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023083int
23084xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23085 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023086
23087{
23088 int i;
23089
23090 if (ctxt == NULL)
23091 return (-1);
23092 /*
23093 * WARNING: Change the start value if adding to the
23094 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023095 * TODO: Is there an other, more easy to maintain,
23096 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023097 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023098 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023099 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023100 xmlSchemaVErr(ctxt, NULL,
23101 XML_SCHEMAV_INTERNAL,
23102 "Internal error: xmlSchemaSetValidOptions, "
23103 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023104 return (-1);
23105 }
23106 }
23107 ctxt->options = options;
23108 return (0);
23109}
23110
23111/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023112 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023113 * @ctxt: a schema validation context
23114 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023115 * Get the validation context options.
23116 *
23117 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023118 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023119int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023120xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
23121
23122{
23123 if (ctxt == NULL)
23124 return (-1);
23125 else
23126 return (ctxt->options);
23127}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023128
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023129
Daniel Veillard259f0df2004-08-18 09:13:18 +000023130/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023131 * xmlSchemaValidateDoc:
23132 * @ctxt: a schema validation context
23133 * @doc: a parsed document tree
23134 *
23135 * Validate a document tree in memory.
23136 *
23137 * Returns 0 if the document is schemas valid, a positive error code
23138 * number otherwise and -1 in case of internal or API error.
23139 */
23140int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023141xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23142{
Daniel Veillard4255d502002-04-16 15:50:10 +000023143 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023144 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023145
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023146 ctxt->doc = doc;
23147 ctxt->node = xmlDocGetRootElement(doc);
23148 if (ctxt->node == NULL) {
23149 xmlSchemaVCustomErr(ctxt,
23150 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23151 (xmlNodePtr) doc, NULL,
23152 "The document has no document element", NULL);
23153 return (ctxt->err);
23154 }
23155 ctxt->validationRoot = ctxt->node;
23156 xmlSchemaStartValidation(ctxt);
23157
23158 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000023159}
23160
23161/**
23162 * xmlSchemaValidateStream:
23163 * @ctxt: a schema validation context
23164 * @input: the input to use for reading the data
23165 * @enc: an optional encoding information
23166 * @sax: a SAX handler for the resulting events
23167 * @user_data: the context to provide to the SAX handler.
23168 *
23169 * Validate a document tree in memory.
23170 *
23171 * Returns 0 if the document is schemas valid, a positive error code
23172 * number otherwise and -1 in case of internal or API error.
23173 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023174int
Daniel Veillard4255d502002-04-16 15:50:10 +000023175xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023176 xmlParserInputBufferPtr input, xmlCharEncoding enc,
23177 xmlSAXHandlerPtr sax, void *user_data)
23178{
Daniel Veillard4255d502002-04-16 15:50:10 +000023179 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023180 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023181 ctxt->input = input;
23182 ctxt->enc = enc;
23183 ctxt->sax = sax;
23184 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023185 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023186}
23187
Daniel Veillard5d4644e2005-04-01 13:11:58 +000023188#define bottom_xmlschemas
23189#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000023190#endif /* LIBXML_SCHEMAS_ENABLED */