blob: b29de7b07b0177bf728987e8b15695043990cd77 [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. Buchcik187ea5f2005-04-19 11:25:43 +000065/* #define ENABLE_PARTICLE_RESTRICTION 1 */
66
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000067#define DUMP_CONTENT_MODEL
68
Daniel Veillardc0826a72004-08-10 14:17:33 +000069
Daniel Veillard4255d502002-04-16 15:50:10 +000070#define UNBOUNDED (1 << 30)
71#define TODO \
72 xmlGenericError(xmlGenericErrorContext, \
73 "Unimplemented block at %s:%d\n", \
74 __FILE__, __LINE__);
75
William M. Brack2f2a6632004-08-20 23:09:47 +000076#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000077
Daniel Veillard4255d502002-04-16 15:50:10 +000078/*
79 * The XML Schemas namespaces
80 */
81static const xmlChar *xmlSchemaNs = (const xmlChar *)
82 "http://www.w3.org/2001/XMLSchema";
83
84static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
85 "http://www.w3.org/2001/XMLSchema-instance";
86
Daniel Veillardc0826a72004-08-10 14:17:33 +000087static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
88 "Element decl.";
89static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
90 "Element ref.";
91static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
92 "Attribute decl.";
93static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
94 "Attribute ref.";
95static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000096 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000098 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000099static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
100 "Model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000101#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000102static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
103 "Model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000104#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000105
Daniel Veillard4255d502002-04-16 15:50:10 +0000106#define IS_SCHEMA(node, type) \
107 ((node != NULL) && (node->ns != NULL) && \
108 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
109 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
110
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111#define FREE_AND_NULL(str) \
112 if (str != NULL) { \
113 xmlFree(str); \
114 str = NULL; \
115 }
116
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000117#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000118 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
119 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000120
121#define IS_COMPLEX_TYPE(item) \
122 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
123 (item->builtInType == XML_SCHEMAS_ANYTYPE))
124
125#define IS_SIMPLE_TYPE(item) \
126 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
127 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
128 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
129
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000130#define IS_ANY_SIMPLE_TYPE(item) \
131 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
132 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
133
134#define IS_NOT_TYPEFIXED(item) \
135 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
136 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
137
138#define HAS_COMPLEX_CONTENT(item) \
139 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
140 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
141 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
142
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000143#define HAS_SIMPLE_CONTENT(item) \
144 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
145 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
146
147#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
148
149#define IS_PARTICLE_EMPTIABLE(item) \
150 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
151
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000152#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
153
154#define IS_MODEL_GROUP(item) \
155 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
156 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
157 (item->type == XML_SCHEMA_TYPE_ALL))
158
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000159#define ELEM_TYPE(item) item->subtypes
160
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000161#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
162
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000163#define SUBST_GROUP_AFF(item) item->refDecl
164
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000165#if 0
166#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
167#endif
168
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000169#define SUBSET_RESTRICTION 1<<0
170#define SUBSET_EXTENSION 1<<1
171#define SUBSET_SUBSTITUTION 1<<2
172#define SUBSET_LIST 1<<3
173#define SUBSET_UNION 1<<4
174
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000175/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000176#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
177#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
178#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000179*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000180
Daniel Veillard4255d502002-04-16 15:50:10 +0000181#define XML_SCHEMAS_PARSE_ERROR 1
182
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000183#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
184
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000185
186/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000187* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
188* locate schemata to be imported
189* using the namespace name; otherwise
190* the location URI will be used */
191
192/*
193* xmlSchemaParserOption:
194*
195* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000197typedef enum {
198 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000199 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000200 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000201 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000202} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000203*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000204
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000205typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000206typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000207
208typedef struct _xmlSchemaItemList xmlSchemaItemList;
209typedef xmlSchemaItemList *xmlSchemaItemListPtr;
210
211struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000212 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000213 int nbItems; /* used for dynamic addition of schemata */
214 int sizeItems; /* used for dynamic addition of schemata */
215};
216
Daniel Veillard4255d502002-04-16 15:50:10 +0000217struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000218 void *userData; /* user specific data block */
219 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
220 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000221 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000222 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000223 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000224
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000225 xmlSchemaPtr topschema; /* The main schema */
226 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
227
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000228 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000229 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000230 int counter;
231
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000232 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000233 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000234 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000235
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000236 const char *buffer;
237 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000238
Daniel Veillard4255d502002-04-16 15:50:10 +0000239 /*
240 * Used to build complex element content models
241 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000243 xmlAutomataStatePtr start;
244 xmlAutomataStatePtr end;
245 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000246
247 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000248 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000249 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
250 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 xmlSchemaAssemblePtr assemble;
252 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000253 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000254 const xmlChar **localImports; /* list of locally imported namespaces */
255 int sizeLocalImports;
256 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000257 xmlHashTablePtr substGroups;
Daniel Veillard4255d502002-04-16 15:50:10 +0000258};
259
260
261#define XML_SCHEMAS_ATTR_UNKNOWN 1
262#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000263#define XML_SCHEMAS_ATTR_PROHIBITED 3
264#define XML_SCHEMAS_ATTR_MISSING 4
265#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
266#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000267#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
268#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000269#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
270#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000271
272typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
273typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
274struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000275 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000276 xmlAttrPtr attr;
277 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000278 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000279 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000280};
281
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000282/**
283 * xmlSchemaBasicItem:
284 *
285 * The abstract base type for schema components.
286 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000287typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
288typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
289struct _xmlSchemaBasicItem {
290 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000291};
292
293/**
294 * xmlSchemaAnnotItem:
295 *
296 * The abstract base type for annotated schema components.
297 * (Extends xmlSchemaBasicItem)
298 */
299typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
300typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
301struct _xmlSchemaAnnotItem {
302 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000303 xmlSchemaAnnotPtr annot;
304};
305
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000306/**
307 * xmlSchemaTreeItem:
308 *
309 * The abstract base type for tree-like structured schema components.
310 * (Extends xmlSchemaAnnotItem)
311 */
312typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
313typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
314struct _xmlSchemaTreeItem {
315 xmlSchemaTypeType type;
316 xmlSchemaAnnotPtr annot;
317 xmlSchemaTreeItemPtr next;
318 xmlSchemaTreeItemPtr children;
319};
320
321/**
322 * xmlSchemaQNameRef:
323 *
324 * A component reference item (not a schema component)
325 * (Extends xmlSchemaBasicItem)
326 */
327typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
328typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
329struct _xmlSchemaQNameRef {
330 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000331 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000332 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000333 const xmlChar *name;
334 const xmlChar *targetNamespace;
335};
336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000337/**
338 * xmlSchemaParticle:
339 *
340 * A particle component.
341 * (Extends xmlSchemaTreeItem)
342 */
343typedef struct _xmlSchemaParticle xmlSchemaParticle;
344typedef xmlSchemaParticle *xmlSchemaParticlePtr;
345struct _xmlSchemaParticle {
346 xmlSchemaTypeType type;
347 xmlSchemaAnnotPtr annot;
348 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
349 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
350 int minOccurs;
351 int maxOccurs;
352 xmlNodePtr node;
353};
354
355/**
356 * xmlSchemaModelGroup:
357 *
358 * A model group component.
359 * (Extends xmlSchemaTreeItem)
360 */
361typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
362typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
363struct _xmlSchemaModelGroup {
364 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
365 xmlSchemaAnnotPtr annot;
366 xmlSchemaTreeItemPtr next; /* not used */
367 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
368 xmlNodePtr node;
369};
370
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000371#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000372/**
373 * xmlSchemaModelGroupDef:
374 *
375 * A model group definition component.
376 * (Extends xmlSchemaTreeItem)
377 */
378typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
379typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
380struct _xmlSchemaModelGroupDef {
381 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
382 xmlSchemaAnnotPtr annot;
383 xmlSchemaTreeItemPtr next; /* not used */
384 xmlSchemaTreeItemPtr children; /* the "model group" */
385 const xmlChar *name;
386 const xmlChar *targetNamespace;
387 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000388 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000389};
390
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000391typedef struct _xmlSchemaIDC xmlSchemaIDC;
392typedef xmlSchemaIDC *xmlSchemaIDCPtr;
393
394/**
395 * xmlSchemaIDCSelect:
396 *
397 * The identity-constraint "field" and "selector" item, holding the
398 * XPath expression.
399 */
400typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
401typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
402struct _xmlSchemaIDCSelect {
403 xmlSchemaIDCSelectPtr next;
404 xmlSchemaIDCPtr idc;
405 int index; /* an index position if significant for IDC key-sequences */
406 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000407 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000408};
409
410/**
411 * xmlSchemaIDC:
412 *
413 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000414 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000415 */
416
417struct _xmlSchemaIDC {
418 xmlSchemaTypeType type;
419 xmlSchemaAnnotPtr annot;
420 xmlSchemaIDCPtr next;
421 xmlNodePtr node;
422 const xmlChar *name;
423 const xmlChar *targetNamespace;
424 xmlSchemaIDCSelectPtr selector;
425 xmlSchemaIDCSelectPtr fields;
426 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000427 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000428};
429
430/**
431 * xmlSchemaIDCAug:
432 *
433 * The augmented IDC information used for validation.
434 */
435typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
436typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
437struct _xmlSchemaIDCAug {
438 xmlSchemaIDCAugPtr next; /* next in a list */
439 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000440 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000441 tables need to be bubbled upwards */
442};
443
444/**
445 * xmlSchemaPSVIIDCKeySequence:
446 *
447 * The key sequence of a node table item.
448 */
449typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
450typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
451struct _xmlSchemaPSVIIDCKey {
452 xmlSchemaTypePtr type;
453 xmlSchemaValPtr compValue;
454};
455
456/**
457 * xmlSchemaPSVIIDCNode:
458 *
459 * The node table item of a node table.
460 */
461typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
462typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
463struct _xmlSchemaPSVIIDCNode {
464 xmlNodePtr node;
465 xmlSchemaPSVIIDCKeyPtr *keys;
466};
467
468/**
469 * xmlSchemaPSVIIDCBinding:
470 *
471 * The identity-constraint binding item of the [identity-constraint table].
472 */
473typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
474typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
475struct _xmlSchemaPSVIIDCBinding {
476 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
477 xmlSchemaIDCPtr definition; /* the IDC definition */
478 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
479 int nbNodes; /* number of entries in the node table */
480 int sizeNodes; /* size of the node table */
481 int nbDupls; /* number of already identified duplicates in the node
482 table */
483 /* int nbKeys; number of keys in each key-sequence */
484};
485
486#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
487#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
488
489#define XPATH_STATE_OBJ_MATCHES -2
490#define XPATH_STATE_OBJ_BLOCKED -3
491
492typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
493typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
494
495/**
496 * xmlSchemaIDCStateObj:
497 *
498 * The state object used to evaluate XPath expressions.
499 */
500typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
501typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
502struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000503 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000504 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000505 int depth; /* depth of creation */
506 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000507 int nbHistory;
508 int sizeHistory;
509 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
510 matcher */
511 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000512 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000513};
514
515#define IDC_MATCHER 0
516
517/**
518 * xmlSchemaIDCMatcher:
519 *
520 * Used to IDC selectors (and fields) successively.
521 */
522struct _xmlSchemaIDCMatcher {
523 int type;
524 int depth; /* the tree depth at creation time */
525 xmlSchemaIDCMatcherPtr next; /* next in the list */
526 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
527 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
528 elements */
529 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000530 int targetDepth;
531};
532
533/*
534* Element info flags.
535*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000536#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
537/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
538/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000539
540/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000541 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000542 *
543 * Holds information of an element node.
544 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000545typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
546typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
547struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000549 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000550 xmlNodePtr node;
551 const xmlChar *localName;
552 const xmlChar *namespaceName;
553 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000554 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlSchemaValPtr value; /* the pre-computed value if any */
556 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
557 for the scope element*/
558 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
559 element */
560};
561
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000562/* #define XML_SCHEMA_VALID_INVALID_NEG_WILDCARD 1<<0 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000563
Daniel Veillard4255d502002-04-16 15:50:10 +0000564/**
565 * xmlSchemaValidCtxt:
566 *
567 * A Schemas validation context
568 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000569struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000570 void *userData; /* user specific data block */
571 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000572 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000573 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000574
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000575 xmlSchemaPtr schema; /* The schema in use */
576 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000577 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000578 xmlCharEncoding enc;
579 xmlSAXHandlerPtr sax;
580 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000581
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000582 xmlDocPtr myDoc;
583 int err;
584 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000585
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000586 xmlNodePtr node;
587 xmlNodePtr cur;
588 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000589
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000590 xmlRegExecCtxtPtr regexp;
591 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000592
Daniel Veillard3646d642004-06-02 19:19:14 +0000593 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000594 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000595 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000596 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000597 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000598 xmlNodePtr validationRoot;
599 xmlSchemaParserCtxtPtr pctxt;
600 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000601
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000602 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000603 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000604 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000605 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
606 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000607
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000608 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
609
610 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
611 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
612
613 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
614 int nbIdcNodes;
615 int sizeIdcNodes;
616
617 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
618 int nbIdcKeys;
619 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000620
621 int flags;
Daniel Veillard4255d502002-04-16 15:50:10 +0000622};
623
Daniel Veillard1d913862003-11-21 00:28:39 +0000624/*
625 * These are the entries in the schemas importSchemas hash table
626 */
627typedef struct _xmlSchemaImport xmlSchemaImport;
628typedef xmlSchemaImport *xmlSchemaImportPtr;
629struct _xmlSchemaImport {
630 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000631 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000632 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000633 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000634};
Daniel Veillard4255d502002-04-16 15:50:10 +0000635
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000636/*
637 * These are the entries associated to includes in a schemas
638 */
639typedef struct _xmlSchemaInclude xmlSchemaInclude;
640typedef xmlSchemaInclude *xmlSchemaIncludePtr;
641struct _xmlSchemaInclude {
642 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000643 const xmlChar *schemaLocation;
644 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000645 const xmlChar *origTargetNamespace;
646 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000647};
648
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000649/**
650 * xmlSchemaSubstGroup:
651 *
652 *
653 */
654typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
655typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
656struct _xmlSchemaSubstGroup {
657 xmlSchemaElementPtr head;
658 xmlSchemaItemListPtr members;
659};
660
Daniel Veillard4255d502002-04-16 15:50:10 +0000661/************************************************************************
662 * *
663 * Some predeclarations *
664 * *
665 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000666
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000667static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
668 xmlSchemaPtr schema,
669 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000670static void
671xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
672 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000673static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000674xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
675static int
676xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000677 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000678 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000679 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000680 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000681 int normalize,
682 int checkNodes);
683static int
684xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
685 xmlSchemaElementPtr elemDecl);
686static int
687xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000688 xmlSchemaWildcardPtr wild);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000689static int
690xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000691static int
692xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
693 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000694static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000695xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
696 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000697static void
698xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000699static int
700xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
701 xmlSchemaTypePtr type,
702 const xmlChar *value,
703 xmlSchemaValPtr *val);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000704static int
705xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000706static xmlSchemaTreeItemPtr
707xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
708 xmlNodePtr node, xmlSchemaTypeType type,
709 int withParticle);
710static const xmlChar *
711xmlSchemaCompTypeToString(xmlSchemaTypeType type);
712static xmlSchemaTypeLinkPtr
713xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000714
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000715/************************************************************************
716 * *
717 * Datatype error handlers *
718 * *
719 ************************************************************************/
720
721/**
722 * xmlSchemaPErrMemory:
723 * @node: a context node
724 * @extra: extra informations
725 *
726 * Handle an out of memory condition
727 */
728static void
729xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
730 const char *extra, xmlNodePtr node)
731{
732 if (ctxt != NULL)
733 ctxt->nberrors++;
734 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
735 extra);
736}
737
738/**
739 * xmlSchemaPErr:
740 * @ctxt: the parsing context
741 * @node: the context node
742 * @error: the error code
743 * @msg: the error message
744 * @str1: extra data
745 * @str2: extra data
746 *
747 * Handle a parser error
748 */
749static void
750xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
751 const char *msg, const xmlChar * str1, const xmlChar * str2)
752{
753 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000754 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000755 void *data = NULL;
756
757 if (ctxt != NULL) {
758 ctxt->nberrors++;
759 channel = ctxt->error;
760 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000761 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000762 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000763 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 error, XML_ERR_ERROR, NULL, 0,
765 (const char *) str1, (const char *) str2, NULL, 0, 0,
766 msg, str1, str2);
767}
768
769/**
770 * xmlSchemaPErr2:
771 * @ctxt: the parsing context
772 * @node: the context node
773 * @node: the current child
774 * @error: the error code
775 * @msg: the error message
776 * @str1: extra data
777 * @str2: extra data
778 *
779 * Handle a parser error
780 */
781static void
782xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
783 xmlNodePtr child, int error,
784 const char *msg, const xmlChar * str1, const xmlChar * str2)
785{
786 if (child != NULL)
787 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
788 else
789 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
790}
791
Daniel Veillard01fa6152004-06-29 17:04:39 +0000792
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000793/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000794 * xmlSchemaPErrExt:
795 * @ctxt: the parsing context
796 * @node: the context node
797 * @error: the error code
798 * @strData1: extra data
799 * @strData2: extra data
800 * @strData3: extra data
801 * @msg: the message
802 * @str1: extra parameter for the message display
803 * @str2: extra parameter for the message display
804 * @str3: extra parameter for the message display
805 * @str4: extra parameter for the message display
806 * @str5: extra parameter for the message display
807 *
808 * Handle a parser error
809 */
810static void
811xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
812 const xmlChar * strData1, const xmlChar * strData2,
813 const xmlChar * strData3, const char *msg, const xmlChar * str1,
814 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
815 const xmlChar * str5)
816{
817
818 xmlGenericErrorFunc channel = NULL;
819 xmlStructuredErrorFunc schannel = NULL;
820 void *data = NULL;
821
822 if (ctxt != NULL) {
823 ctxt->nberrors++;
824 channel = ctxt->error;
825 data = ctxt->userData;
826 schannel = ctxt->serror;
827 }
828 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
829 error, XML_ERR_ERROR, NULL, 0,
830 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000831 (const char *) strData3, 0, 0, msg, str1, str2,
832 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000833}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000834
Daniel Veillard3646d642004-06-02 19:19:14 +0000835
836/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000837 * xmlSchemaVTypeErrMemory:
838 * @node: a context node
839 * @extra: extra informations
840 *
841 * Handle an out of memory condition
842 */
843static void
844xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
845 const char *extra, xmlNodePtr node)
846{
847 if (ctxt != NULL) {
848 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000849 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000850 }
851 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
852 extra);
853}
854
855/**
856 * xmlSchemaVErr3:
857 * @ctxt: the validation context
858 * @node: the context node
859 * @error: the error code
860 * @msg: the error message
861 * @str1: extra data
862 * @str2: extra data
863 * @str3: extra data
864 *
865 * Handle a validation error
866 */
867static void
868xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
869 const char *msg, const xmlChar *str1, const xmlChar *str2,
870 const xmlChar *str3)
871{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000872 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000873 xmlGenericErrorFunc channel = NULL;
874 void *data = NULL;
875
876 if (ctxt != NULL) {
877 ctxt->nberrors++;
878 ctxt->err = error;
879 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000880 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000881 data = ctxt->userData;
882 }
883 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000884 /* Removed, since the old schema error codes have been
885 * substituted for the global error codes.
886 *
887 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
888 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000889 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000890 error, XML_ERR_ERROR, NULL, 0,
891 (const char *) str1, (const char *) str2,
892 (const char *) str3, 0, 0,
893 msg, str1, str2, str3);
894}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000895
896/**
897 * xmlSchemaVErrExt:
898 * @ctxt: the validation context
899 * @node: the context node
900 * @error: the error code
901 * @msg: the message
902 * @str1: extra parameter for the message display
903 * @str2: extra parameter for the message display
904 * @str3: extra parameter for the message display
905 * @str4: extra parameter for the message display
906 * @str5: extra parameter for the message display
907 *
908 * Handle a validation error
909 */
910static void
911xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
912 const char *msg, const xmlChar * str1,
913 const xmlChar * str2, const xmlChar * str3,
914 const xmlChar * str4, const xmlChar * str5)
915{
916 xmlStructuredErrorFunc schannel = NULL;
917 xmlGenericErrorFunc channel = NULL;
918 void *data = NULL;
919
920 if (ctxt != NULL) {
921 ctxt->nberrors++;
922 ctxt->err = error;
923 channel = ctxt->error;
924 schannel = ctxt->serror;
925 data = ctxt->userData;
926 }
927 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000928 /* Removed, since the old schema error codes have been
929 * substituted for the global error codes.
930 *
931 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
932 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000933 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000934 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
935 msg, str1, str2, str3, str4, str5);
936}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000937/**
938 * xmlSchemaVErr:
939 * @ctxt: the validation context
940 * @node: the context node
941 * @error: the error code
942 * @msg: the error message
943 * @str1: extra data
944 * @str2: extra data
945 *
946 * Handle a validation error
947 */
948static void
949xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
950 const char *msg, const xmlChar * str1, const xmlChar * str2)
951{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000952 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000953 xmlGenericErrorFunc channel = NULL;
954 void *data = NULL;
955
956 if (ctxt != NULL) {
957 ctxt->nberrors++;
958 ctxt->err = error;
959 channel = ctxt->error;
960 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000961 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000962 }
963 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000964 /* Removed, since the old schema error codes have been
965 * substituted for the global error codes.
966 *
967 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
968 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000969 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000970 error, XML_ERR_ERROR, NULL, 0,
971 (const char *) str1, (const char *) str2, NULL, 0, 0,
972 msg, str1, str2);
973}
Daniel Veillard4255d502002-04-16 15:50:10 +0000974
Daniel Veillardc0826a72004-08-10 14:17:33 +0000975/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000976 * xmlSchemaGetComponentNode:
977 * @item: a schema component
978 *
979 * Returns node associated with the schema component.
980 * NOTE that such a node need not be available; plus, a component's
981 * node need not to reflect the component directly, since there is no
982 * one-to-one relationship between the XML Schema representation and
983 * the component representation.
984 */
985static xmlNodePtr
986xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
987{
988 switch (item->type) {
989 case XML_SCHEMA_TYPE_ELEMENT:
990 return (((xmlSchemaElementPtr) item)->node);
991 case XML_SCHEMA_TYPE_ATTRIBUTE:
992 return (((xmlSchemaAttributePtr) item)->node);
993 case XML_SCHEMA_TYPE_COMPLEX:
994 case XML_SCHEMA_TYPE_SIMPLE:
995 return (((xmlSchemaTypePtr) item)->node);
996 case XML_SCHEMA_TYPE_ANY:
997 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
998 return (((xmlSchemaWildcardPtr) item)->node);
999 case XML_SCHEMA_TYPE_PARTICLE:
1000 return (((xmlSchemaParticlePtr) item)->node);
1001 case XML_SCHEMA_TYPE_SEQUENCE:
1002 case XML_SCHEMA_TYPE_CHOICE:
1003 case XML_SCHEMA_TYPE_ALL:
1004 return (((xmlSchemaModelGroupPtr) item)->node);
1005 case XML_SCHEMA_TYPE_GROUP:
1006 return (((xmlSchemaModelGroupDefPtr) item)->node);
1007 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1008 return (((xmlSchemaAttributeGroupPtr) item)->node);
1009 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1010 case XML_SCHEMA_TYPE_IDC_KEY:
1011 case XML_SCHEMA_TYPE_IDC_KEYREF:
1012 return (((xmlSchemaIDCPtr) item)->node);
1013 default:
1014 return (NULL);
1015 }
1016}
1017
1018#if 0
1019/**
1020 * xmlSchemaGetNextComponent:
1021 * @item: a schema component
1022 *
1023 * Returns the next sibling of the schema component.
1024 */
1025static xmlSchemaBasicItemPtr
1026xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1027{
1028 switch (item->type) {
1029 case XML_SCHEMA_TYPE_ELEMENT:
1030 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1031 case XML_SCHEMA_TYPE_ATTRIBUTE:
1032 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1033 case XML_SCHEMA_TYPE_COMPLEX:
1034 case XML_SCHEMA_TYPE_SIMPLE:
1035 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1036 case XML_SCHEMA_TYPE_ANY:
1037 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1038 return (NULL);
1039 case XML_SCHEMA_TYPE_PARTICLE:
1040 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1041 case XML_SCHEMA_TYPE_SEQUENCE:
1042 case XML_SCHEMA_TYPE_CHOICE:
1043 case XML_SCHEMA_TYPE_ALL:
1044 return (NULL);
1045 case XML_SCHEMA_TYPE_GROUP:
1046 return (NULL);
1047 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1048 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1049 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1050 case XML_SCHEMA_TYPE_IDC_KEY:
1051 case XML_SCHEMA_TYPE_IDC_KEYREF:
1052 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1053 default:
1054 return (NULL);
1055 }
1056}
1057#endif
1058
1059/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001060 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001061 * @attr: the attribute declaration/use
1062 *
1063 * Returns the name of the attribute; if the attribute
1064 * is a reference, the name of the referenced global type will be returned.
1065 */
1066static const xmlChar *
1067xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
1068{
1069 if (attr->ref != NULL)
1070 return(attr->ref);
1071 else
1072 return(attr->name);
1073}
1074
1075/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001076 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001077 * @type: the type (element or attribute)
1078 *
1079 * Returns the target namespace URI of the type; if the type is a reference,
1080 * the target namespace of the referenced type will be returned.
1081 */
1082static const xmlChar *
1083xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
1084{
1085 if (attr->ref != NULL)
1086 return (attr->refNs);
1087 else
1088 return(attr->targetNamespace);
1089}
1090
1091/**
1092 * xmlSchemaFormatNsUriLocal:
1093 * @buf: the string buffer
1094 * @uri: the namespace URI
1095 * @local: the local name
1096 *
1097 * Returns a representation of the given URI used
1098 * for error reports.
1099 *
1100 * Returns an empty string, if @ns is NULL, a formatted
1101 * string otherwise.
1102 */
1103static const xmlChar*
1104xmlSchemaFormatNsUriLocal(xmlChar **buf,
1105 const xmlChar *uri, const xmlChar *local)
1106{
1107 if (*buf != NULL)
1108 xmlFree(*buf);
1109 if (uri == NULL) {
1110 *buf = xmlStrdup(BAD_CAST "{'");
1111 *buf = xmlStrcat(*buf, local);
1112 } else {
1113 *buf = xmlStrdup(BAD_CAST "{'");
1114 *buf = xmlStrcat(*buf, uri);
1115 *buf = xmlStrcat(*buf, BAD_CAST "', '");
1116 *buf = xmlStrcat(*buf, local);
1117 }
1118 *buf = xmlStrcat(*buf, BAD_CAST "'}");
1119 return ((const xmlChar *) *buf);
1120}
1121
1122/**
1123 * xmlSchemaFormatNsPrefixLocal:
1124 * @buf: the string buffer
1125 * @ns: the namespace
1126 * @local: the local name
1127 *
1128 * Returns a representation of the given URI used
1129 * for error reports.
1130 *
1131 * Returns an empty string, if @ns is NULL, a formatted
1132 * string otherwise.
1133 */
1134static const xmlChar*
1135xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
1136 xmlNsPtr ns, const xmlChar *local)
1137{
1138 if (*buf != NULL) {
1139 xmlFree(*buf);
1140 *buf = NULL;
1141 }
1142 if ((ns == NULL) || (ns->prefix == NULL))
1143 return(local);
1144 else {
1145 *buf = xmlStrdup(ns->prefix);
1146 *buf = xmlStrcat(*buf, BAD_CAST ":");
1147 *buf = xmlStrcat(*buf, local);
1148 }
1149 return ((const xmlChar *) *buf);
1150}
1151
1152/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001153 * xmlSchemaFormatQName:
1154 * @buf: the string buffer
1155 * @namespaceName: the namespace name
1156 * @localName: the local name
1157 *
1158 * Returns the given QName in the format "{namespaceName}localName" or
1159 * just "localName" if @namespaceName is NULL.
1160 *
1161 * Returns the localName if @namespaceName is NULL, a formatted
1162 * string otherwise.
1163 */
1164static const xmlChar*
1165xmlSchemaFormatQName(xmlChar **buf,
1166 const xmlChar *namespaceName,
1167 const xmlChar *localName)
1168{
1169 FREE_AND_NULL(*buf)
1170 if (namespaceName == NULL)
1171 return(localName);
1172
1173 *buf = xmlStrdup(BAD_CAST "{");
1174 *buf = xmlStrcat(*buf, namespaceName);
1175 *buf = xmlStrcat(*buf, BAD_CAST "}");
1176 *buf = xmlStrcat(*buf, localName);
1177
1178 return ((const xmlChar *) *buf);
1179}
1180
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001181static const xmlChar *
1182xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1183{
1184 switch (item->type) {
1185 case XML_SCHEMA_TYPE_ELEMENT:
1186 return (((xmlSchemaElementPtr) item)->name);
1187 case XML_SCHEMA_TYPE_ATTRIBUTE:
1188 return (((xmlSchemaAttributePtr) item)->name);
1189 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1190 return (((xmlSchemaAttributeGroupPtr) item)->name);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +00001191 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001192 case XML_SCHEMA_TYPE_SIMPLE:
1193 case XML_SCHEMA_TYPE_COMPLEX:
1194 return (((xmlSchemaTypePtr) item)->name);
1195 case XML_SCHEMA_TYPE_GROUP:
1196 return (((xmlSchemaModelGroupDefPtr) item)->name);
1197 case XML_SCHEMA_TYPE_IDC_KEY:
1198 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1199 case XML_SCHEMA_TYPE_IDC_KEYREF:
1200 return (((xmlSchemaIDCPtr) item)->name);
1201 default:
1202 /*
1203 * Other components cannot have names.
1204 */
1205 break;
1206 }
1207 return (NULL);
1208}
1209
1210static const xmlChar *
1211xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1212{
1213 switch (item->type) {
1214 case XML_SCHEMA_TYPE_ELEMENT:
1215 return (((xmlSchemaElementPtr) item)->targetNamespace);
1216 case XML_SCHEMA_TYPE_ATTRIBUTE:
1217 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1218 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1219 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +00001220 case XML_SCHEMA_TYPE_BASIC:
1221 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001222 case XML_SCHEMA_TYPE_SIMPLE:
1223 case XML_SCHEMA_TYPE_COMPLEX:
1224 return (((xmlSchemaTypePtr) item)->targetNamespace);
1225 case XML_SCHEMA_TYPE_GROUP:
1226 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1227 case XML_SCHEMA_TYPE_IDC_KEY:
1228 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1229 case XML_SCHEMA_TYPE_IDC_KEYREF:
1230 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1231 default:
1232 /*
1233 * Other components cannot have names.
1234 */
1235 break;
1236 }
1237 return (NULL);
1238}
1239
1240static const xmlChar*
1241xmlSchemaGetComponentQName(xmlChar **buf,
1242 void *item)
1243{
1244 return (xmlSchemaFormatQName(buf,
1245 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1246 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1247}
1248
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001249/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001250 * xmlSchemaWildcardPCToString:
1251 * @pc: the type of processContents
1252 *
1253 * Returns a string representation of the type of
1254 * processContents.
1255 */
1256static const xmlChar *
1257xmlSchemaWildcardPCToString(int pc)
1258{
1259 switch (pc) {
1260 case XML_SCHEMAS_ANY_SKIP:
1261 return (BAD_CAST "skip");
1262 case XML_SCHEMAS_ANY_LAX:
1263 return (BAD_CAST "lax");
1264 case XML_SCHEMAS_ANY_STRICT:
1265 return (BAD_CAST "strict");
1266 default:
1267 return (BAD_CAST "invalid process contents");
1268 }
1269}
1270
1271/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001272 * xmlSchemaFormatItemForReport:
1273 * @buf: the string buffer
1274 * @itemDes: the designation of the item
1275 * @itemName: the name of the item
1276 * @item: the item as an object
1277 * @itemNode: the node of the item
1278 * @local: the local name
1279 * @parsing: if the function is used during the parse
1280 *
1281 * Returns a representation of the given item used
1282 * for error reports.
1283 *
1284 * The following order is used to build the resulting
1285 * designation if the arguments are not NULL:
1286 * 1a. If itemDes not NULL -> itemDes
1287 * 1b. If (itemDes not NULL) and (itemName not NULL)
1288 * -> itemDes + itemName
1289 * 2. If the preceding was NULL and (item not NULL) -> item
1290 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1291 *
1292 * If the itemNode is an attribute node, the name of the attribute
1293 * will be appended to the result.
1294 *
1295 * Returns the formatted string and sets @buf to the resulting value.
1296 */
1297static xmlChar*
1298xmlSchemaFormatItemForReport(xmlChar **buf,
1299 const xmlChar *itemDes,
1300 xmlSchemaTypePtr item,
1301 xmlNodePtr itemNode,
1302 int parsing)
1303{
1304 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001305 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001306
1307 if (*buf != NULL) {
1308 xmlFree(*buf);
1309 *buf = NULL;
1310 }
1311
William M. Brack2f2a6632004-08-20 23:09:47 +00001312 if (itemDes != NULL) {
1313 *buf = xmlStrdup(itemDes);
1314 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001315 switch (item->type) {
1316 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001317 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1318 *buf = xmlStrdup(BAD_CAST "'anyType'");
1319 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1320 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1321 else {
1322 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1323 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1324 *buf = xmlStrdup(BAD_CAST "'");
1325 *buf = xmlStrcat(*buf, item->name);
1326 *buf = xmlStrcat(*buf, BAD_CAST "'");
1327 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001328 break;
1329 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001330 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1331 *buf = xmlStrdup(xmlSchemaElemDesST);
1332 *buf = xmlStrcat(*buf, BAD_CAST " '");
1333 *buf = xmlStrcat(*buf, item->name);
1334 *buf = xmlStrcat(*buf, BAD_CAST "'");
1335 } else {
1336 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001338 break;
1339 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001340 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1341 *buf = xmlStrdup(xmlSchemaElemDesCT);
1342 *buf = xmlStrcat(*buf, BAD_CAST " '");
1343 *buf = xmlStrcat(*buf, item->name);
1344 *buf = xmlStrcat(*buf, BAD_CAST "'");
1345 } else {
1346 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001347 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001348 break;
1349 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1350 xmlSchemaAttributePtr attr;
1351
1352 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001353 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001354 (attr->ref == NULL)) {
1355 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1356 *buf = xmlStrcat(*buf, BAD_CAST " '");
1357 *buf = xmlStrcat(*buf, attr->name);
1358 *buf = xmlStrcat(*buf, BAD_CAST "'");
1359 } else {
1360 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1361 *buf = xmlStrcat(*buf, BAD_CAST " '");
1362 *buf = xmlStrcat(*buf, attr->refPrefix);
1363 *buf = xmlStrcat(*buf, BAD_CAST ":");
1364 *buf = xmlStrcat(*buf, attr->ref);
1365 *buf = xmlStrcat(*buf, BAD_CAST "'");
1366 }
1367 }
1368 break;
1369 case XML_SCHEMA_TYPE_ELEMENT: {
1370 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001371
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001372 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001373 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001374 (elem->ref == NULL)) {
1375 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1376 *buf = xmlStrcat(*buf, BAD_CAST " '");
1377 *buf = xmlStrcat(*buf, elem->name);
1378 *buf = xmlStrcat(*buf, BAD_CAST "'");
1379 } else {
1380 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1381 *buf = xmlStrcat(*buf, BAD_CAST " '");
1382 *buf = xmlStrcat(*buf, elem->refPrefix);
1383 *buf = xmlStrcat(*buf, BAD_CAST ":");
1384 *buf = xmlStrcat(*buf, elem->ref);
1385 *buf = xmlStrcat(*buf, BAD_CAST "'");
1386 }
1387 }
1388 break;
1389 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390 case XML_SCHEMA_TYPE_IDC_KEY:
1391 case XML_SCHEMA_TYPE_IDC_KEYREF:
1392 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1393 *buf = xmlStrdup(BAD_CAST "unique '");
1394 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1395 *buf = xmlStrdup(BAD_CAST "key '");
1396 else
1397 *buf = xmlStrdup(BAD_CAST "keyRef '");
1398 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1399 *buf = xmlStrcat(*buf, BAD_CAST "'");
1400 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001401 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001402 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001403 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1404 ((xmlSchemaWildcardPtr) item)->processContents));
1405 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1406 break;
1407 case XML_SCHEMA_FACET_MININCLUSIVE:
1408 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1409 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1410 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1411 case XML_SCHEMA_FACET_TOTALDIGITS:
1412 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1413 case XML_SCHEMA_FACET_PATTERN:
1414 case XML_SCHEMA_FACET_ENUMERATION:
1415 case XML_SCHEMA_FACET_WHITESPACE:
1416 case XML_SCHEMA_FACET_LENGTH:
1417 case XML_SCHEMA_FACET_MAXLENGTH:
1418 case XML_SCHEMA_FACET_MINLENGTH:
1419 *buf = xmlStrdup(BAD_CAST "facet '");
1420 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1421 *buf = xmlStrcat(*buf, BAD_CAST "'");
1422 break;
1423 case XML_SCHEMA_TYPE_NOTATION:
1424 *buf = xmlStrdup(BAD_CAST "notation");
1425 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001426 case XML_SCHEMA_TYPE_GROUP: {
1427 xmlChar *s = NULL;
1428
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001429 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1430 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001431 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&s,
1432 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1433 ((xmlSchemaModelGroupDefPtr) item)->name));
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001434 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001435 FREE_AND_NULL(s)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001436 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001437 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001438 case XML_SCHEMA_TYPE_SEQUENCE:
1439 case XML_SCHEMA_TYPE_CHOICE:
1440 case XML_SCHEMA_TYPE_ALL:
1441 case XML_SCHEMA_TYPE_PARTICLE:
1442 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1443 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001444 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001445 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001446 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001447 } else
1448 named = 0;
1449
1450 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001451 xmlNodePtr elem;
1452
1453 if (itemNode->type == XML_ATTRIBUTE_NODE)
1454 elem = itemNode->parent;
1455 else
1456 elem = itemNode;
1457 *buf = xmlStrdup(BAD_CAST "Element '");
1458 if (parsing)
1459 *buf = xmlStrcat(*buf, elem->name);
1460 else
1461 *buf = xmlStrcat(*buf,
1462 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1463 *buf = xmlStrcat(*buf, BAD_CAST "'");
1464 }
1465 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1466 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1467 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1468 itemNode->ns, itemNode->name));
1469 *buf = xmlStrcat(*buf, BAD_CAST "'");
1470 }
1471 FREE_AND_NULL(str);
1472
1473 return (*buf);
1474}
1475
1476/**
1477 * xmlSchemaPFormatItemDes:
1478 * @buf: the string buffer
1479 * @item: the item as a schema object
1480 * @itemNode: the item as a node
1481 *
1482 * If the pointer to @buf is not NULL and @but holds no value,
1483 * the value is set to a item designation using
1484 * xmlSchemaFormatItemForReport. This one avoids adding
1485 * an attribute designation postfix.
1486 *
1487 * Returns a string of all enumeration elements.
1488 */
1489static void
1490xmlSchemaPRequestItemDes(xmlChar **buf,
1491 xmlSchemaTypePtr item,
1492 xmlNodePtr itemNode)
1493{
1494 if ((buf == 0) || (*buf != NULL))
1495 return;
1496 if (itemNode->type == XML_ATTRIBUTE_NODE)
1497 itemNode = itemNode->parent;
1498 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1499}
1500
1501/**
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001502 * xmlSchemaGetCanonValueWhtspExt:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001503 * @val: the precomputed value
1504 * @retValue: the returned value
1505 * @ws: the whitespace type of the value
1506 *
1507 * Get a the cononical representation of the value.
1508 * The caller has to free the returned retValue.
1509 *
1510 * Returns 0 if the value could be built and -1 in case of
1511 * API errors or if the value type is not supported yet.
1512 */
1513static int
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001514xmlSchemaGetCanonValueWhtspExt(const xmlChar *value,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001515 xmlSchemaValPtr val,
1516 xmlSchemaWhitespaceValueType ws,
1517 const xmlChar **retValue)
1518{
1519 xmlSchemaValType valType;
1520
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001521 if ((retValue == NULL) || ((value == NULL) && (val == NULL)))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001522 return (-1);
1523 *retValue = NULL;
1524 valType = xmlSchemaGetValType(val);
1525 switch (valType) {
1526 case XML_SCHEMAS_STRING:
1527 if (value == NULL)
1528 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001529 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1530 *retValue = xmlSchemaCollapseString(value);
1531 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1532 *retValue = xmlSchemaWhiteSpaceReplace(value);
1533 if ((*retValue) == NULL)
1534 *retValue = BAD_CAST xmlStrdup(value);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001535 break;
1536 case XML_SCHEMAS_NORMSTRING:
1537 if (value == NULL)
1538 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1539 else {
1540 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1541 *retValue = xmlSchemaCollapseString(value);
1542 else
1543 *retValue = xmlSchemaWhiteSpaceReplace(value);
1544 if ((*retValue) == NULL)
1545 *retValue = BAD_CAST xmlStrdup(value);
1546 }
1547 break;
1548 default:
1549 return (xmlSchemaGetCanonValue(val, retValue));
1550 }
1551 return (0);
1552}
1553
1554/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001555 * xmlSchemaFormatFacetEnumSet:
1556 * @buf: the string buffer
1557 * @type: the type holding the enumeration facets
1558 *
1559 * Builds a string consisting of all enumeration elements.
1560 *
1561 * Returns a string of all enumeration elements.
1562 */
1563static const xmlChar *
1564xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1565{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001566 xmlSchemaFacetPtr facet;
1567 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001568 const xmlChar *value = NULL;
1569 int res, found = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001570
1571 if (*buf != NULL)
1572 xmlFree(*buf);
1573 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001574
1575 do {
1576 /*
1577 * Use the whitespace type of the base type.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001578 */
1579 ws = (xmlSchemaWhitespaceValueType)
1580 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001581 for (facet = type->facets; facet != NULL; facet = facet->next) {
1582 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1583 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001584 found = 1;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +00001585 res = xmlSchemaGetCanonValueWhtspExt(facet->value, facet->val,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001586 ws, &value);
1587 if (res == -1) {
1588 xmlSchemaVErr(NULL, NULL,
1589 XML_SCHEMAV_INTERNAL,
1590 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1591 "compute the canonical lexical representation.\n",
1592 NULL, NULL);
1593 if (*buf != NULL)
1594 xmlFree(*buf);
1595 *buf = NULL;
1596 return (NULL);
1597 }
1598 if (*buf == NULL) {
1599 *buf = xmlStrdup(BAD_CAST "'");
1600 *buf = xmlStrcat(*buf, value);
1601 *buf = xmlStrcat(*buf, BAD_CAST "'");
1602 } else {
1603 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1604 *buf = xmlStrcat(*buf, value);
1605 *buf = xmlStrcat(*buf, BAD_CAST "'");
1606 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001607 if (value != NULL) {
1608 xmlFree((xmlChar *)value);
1609 value = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001610 }
1611 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001612 type = type->baseType;
1613 } while ((! found) && (type != NULL) &&
1614 (type->type != XML_SCHEMA_TYPE_BASIC));
1615
Daniel Veillardc0826a72004-08-10 14:17:33 +00001616 return ((const xmlChar *) *buf);
1617}
1618
1619/**
1620 * xmlSchemaVFacetErr:
1621 * @ctxt: the schema validation context
1622 * @error: the error code
1623 * @node: the node to be validated
1624 * @value: the value of the node
1625 * @type: the type holding the facet
1626 * @facet: the facet
1627 * @message: the error message of NULL
1628 * @str1: extra data
1629 * @str2: extra data
1630 * @str3: extra data
1631 *
1632 * Reports a facet validation error.
1633 * TODO: Should this report the value of an element as well?
1634 */
1635static void
1636xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1637 xmlParserErrors error,
1638 xmlNodePtr node,
1639 const xmlChar *value,
1640 unsigned long length,
1641 xmlSchemaTypePtr type,
1642 xmlSchemaFacetPtr facet,
1643 const char *message,
1644 const xmlChar *str1,
1645 const xmlChar *str2,
1646 const xmlChar *str3)
1647{
1648 xmlChar *str = NULL, *msg = NULL;
1649 xmlSchemaTypeType facetType;
1650
1651 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1652 msg = xmlStrcat(msg, BAD_CAST " [");
1653 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1654 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1655 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1656 facetType = XML_SCHEMA_FACET_ENUMERATION;
1657 /*
1658 * If enumerations are validated, one must not expect the
1659 * facet to be given.
1660 */
1661 } else
1662 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001663 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001664 msg = xmlStrcat(msg, BAD_CAST "']: ");
1665 if (message == NULL) {
1666 /*
1667 * Use a default message.
1668 */
1669 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1670 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1671 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1672
1673 char len[25], actLen[25];
1674
1675 /* FIXME, TODO: What is the max expected string length of the
1676 * this value?
1677 */
1678 if (node->type == XML_ATTRIBUTE_NODE)
1679 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1680 else
1681 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1682
1683 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1684 snprintf(actLen, 24, "%lu", length);
1685
1686 if (facetType == XML_SCHEMA_FACET_LENGTH)
1687 msg = xmlStrcat(msg,
1688 BAD_CAST "this differs from the allowed length of '%s'.\n");
1689 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1690 msg = xmlStrcat(msg,
1691 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1692 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1693 msg = xmlStrcat(msg,
1694 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1695
1696 if (node->type == XML_ATTRIBUTE_NODE)
1697 xmlSchemaVErrExt(ctxt, node, error,
1698 (const char *) msg,
1699 value, (const xmlChar *) actLen, (const xmlChar *) len,
1700 NULL, NULL);
1701 else
1702 xmlSchemaVErr(ctxt, node, error,
1703 (const char *) msg,
1704 (const xmlChar *) actLen, (const xmlChar *) len);
1705
1706 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1707 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1708 "of the set {%s}.\n");
1709 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1710 xmlSchemaFormatFacetEnumSet(&str, type));
1711 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1712 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1713 "by the pattern '%s'.\n");
1714 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001715 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001716 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1717 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1718 "minimum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001719 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001720 facet->value);
1721 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1722 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1723 "maximum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001724 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001725 facet->value);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001726 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001727 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
1728 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001729 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1730 facet->value);
1731 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001732 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
1733 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001734 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1735 facet->value);
Daniel Veillardf3598452005-04-05 11:10:45 +00001736 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001737 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
Daniel Veillardf3598452005-04-05 11:10:45 +00001738 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001739 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001740 facet->value);
1741 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001742 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
Daniel Veillardf3598452005-04-05 11:10:45 +00001743 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001744 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001745 facet->value);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001746 } else if (node->type == XML_ATTRIBUTE_NODE) {
1747 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001748 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001749 } else {
1750 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1751 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1752 }
1753 } else {
1754 msg = xmlStrcat(msg, (const xmlChar *) message);
1755 msg = xmlStrcat(msg, BAD_CAST ".\n");
1756 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1757 }
1758 FREE_AND_NULL(str)
1759 xmlFree(msg);
1760}
1761
1762/**
1763 * xmlSchemaVSimpleTypeErr:
1764 * @ctxt: the schema validation context
1765 * @error: the error code
1766 * @type: the type used for validation
1767 * @node: the node containing the validated value
1768 * @value: the validated value
1769 *
1770 * Reports a simple type validation error.
1771 * TODO: Should this report the value of an element as well?
1772 */
1773static void
1774xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1775 xmlParserErrors error,
1776 xmlNodePtr node,
1777 const xmlChar *value,
1778 xmlSchemaTypePtr type)
1779{
1780 xmlChar *str = NULL, *msg = NULL;
1781
1782 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1783 msg = xmlStrcat(msg, BAD_CAST " [");
1784 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1785 if (node->type == XML_ATTRIBUTE_NODE) {
1786 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1787 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1788 } else {
1789 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1790 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1791 }
1792 FREE_AND_NULL(str)
1793 xmlFree(msg);
1794}
1795
1796/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001797 * xmlSchemaVComplexTypeErr:
1798 * @ctxt: the schema validation context
1799 * @error: the error code
1800 * @node: the node containing the validated value
1801 * @type: the complex type used for validation
1802 * @message: the error message
1803 *
1804 * Reports a complex type validation error.
1805 */
1806static void
1807xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1808 xmlParserErrors error,
1809 xmlNodePtr node,
1810 xmlSchemaTypePtr type,
1811 const char *message)
1812{
1813 xmlChar *str = NULL, *msg = NULL;
1814
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001815 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001816 /* Specify the complex type only if it is global. */
1817 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001818 msg = xmlStrcat(msg, BAD_CAST " [");
1819 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1820 msg = xmlStrcat(msg, BAD_CAST "]");
1821 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001822 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1823 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001824 (const xmlChar *) message, NULL);
1825 FREE_AND_NULL(str)
1826 xmlFree(msg);
1827}
1828
1829/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001830 * xmlSchemaVComplexTypeElemErr:
1831 * @ctxt: the schema validation context
1832 * @error: the error code
1833 * @node: the node containing the validated value
1834 * @type: the complex type used for validation
1835 * @message: the error message
1836 *
1837 * Reports a complex type validation error.
1838 */
1839static void
1840xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1841 xmlParserErrors error,
1842 xmlNodePtr node,
1843 xmlSchemaTypePtr type,
1844 const char *message,
1845 int nbval,
1846 int nbneg,
1847 xmlChar **values)
1848{
1849 xmlChar *str = NULL, *msg = NULL;
1850 xmlChar *localName, *nsName;
1851 const xmlChar *cur, *end;
1852 int i;
1853
1854 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1855 /* Specify the complex type only if it is global. */
1856 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1857 msg = xmlStrcat(msg, BAD_CAST " [");
1858 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1859 msg = xmlStrcat(msg, BAD_CAST "]");
1860 FREE_AND_NULL(str)
1861 }
1862 msg = xmlStrcat(msg, BAD_CAST ": ");
1863 msg = xmlStrcat(msg, (const xmlChar *) message);
1864 /*
1865 * Note that is does not make sense to report that we have a
1866 * wildcard here, since the wildcard might be unfolded into
1867 * multiple transitions.
1868 */
1869 if (nbval + nbneg > 0) {
1870 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001871 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001872 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001873 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 nsName = NULL;
1875
1876 for (i = 0; i < nbval + nbneg; i++) {
1877 cur = values[i];
1878 /*
1879 * Get the local name.
1880 */
1881 localName = NULL;
1882
1883 end = cur;
1884 if (*end == '*') {
1885 localName = xmlStrdup(BAD_CAST "*");
1886 *end++;
1887 } else {
1888 while ((*end != 0) && (*end != '|'))
1889 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001890 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001891 }
1892 if (*end != 0) {
1893 *end++;
1894 /*
1895 * Skip "*|*" if they come with negated expressions, since
1896 * they represent the same negated wildcard.
1897 */
1898 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1899 /*
1900 * Get the namespace name.
1901 */
1902 cur = end;
1903 if (*end == '*') {
1904 nsName = xmlStrdup(BAD_CAST "{*}");
1905 } else {
1906 while (*end != 0)
1907 end++;
1908
1909 if (i >= nbval)
1910 nsName = xmlStrdup(BAD_CAST "{##other:");
1911 else
1912 nsName = xmlStrdup(BAD_CAST "{");
1913
1914 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1915 nsName = xmlStrcat(nsName, BAD_CAST "}");
1916 }
1917 str = xmlStrcat(str, BAD_CAST nsName);
1918 FREE_AND_NULL(nsName)
1919 } else {
1920 FREE_AND_NULL(localName);
1921 continue;
1922 }
1923 }
1924 str = xmlStrcat(str, BAD_CAST localName);
1925 FREE_AND_NULL(localName);
1926
1927 if (i < nbval + nbneg -1)
1928 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001929 }
1930 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001931 msg = xmlStrcat(msg, BAD_CAST str);
1932 FREE_AND_NULL(str)
1933 }
1934 msg = xmlStrcat(msg, BAD_CAST ".\n");
1935 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1936 xmlFree(msg);
1937}
1938
1939/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001940 * xmlSchemaPMissingAttrErr:
1941 * @ctxt: the schema validation context
1942 * @ownerDes: the designation of the owner
1943 * @ownerName: the name of the owner
1944 * @ownerItem: the owner as a schema object
1945 * @ownerElem: the owner as an element node
1946 * @node: the parent element node of the missing attribute node
1947 * @type: the corresponding type of the attribute node
1948 *
1949 * Reports an illegal attribute.
1950 */
1951static void
1952xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1953 xmlParserErrors error,
1954 xmlChar **ownerDes,
1955 xmlSchemaTypePtr ownerItem,
1956 xmlNodePtr ownerElem,
1957 const char *name,
1958 const char *message)
1959{
1960 xmlChar *des = NULL;
1961
1962 if (ownerDes == NULL)
1963 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1964 else if (*ownerDes == NULL) {
1965 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1966 des = *ownerDes;
1967 } else
1968 des = *ownerDes;
1969 if (message != NULL)
1970 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1971 else
1972 xmlSchemaPErr(ctxt, ownerElem, error,
1973 "%s: The attribute '%s' is required but missing.\n",
1974 BAD_CAST des, BAD_CAST name);
1975 if (ownerDes == NULL)
1976 FREE_AND_NULL(des);
1977}
1978
William M. Brack2f2a6632004-08-20 23:09:47 +00001979/**
1980 * xmlSchemaCompTypeToString:
1981 * @type: the type of the schema item
1982 *
1983 * Returns the component name of a schema item.
1984 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001985static const xmlChar *
Daniel Veillardc0826a72004-08-10 14:17:33 +00001986xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1987{
1988 switch (type) {
1989 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001990 return(BAD_CAST "simple type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001991 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001992 return(BAD_CAST "complex type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001993 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001994 return(BAD_CAST "element declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001995 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001996 return(BAD_CAST "attribute declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001997 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001998 return(BAD_CAST "model group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001999 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002000 return(BAD_CAST "attribute group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002001 case XML_SCHEMA_TYPE_NOTATION:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002002 return(BAD_CAST "notation declaration");
2003 case XML_SCHEMA_TYPE_SEQUENCE:
2004 return(BAD_CAST "model group (sequence)");
2005 case XML_SCHEMA_TYPE_CHOICE:
2006 return(BAD_CAST "model group (choice)");
2007 case XML_SCHEMA_TYPE_ALL:
2008 return(BAD_CAST "model group (all)");
2009 case XML_SCHEMA_TYPE_PARTICLE:
2010 return(BAD_CAST "particle");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002011 default:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002012 return(BAD_CAST "Not a schema component");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002013 }
2014}
2015/**
2016 * xmlSchemaPResCompAttrErr:
2017 * @ctxt: the schema validation context
2018 * @error: the error code
2019 * @ownerDes: the designation of the owner
2020 * @ownerItem: the owner as a schema object
2021 * @ownerElem: the owner as an element node
2022 * @name: the name of the attribute holding the QName
2023 * @refName: the referenced local name
2024 * @refURI: the referenced namespace URI
2025 * @message: optional message
2026 *
2027 * Used to report QName attribute values that failed to resolve
2028 * to schema components.
2029 */
2030static void
2031xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2032 xmlParserErrors error,
2033 xmlChar **ownerDes,
2034 xmlSchemaTypePtr ownerItem,
2035 xmlNodePtr ownerElem,
2036 const char *name,
2037 const xmlChar *refName,
2038 const xmlChar *refURI,
2039 xmlSchemaTypeType refType,
2040 const char *refTypeStr)
2041{
2042 xmlChar *des = NULL, *strA = NULL;
2043
2044 if (ownerDes == NULL)
2045 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2046 else if (*ownerDes == NULL) {
2047 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2048 des = *ownerDes;
2049 } else
2050 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002051 if (refTypeStr == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002052 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002053 xmlSchemaPErrExt(ctxt, ownerElem, error,
2054 NULL, NULL, NULL,
2055 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
2056 "%s.\n", BAD_CAST des, BAD_CAST name,
2057 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
2058 BAD_CAST refTypeStr, NULL);
2059 if (ownerDes == NULL)
2060 FREE_AND_NULL(des)
2061 FREE_AND_NULL(strA)
2062}
2063
William M. Brack2f2a6632004-08-20 23:09:47 +00002064/**
2065 * xmlSchemaPCustomAttrErr:
2066 * @ctxt: the schema parser context
2067 * @error: the error code
2068 * @ownerDes: the designation of the owner
2069 * @ownerItem: the owner as a schema object
2070 * @attr: the illegal attribute node
2071 *
2072 * Reports an illegal attribute during the parse.
2073 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002074static void
2075xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002076 xmlParserErrors error,
2077 xmlChar **ownerDes,
2078 xmlSchemaTypePtr ownerItem,
2079 xmlAttrPtr attr,
2080 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002081{
2082 xmlChar *des = NULL;
2083
2084 if (ownerDes == NULL)
2085 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2086 else if (*ownerDes == NULL) {
2087 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2088 des = *ownerDes;
2089 } else
2090 des = *ownerDes;
2091 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2092 "%s, attribute '%s': %s.\n",
2093 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2094 if (ownerDes == NULL)
2095 FREE_AND_NULL(des);
2096}
2097
2098/**
2099 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002100 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002101 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002102 * @ownerDes: the designation of the attribute's owner
2103 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00002104 * @attr: the illegal attribute node
2105 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002106 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002107 */
2108static void
2109xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2110 xmlParserErrors error,
2111 xmlChar **ownerDes,
2112 xmlSchemaTypePtr ownerItem,
2113 xmlAttrPtr attr)
2114{
2115 xmlChar *des = NULL, *strA = NULL;
2116
2117 if (ownerDes == NULL)
2118 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2119 else if (*ownerDes == NULL) {
2120 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2121 des = *ownerDes;
2122 } else
2123 des = *ownerDes;
2124 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2125 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2126 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2127 if (ownerDes == NULL)
2128 FREE_AND_NULL(des);
2129 FREE_AND_NULL(strA);
2130}
2131
William M. Brack2f2a6632004-08-20 23:09:47 +00002132/**
2133 * xmlSchemaPAquireDes:
2134 * @des: the first designation
2135 * @itemDes: the second designation
2136 * @item: the schema item
2137 * @itemElem: the node of the schema item
2138 *
2139 * Creates a designation for an item.
2140 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002141static void
2142xmlSchemaPAquireDes(xmlChar **des,
2143 xmlChar **itemDes,
2144 xmlSchemaTypePtr item,
2145 xmlNodePtr itemElem)
2146{
2147 if (itemDes == NULL)
2148 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
2149 else if (*itemDes == NULL) {
2150 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
2151 *des = *itemDes;
2152 } else
2153 *des = *itemDes;
2154}
2155
William M. Brack2f2a6632004-08-20 23:09:47 +00002156/**
2157 * xmlSchemaPCustomErr:
2158 * @ctxt: the schema parser context
2159 * @error: the error code
2160 * @itemDes: the designation of the schema item
2161 * @item: the schema item
2162 * @itemElem: the node of the schema item
2163 * @message: the error message
2164 * @str1: an optional param for the error message
2165 * @str2: an optional param for the error message
2166 * @str3: an optional param for the error message
2167 *
2168 * Reports an error during parsing.
2169 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002170static void
2171xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2172 xmlParserErrors error,
2173 xmlChar **itemDes,
2174 xmlSchemaTypePtr item,
2175 xmlNodePtr itemElem,
2176 const char *message,
2177 const xmlChar *str1,
2178 const xmlChar *str2,
2179 const xmlChar *str3)
2180{
2181 xmlChar *des = NULL, *msg = NULL;
2182
2183 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2184 msg = xmlStrdup(BAD_CAST "%s: ");
2185 msg = xmlStrcat(msg, (const xmlChar *) message);
2186 msg = xmlStrcat(msg, BAD_CAST ".\n");
2187 if ((itemElem == NULL) && (item != NULL))
2188 itemElem = item->node;
2189 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2190 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2191 if (itemDes == NULL)
2192 FREE_AND_NULL(des);
2193 FREE_AND_NULL(msg);
2194}
2195
William M. Brack2f2a6632004-08-20 23:09:47 +00002196/**
2197 * xmlSchemaPCustomErr:
2198 * @ctxt: the schema parser context
2199 * @error: the error code
2200 * @itemDes: the designation of the schema item
2201 * @item: the schema item
2202 * @itemElem: the node of the schema item
2203 * @message: the error message
2204 * @str1: the optional param for the error message
2205 *
2206 * Reports an error during parsing.
2207 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002208static void
2209xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2210 xmlParserErrors error,
2211 xmlChar **itemDes,
2212 xmlSchemaTypePtr item,
2213 xmlNodePtr itemElem,
2214 const char *message,
2215 const xmlChar *str1)
2216{
2217 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2218 str1, NULL, NULL);
2219}
2220
William M. Brack2f2a6632004-08-20 23:09:47 +00002221/**
2222 * xmlSchemaPAttrUseErr:
2223 * @ctxt: the schema parser context
2224 * @error: the error code
2225 * @itemDes: the designation of the schema type
2226 * @item: the schema type
2227 * @itemElem: the node of the schema type
2228 * @attr: the invalid schema attribute
2229 * @message: the error message
2230 * @str1: the optional param for the error message
2231 *
2232 * Reports an attribute use error during parsing.
2233 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002234static void
2235xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
2236 xmlParserErrors error,
2237 xmlChar **itemDes,
2238 xmlSchemaTypePtr item,
2239 xmlNodePtr itemElem,
2240 const xmlSchemaAttributePtr attr,
2241 const char *message,
2242 const xmlChar *str1)
2243{
2244 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
2245
2246 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2247 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
2248 xmlSchemaGetAttrName(attr));
2249 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
2250 msg = xmlStrcat(msg, (const xmlChar *) message);
2251 msg = xmlStrcat(msg, BAD_CAST ".\n");
2252 if ((itemElem == NULL) && (item != NULL))
2253 itemElem = item->node;
2254 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2255 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
2256 if (itemDes == NULL)
2257 FREE_AND_NULL(des);
2258 FREE_AND_NULL(strA);
2259 xmlFree(msg);
2260}
2261
William M. Brack2f2a6632004-08-20 23:09:47 +00002262/**
2263 * xmlSchemaPIllegalFacetAtomicErr:
2264 * @ctxt: the schema parser context
2265 * @error: the error code
2266 * @itemDes: the designation of the type
2267 * @item: the schema type
2268 * @baseItem: the base type of type
2269 * @facet: the illegal facet
2270 *
2271 * Reports an illegal facet for atomic simple types.
2272 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002273static void
2274xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2275 xmlParserErrors error,
2276 xmlChar **itemDes,
2277 xmlSchemaTypePtr item,
2278 xmlSchemaTypePtr baseItem,
2279 xmlSchemaFacetPtr facet)
2280{
2281 xmlChar *des = NULL, *strT = NULL;
2282
2283 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2284 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2285 "%s: The facet '%s' is not allowed on types derived from the "
2286 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002287 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
2289 NULL, NULL);
2290 if (itemDes == NULL)
2291 FREE_AND_NULL(des);
2292 FREE_AND_NULL(strT);
2293}
2294
William M. Brack2f2a6632004-08-20 23:09:47 +00002295/**
2296 * xmlSchemaPIllegalFacetListUnionErr:
2297 * @ctxt: the schema parser context
2298 * @error: the error code
2299 * @itemDes: the designation of the schema item involved
2300 * @item: the schema item involved
2301 * @facet: the illegal facet
2302 *
2303 * Reports an illegal facet for <list> and <union>.
2304 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002305static void
2306xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
2307 xmlParserErrors error,
2308 xmlChar **itemDes,
2309 xmlSchemaTypePtr item,
2310 xmlSchemaFacetPtr facet)
2311{
2312 xmlChar *des = NULL, *strT = NULL;
2313
2314 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2315 xmlSchemaPErr(ctxt, item->node, error,
2316 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002317 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002318 if (itemDes == NULL)
2319 FREE_AND_NULL(des);
2320 FREE_AND_NULL(strT);
2321}
2322
2323/**
2324 * xmlSchemaPMutualExclAttrErr:
2325 * @ctxt: the schema validation context
2326 * @error: the error code
2327 * @elemDes: the designation of the parent element node
2328 * @attr: the bad attribute node
2329 * @type: the corresponding type of the attribute node
2330 *
2331 * Reports an illegal attribute.
2332 */
2333static void
2334xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2335 xmlParserErrors error,
2336 xmlChar **ownerDes,
2337 xmlSchemaTypePtr ownerItem,
2338 xmlAttrPtr attr,
2339 const char *name1,
2340 const char *name2)
2341{
2342 xmlChar *des = NULL;
2343
2344 if (ownerDes == NULL)
2345 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2346 else if (*ownerDes == NULL) {
2347 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2348 des = *ownerDes;
2349 } else
2350 des = *ownerDes;
2351 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2352 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2353 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2354 if (ownerDes == NULL)
2355 FREE_AND_NULL(des)
2356}
2357
2358/**
2359 * xmlSchemaPSimpleTypeErr:
2360 * @ctxt: the schema validation context
2361 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002362 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002363 * @ownerDes: the designation of the owner
2364 * @ownerItem: the schema object if existent
2365 * @node: the validated node
2366 * @value: the validated value
2367 *
2368 * Reports a simple type validation error.
2369 * TODO: Should this report the value of an element as well?
2370 */
2371static void
2372xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2373 xmlParserErrors error,
2374 xmlChar **ownerDes,
2375 xmlSchemaTypePtr ownerItem,
2376 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002377 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002378 const char *typeDes,
2379 const xmlChar *value,
2380 const char *message,
2381 const xmlChar *str1,
2382 const xmlChar *str2)
2383{
William M. Brack2f2a6632004-08-20 23:09:47 +00002384 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002385
2386 if (ownerDes == NULL)
2387 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2388 else if (*ownerDes == NULL) {
2389 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2390 des = *ownerDes;
2391 } else
2392 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002393 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002394 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002395 if (message == NULL) {
2396 /*
2397 * Use default messages.
2398 */
2399 if (node->type == XML_ATTRIBUTE_NODE) {
2400 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2401 "%s, attribute '%s' [%s]: The value '%s' is not "
2402 "valid.\n",
2403 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2404 node->name), BAD_CAST typeDes, value, NULL);
2405 } else {
2406 xmlSchemaPErr(ctxt, node, error,
2407 "%s [%s]: The character content is not valid.\n",
2408 BAD_CAST des, BAD_CAST typeDes);
2409 }
2410 } else {
2411 xmlChar *msg;
2412
2413 msg = xmlStrdup(BAD_CAST "%s");
2414 if (node->type == XML_ATTRIBUTE_NODE)
2415 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2416 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2417 msg = xmlStrcat(msg, (const xmlChar *) message);
2418 msg = xmlStrcat(msg, BAD_CAST ".\n");
2419 if (node->type == XML_ATTRIBUTE_NODE) {
2420 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2421 (const char *) msg,
2422 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2423 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2424 } else {
2425 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2426 (const char *) msg,
2427 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2428 }
2429 xmlFree(msg);
2430 }
2431 /* Cleanup. */
2432 FREE_AND_NULL(strA)
2433 FREE_AND_NULL(strT)
2434 if (ownerDes == NULL)
2435 FREE_AND_NULL(des)
2436}
2437
William M. Brack2f2a6632004-08-20 23:09:47 +00002438/**
2439 * xmlSchemaPContentErr:
2440 * @ctxt: the schema parser context
2441 * @error: the error code
2442 * @onwerDes: the designation of the holder of the content
2443 * @ownerItem: the owner item of the holder of the content
2444 * @ownerElem: the node of the holder of the content
2445 * @child: the invalid child node
2446 * @message: the optional error message
2447 * @content: the optional string describing the correct content
2448 *
2449 * Reports an error concerning the content of a schema element.
2450 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002451static void
2452xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2453 xmlParserErrors error,
2454 xmlChar **ownerDes,
2455 xmlSchemaTypePtr ownerItem,
2456 xmlNodePtr ownerElem,
2457 xmlNodePtr child,
2458 const char *message,
2459 const char *content)
2460{
2461 xmlChar *des = NULL;
2462
2463 if (ownerDes == NULL)
2464 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2465 else if (*ownerDes == NULL) {
2466 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2467 des = *ownerDes;
2468 } else
2469 des = *ownerDes;
2470 if (message != NULL)
2471 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2472 "%s: %s.\n",
2473 BAD_CAST des, BAD_CAST message);
2474 else {
2475 if (content != NULL) {
2476 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2477 "%s: The content is not valid. Expected is %s.\n",
2478 BAD_CAST des, BAD_CAST content);
2479 } else {
2480 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2481 "%s: The content is not valid.\n",
2482 BAD_CAST des, NULL);
2483 }
2484 }
2485 if (ownerDes == NULL)
2486 FREE_AND_NULL(des)
2487}
2488
2489/**
2490 * xmlSchemaVIllegalAttrErr:
2491 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002492 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002493 * @attr: the illegal attribute node
2494 *
2495 * Reports an illegal attribute.
2496 */
2497static void
2498xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002499 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002500 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002501{
2502 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002503
2504 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2505 error,
2506 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002507 "%s: The attribute '%s' is not allowed.\n",
2508 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2509 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2510 FREE_AND_NULL(strE)
2511 FREE_AND_NULL(strA)
2512}
2513
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002514
2515static int
2516xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2517{
2518 switch (item->type) {
2519 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002520 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002521 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2522 return(1);
2523 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002524 case XML_SCHEMA_TYPE_GROUP:
2525 return (1);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002526 case XML_SCHEMA_TYPE_ELEMENT:
2527 if ( ((xmlSchemaElementPtr) item)->flags &
2528 XML_SCHEMAS_ELEM_GLOBAL)
2529 return(1);
2530 break;
2531 case XML_SCHEMA_TYPE_ATTRIBUTE:
2532 if ( ((xmlSchemaAttributePtr) item)->flags &
2533 XML_SCHEMAS_ATTR_GLOBAL)
2534 return(1);
2535 break;
2536 /* Note that attribute groups are always global. */
2537 default:
2538 return(1);
2539 }
2540 return (0);
2541}
2542
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002543
2544static void
2545xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2546 xmlParserErrors error,
2547 xmlSchemaNodeInfoPtr nodeInfo,
2548 xmlSchemaTypePtr type,
2549 const char *message,
2550 const xmlChar *str1,
2551 const xmlChar *str2)
2552{
2553 xmlChar *msg = NULL, *str = NULL;
2554
2555 msg = xmlStrdup(BAD_CAST "Element '");
2556
2557 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2558 xmlSchemaNodeInfoPtr elemInfo;
2559 /*
2560 * The node info is an attribute info.
2561 */
2562 elemInfo = vctxt->elemInfos[vctxt->depth];
2563 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2564 elemInfo->namespaceName, elemInfo->localName));
2565 msg = xmlStrcat(msg, BAD_CAST "', ");
2566 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2567 }
2568 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2569 nodeInfo->namespaceName, nodeInfo->localName));
2570 msg = xmlStrcat(msg, BAD_CAST "'");
2571
2572 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2573 msg = xmlStrcat(msg, BAD_CAST " [");
2574 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2575 NULL, type, NULL, 0));
2576 msg = xmlStrcat(msg, BAD_CAST "]");
2577 }
2578 msg = xmlStrcat(msg, BAD_CAST ": ");
2579
2580 msg = xmlStrcat(msg, (const xmlChar *) message);
2581 msg = xmlStrcat(msg, BAD_CAST ".\n");
2582 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2583 str1, str2);
2584 FREE_AND_NULL(msg)
2585 FREE_AND_NULL(str)
2586}
2587
William M. Brack2f2a6632004-08-20 23:09:47 +00002588/**
2589 * xmlSchemaVCustomErr:
2590 * @ctxt: the schema validation context
2591 * @error: the error code
2592 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002593 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002594 * @message: the error message
2595 * @str1: the optional param for the message
2596 *
2597 * Reports a validation error.
2598 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002599static void
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002600xmlSchemaVCustomErrExt(xmlSchemaValidCtxtPtr ctxt,
2601 xmlParserErrors error,
2602 xmlNodePtr node,
2603 xmlSchemaTypePtr type,
2604 const char *message,
2605 const xmlChar *str1,
2606 const xmlChar *str2,
2607 const xmlChar *str3)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002608{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002609 xmlChar *msg = NULL, *str = NULL;
2610
2611 if (node == NULL) {
2612 xmlSchemaVErr(ctxt, NULL,
2613 XML_SCHEMAV_INTERNAL,
2614 "Internal error: xmlSchemaVCustomErr, no node "
2615 "given.\n", NULL, NULL);
2616 return;
2617 }
2618 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2619 if (node->type != XML_DOCUMENT_NODE) {
2620 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002621 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002622 msg = xmlStrcat(msg, BAD_CAST " [");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002623 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL,
2624 type, NULL, 0));
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002625 msg = xmlStrcat(msg, BAD_CAST "]");
2626 }
2627 msg = xmlStrcat(msg, BAD_CAST ": ");
2628 } else
2629 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002630 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002631 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002632 xmlSchemaVErrExt(ctxt, node, error, (const char *) msg, str1, str2,
2633 str3, NULL, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002634 FREE_AND_NULL(msg)
2635 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002636}
2637
William M. Brack2f2a6632004-08-20 23:09:47 +00002638/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002639 * xmlSchemaVCustomErr:
2640 * @ctxt: the schema validation context
2641 * @error: the error code
2642 * @node: the validated node
2643 * @type: the schema type of the validated node
2644 * @message: the error message
2645 * @str1: the optional param for the message
2646 *
2647 * Reports a validation error.
2648 */
2649static void
2650xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2651 xmlParserErrors error,
2652 xmlNodePtr node,
2653 xmlSchemaTypePtr type,
2654 const char *message,
2655 const xmlChar *str1)
2656{
2657 xmlSchemaVCustomErrExt(ctxt, error, node, type, message, str1, NULL, NULL);
2658}
2659
2660/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002661 * xmlSchemaVWildcardErr:
2662 * @ctxt: the schema validation context
2663 * @error: the error code
2664 * @node: the validated node
2665 * @wild: the wildcard used
2666 * @message: the error message
2667 *
2668 * Reports an validation-by-wildcard error.
2669 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002670static void
2671xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2672 xmlParserErrors error,
2673 xmlNodePtr node,
2674 xmlSchemaWildcardPtr wild,
2675 const char *message)
2676{
2677 xmlChar *des = NULL, *msg = NULL;
2678
2679 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002680 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002681 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002682 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002683 msg = xmlStrcat(msg, (const xmlChar *) message);
2684 msg = xmlStrcat(msg, BAD_CAST ".\n");
2685 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2686 FREE_AND_NULL(des);
2687 FREE_AND_NULL(msg);
2688}
2689
2690/**
2691 * xmlSchemaVMissingAttrErr:
2692 * @ctxt: the schema validation context
2693 * @node: the parent element node of the missing attribute node
2694 * @type: the corresponding type of the attribute node
2695 *
2696 * Reports an illegal attribute.
2697 */
2698static void
2699xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2700 xmlNodePtr elem,
2701 xmlSchemaAttributePtr type)
2702{
2703 const xmlChar *name, *uri;
2704 xmlChar *strE = NULL, *strA = NULL;
2705
2706 if (type->ref != NULL) {
2707 name = type->ref;
2708 uri = type->refNs;
2709 } else {
2710 name = type->name;
2711 uri = type->targetNamespace;
2712 }
2713 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002714 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2715 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002716 "%s: The attribute %s is required but missing.\n",
2717 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2718 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2719 FREE_AND_NULL(strE)
2720 FREE_AND_NULL(strA)
2721}
2722
Daniel Veillard4255d502002-04-16 15:50:10 +00002723/************************************************************************
2724 * *
2725 * Allocation functions *
2726 * *
2727 ************************************************************************/
2728
2729/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002730 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002731 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 *
2733 * Allocate a new Schema structure.
2734 *
2735 * Returns the newly allocated structure or NULL in case or error
2736 */
2737static xmlSchemaPtr
2738xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2739{
2740 xmlSchemaPtr ret;
2741
2742 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2743 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002744 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002745 return (NULL);
2746 }
2747 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002748 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002749 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002750
2751 return (ret);
2752}
2753
2754/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002755 * xmlSchemaNewSchema:
2756 * @ctxt: a schema validation context
2757 *
2758 * Allocate a new Schema structure.
2759 *
2760 * Returns the newly allocated structure or NULL in case or error
2761 */
2762static xmlSchemaAssemblePtr
2763xmlSchemaNewAssemble(void)
2764{
2765 xmlSchemaAssemblePtr ret;
2766
2767 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2768 if (ret == NULL) {
2769 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2770 return (NULL);
2771 }
2772 memset(ret, 0, sizeof(xmlSchemaAssemble));
2773 ret->items = NULL;
2774 return (ret);
2775}
2776
2777/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002778 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002779 *
2780 * Allocate a new Facet structure.
2781 *
2782 * Returns the newly allocated structure or NULL in case or error
2783 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002784xmlSchemaFacetPtr
2785xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002786{
2787 xmlSchemaFacetPtr ret;
2788
2789 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2790 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002791 return (NULL);
2792 }
2793 memset(ret, 0, sizeof(xmlSchemaFacet));
2794
2795 return (ret);
2796}
2797
2798/**
2799 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002800 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002801 * @node: a node
2802 *
2803 * Allocate a new annotation structure.
2804 *
2805 * Returns the newly allocated structure or NULL in case or error
2806 */
2807static xmlSchemaAnnotPtr
2808xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2809{
2810 xmlSchemaAnnotPtr ret;
2811
2812 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2813 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002814 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002815 return (NULL);
2816 }
2817 memset(ret, 0, sizeof(xmlSchemaAnnot));
2818 ret->content = node;
2819 return (ret);
2820}
2821
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002822static xmlSchemaItemListPtr
2823xmlSchemaNewItemList(void)
2824{
2825 xmlSchemaItemListPtr ret;
2826
2827 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2828 if (ret == NULL) {
2829 xmlSchemaPErrMemory(NULL,
2830 "allocating an item list structure", NULL);
2831 return (NULL);
2832 }
2833 memset(ret, 0, sizeof(xmlSchemaItemList));
2834 return (ret);
2835}
2836
2837/**
2838 * xmlSchemaAddElementSubstitutionMember:
2839 * @pctxt: a schema parser context
2840 * @head: the head of the substitution group
2841 * @member: the new member of the substitution group
2842 *
2843 * Allocate a new annotation structure.
2844 *
2845 * Returns the newly allocated structure or NULL in case or error
2846 */
2847static int
2848xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2849 xmlSchemaElementPtr head,
2850 xmlSchemaElementPtr member)
2851{
2852 xmlSchemaSubstGroupPtr substGroup;
2853
2854 if (pctxt == NULL)
2855 return (-1);
2856
2857 if (pctxt->substGroups == NULL) {
2858 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2859 if (pctxt->substGroups == NULL)
2860 return (-1);
2861 }
2862 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2863 head->targetNamespace);
2864 if (substGroup == NULL) {
2865 int res;
2866
2867 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2868 if (substGroup == NULL) {
2869 xmlSchemaPErrMemory(NULL,
2870 "xmlSchemaAddElementSubstitution, allocating a substitution "
2871 "group container",
2872 NULL);
2873 return (-1);
2874 }
2875 substGroup->members = xmlSchemaNewItemList();
2876 if (substGroup->members == NULL) {
2877 xmlFree(substGroup);
2878 return (-1);
2879 }
2880 substGroup->head = head;
2881
2882 res = xmlHashAddEntry2(pctxt->substGroups,
2883 head->name, head->targetNamespace, substGroup);
2884 if (res != 0) {
2885 xmlFree(substGroup->members);
2886 xmlFree(substGroup);
2887 xmlSchemaPErr(pctxt, member->node,
2888 XML_SCHEMAP_INTERNAL,
2889 "Internal error: xmlSchemaAddElementSubstitution, "
2890 "failed to add a new substitution group container for "
2891 "'%s'.\n", head->name, NULL);
2892 return (-1);
2893 }
2894 }
2895 if (substGroup->members->items == NULL) {
2896 substGroup->members->items = (void **) xmlMalloc(
2897 5 * sizeof(xmlSchemaElementPtr));
2898 if (substGroup->members->items == NULL) {
2899 xmlSchemaPErrMemory(NULL,
2900 "allocating list of substitution group members", NULL);
2901 return (-1);
2902 }
2903 substGroup->members->sizeItems = 5;
2904 } else if (substGroup->members->sizeItems <=
2905 substGroup->members->nbItems) {
2906 substGroup->members->sizeItems *= 2;
2907 substGroup->members->items = (void **) xmlRealloc(
2908 substGroup->members->items,
2909 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2910 if (substGroup->members->items == NULL) {
2911 xmlSchemaPErrMemory(NULL,
2912 "re-allocating list of substitution group members", NULL);
2913 substGroup->members->sizeItems = 0;
2914 return (-1);
2915 }
2916 }
2917 ((xmlSchemaElementPtr *) substGroup->members->items)
2918 [substGroup->members->nbItems++] = (void *) member;
2919 return (0);
2920}
2921
2922/**
2923 * xmlSchemaGetElementSubstitutionGroup:
2924 * @pctxt: a schema parser context
2925 * @head: the head of the substitution group
2926 * @member: the new member of the substitution group
2927 *
2928 * Allocate a new annotation structure.
2929 *
2930 * Returns the newly allocated structure or NULL in case or error
2931 */
2932static xmlSchemaSubstGroupPtr
2933xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2934 xmlSchemaElementPtr head)
2935{
2936 if (pctxt == NULL)
2937 return (NULL);
2938
2939 if (pctxt->substGroups == NULL)
2940 return (NULL);
2941
2942 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2943 head->name, head->targetNamespace));
2944}
2945
2946/**
2947 * xmlSchemaFreeItemList:
2948 * @annot: a schema type structure
2949 *
2950 * Deallocate a annotation structure
2951 */
2952static void
2953xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2954{
2955 if (list == NULL)
2956 return;
2957 if (list->items != NULL)
2958 xmlFree(list->items);
2959 xmlFree(list);
2960}
2961
Daniel Veillard4255d502002-04-16 15:50:10 +00002962/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002963 * xmlSchemaFreeAnnot:
2964 * @annot: a schema type structure
2965 *
2966 * Deallocate a annotation structure
2967 */
2968static void
2969xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2970{
2971 if (annot == NULL)
2972 return;
2973 xmlFree(annot);
2974}
2975
2976/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002977 * xmlSchemaFreeImport:
2978 * @import: a schema import structure
2979 *
2980 * Deallocate an import structure
2981 */
2982static void
2983xmlSchemaFreeImport(xmlSchemaImportPtr import)
2984{
2985 if (import == NULL)
2986 return;
2987
2988 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002989 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002990 xmlFree(import);
2991}
2992
2993/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002994 * xmlSchemaFreeInclude:
2995 * @include: a schema include structure
2996 *
2997 * Deallocate an include structure
2998 */
2999static void
3000xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
3001{
3002 if (include == NULL)
3003 return;
3004
3005 xmlFreeDoc(include->doc);
3006 xmlFree(include);
3007}
3008
3009/**
3010 * xmlSchemaFreeIncludeList:
3011 * @includes: a schema include list
3012 *
3013 * Deallocate an include structure
3014 */
3015static void
3016xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
3017{
3018 xmlSchemaIncludePtr next;
3019
3020 while (includes != NULL) {
3021 next = includes->next;
3022 xmlSchemaFreeInclude(includes);
3023 includes = next;
3024 }
3025}
3026
3027/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003028 * xmlSchemaFreeNotation:
3029 * @schema: a schema notation structure
3030 *
3031 * Deallocate a Schema Notation structure.
3032 */
3033static void
3034xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3035{
3036 if (nota == NULL)
3037 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003038 xmlFree(nota);
3039}
3040
3041/**
3042 * xmlSchemaFreeAttribute:
3043 * @schema: a schema attribute structure
3044 *
3045 * Deallocate a Schema Attribute structure.
3046 */
3047static void
3048xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3049{
3050 if (attr == NULL)
3051 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003052 if (attr->annot != NULL)
3053 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003054 if (attr->defVal != NULL)
3055 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003056 xmlFree(attr);
3057}
3058
3059/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003060 * xmlSchemaFreeWildcardNsSet:
3061 * set: a schema wildcard namespace
3062 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003063 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003064 */
3065static void
3066xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3067{
3068 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003069
Daniel Veillard3646d642004-06-02 19:19:14 +00003070 while (set != NULL) {
3071 next = set->next;
3072 xmlFree(set);
3073 set = next;
3074 }
3075}
3076
3077/**
3078 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003079 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003080 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003081 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003082 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003083void
Daniel Veillard3646d642004-06-02 19:19:14 +00003084xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3085{
3086 if (wildcard == NULL)
3087 return;
3088 if (wildcard->annot != NULL)
3089 xmlSchemaFreeAnnot(wildcard->annot);
3090 if (wildcard->nsSet != NULL)
3091 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3092 if (wildcard->negNsSet != NULL)
3093 xmlFree(wildcard->negNsSet);
3094 xmlFree(wildcard);
3095}
3096
3097/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003098 * xmlSchemaFreeAttributeGroup:
3099 * @schema: a schema attribute group structure
3100 *
3101 * Deallocate a Schema Attribute Group structure.
3102 */
3103static void
3104xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3105{
3106 if (attr == NULL)
3107 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003108 if (attr->annot != NULL)
3109 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003110 xmlFree(attr);
3111}
3112
3113/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003114 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003115 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003116 *
3117 * Deallocate a list of schema attribute uses.
3118 */
3119static void
3120xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3121{
3122 xmlSchemaAttributeLinkPtr next;
3123
3124 while (attrUse != NULL) {
3125 next = attrUse->next;
3126 xmlFree(attrUse);
3127 attrUse = next;
3128 }
3129}
3130
3131/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003132 * xmlSchemaFreeQNameRef:
3133 * @item: a QName reference structure
3134 *
3135 * Deallocatea a QName reference structure.
3136 */
3137static void
3138xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3139{
3140 xmlFree(item);
3141}
3142
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003143/**
3144 * xmlSchemaFreeQNameRef:
3145 * @item: a QName reference structure
3146 *
3147 * Deallocatea a QName reference structure.
3148 */
3149static void
3150xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3151{
3152 if (item == NULL)
3153 return;
3154 if (item->members != NULL)
3155 xmlSchemaFreeItemList(item->members);
3156 xmlFree(item);
3157}
3158
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003159static int
3160xmlSchemaAddVolatile(xmlSchemaPtr schema,
3161 xmlSchemaBasicItemPtr item)
3162{
3163 xmlSchemaItemListPtr list;
3164
3165 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003166 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003167 if (schema->volatiles == NULL) {
3168 xmlSchemaPErrMemory(NULL,
3169 "allocating list of volatiles", NULL);
3170 return (-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003171 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003172 }
3173 list = (xmlSchemaItemListPtr) schema->volatiles;
3174 if (list->items == NULL) {
3175 list->items = (void **) xmlMalloc(
3176 20 * sizeof(xmlSchemaBasicItemPtr));
3177 if (list->items == NULL) {
3178 xmlSchemaPErrMemory(NULL,
3179 "allocating new volatile item buffer", NULL);
3180 return (-1);
3181 }
3182 list->sizeItems = 20;
3183 } else if (list->sizeItems <= list->nbItems) {
3184 list->sizeItems *= 2;
3185 list->items = (void **) xmlRealloc(list->items,
3186 list->sizeItems * sizeof(xmlSchemaTypePtr));
3187 if (list->items == NULL) {
3188 xmlSchemaPErrMemory(NULL,
3189 "growing volatile item buffer", NULL);
3190 list->sizeItems = 0;
3191 return (-1);
3192 }
3193 }
3194 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3195 return (0);
3196}
3197
3198/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003199 * xmlSchemaFreeTypeLinkList:
3200 * @alink: a type link
3201 *
3202 * Deallocate a list of types.
3203 */
3204static void
3205xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3206{
3207 xmlSchemaTypeLinkPtr next;
3208
3209 while (link != NULL) {
3210 next = link->next;
3211 xmlFree(link);
3212 link = next;
3213 }
3214}
3215
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003216static void
3217xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3218{
3219 xmlSchemaIDCStateObjPtr next;
3220 while (sto != NULL) {
3221 next = sto->next;
3222 if (sto->history != NULL)
3223 xmlFree(sto->history);
3224 if (sto->xpathCtxt != NULL)
3225 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3226 xmlFree(sto);
3227 sto = next;
3228 }
3229}
3230
3231/**
3232 * xmlSchemaFreeIDC:
3233 * @idc: a identity-constraint definition
3234 *
3235 * Deallocates an identity-constraint definition.
3236 */
3237static void
3238xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3239{
3240 xmlSchemaIDCSelectPtr cur, prev;
3241
3242 if (idcDef == NULL)
3243 return;
3244 if (idcDef->annot != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003245 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003246 /* Selector */
3247 if (idcDef->selector != NULL) {
3248 if (idcDef->selector->xpathComp != NULL)
3249 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3250 xmlFree(idcDef->selector);
3251 }
3252 /* Fields */
3253 if (idcDef->fields != NULL) {
3254 cur = idcDef->fields;
3255 do {
3256 prev = cur;
3257 cur = cur->next;
3258 if (prev->xpathComp != NULL)
3259 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3260 xmlFree(prev);
3261 } while (cur != NULL);
3262 }
3263 xmlFree(idcDef);
3264}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003265
Daniel Veillard01fa6152004-06-29 17:04:39 +00003266/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003267 * xmlSchemaFreeElement:
3268 * @schema: a schema element structure
3269 *
3270 * Deallocate a Schema Element structure.
3271 */
3272static void
3273xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3274{
3275 if (elem == NULL)
3276 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003277 if (elem->annot != NULL)
3278 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003279 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003280 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003281 if (elem->defVal != NULL)
3282 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003283 xmlFree(elem);
3284}
3285
3286/**
3287 * xmlSchemaFreeFacet:
3288 * @facet: a schema facet structure
3289 *
3290 * Deallocate a Schema Facet structure.
3291 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003292void
Daniel Veillard4255d502002-04-16 15:50:10 +00003293xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3294{
3295 if (facet == NULL)
3296 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003297 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003298 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003299 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003300 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003301 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003302 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003303 xmlFree(facet);
3304}
3305
3306/**
3307 * xmlSchemaFreeType:
3308 * @type: a schema type structure
3309 *
3310 * Deallocate a Schema Type structure.
3311 */
3312void
3313xmlSchemaFreeType(xmlSchemaTypePtr type)
3314{
3315 if (type == NULL)
3316 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003317 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003318 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003319 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003320 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003321
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003322 facet = type->facets;
3323 while (facet != NULL) {
3324 next = facet->next;
3325 xmlSchemaFreeFacet(facet);
3326 facet = next;
3327 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003328 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003329 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3330 if (type->attributeUses != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003331 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003332 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003333 if (type->memberTypes != NULL)
3334 xmlSchemaFreeTypeLinkList(type->memberTypes);
3335 if (type->facetSet != NULL) {
3336 xmlSchemaFacetLinkPtr next, link;
3337
3338 link = type->facetSet;
3339 do {
3340 next = link->next;
3341 xmlFree(link);
3342 link = next;
3343 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003344 }
3345 if (type->contModel != NULL)
3346 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003347 xmlFree(type);
3348}
3349
3350/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003351 * xmlSchemaFreeModelGroupDef:
3352 * @item: a schema model group definition
3353 *
3354 * Deallocates a schema model group definition.
3355 */
3356static void
3357xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3358{
3359 if (item->annot != NULL)
3360 xmlSchemaFreeAnnot(item->annot);
3361 xmlFree(item);
3362}
3363
3364/**
3365 * xmlSchemaFreeModelGroup:
3366 * @item: a schema model group
3367 *
3368 * Deallocates a schema model group structure.
3369 */
3370static void
3371xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3372{
3373 if (item->annot != NULL)
3374 xmlSchemaFreeAnnot(item->annot);
3375 xmlFree(item);
3376}
3377
3378/**
3379 * xmlSchemaFreeParticle:
3380 * @type: a schema type structure
3381 *
3382 * Deallocate a Schema Type structure.
3383 */
3384static void
3385xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3386{
3387 if (item->annot != NULL)
3388 xmlSchemaFreeAnnot(item->annot);
3389 xmlFree(item);
3390}
3391
3392/**
3393 * xmlSchemaFreeMiscComponents:
3394 * @item: a schema component
3395 *
3396 * Deallocates misc. schema component structures.
3397 */
3398static void
3399xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3400{
3401 if (item == NULL)
3402 return;
3403 switch (item->type) {
3404 case XML_SCHEMA_TYPE_PARTICLE:
3405 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3406 return;
3407 case XML_SCHEMA_TYPE_SEQUENCE:
3408 case XML_SCHEMA_TYPE_CHOICE:
3409 case XML_SCHEMA_TYPE_ALL:
3410 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3411 return;
3412 case XML_SCHEMA_TYPE_ANY:
3413 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3414 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3415 break;
3416 default:
3417 /* TODO: This should never be hit. */
3418 TODO
3419 return;
3420 }
3421}
3422
3423static void
3424xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3425{
3426 if (schema->volatiles == NULL)
3427 return;
3428 {
3429 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3430 xmlSchemaTreeItemPtr item;
3431 int i;
3432
3433 for (i = 0; i < list->nbItems; i++) {
3434 if (list->items[i] != NULL) {
3435 item = (xmlSchemaTreeItemPtr) list->items[i];
3436 switch (item->type) {
3437 case XML_SCHEMA_EXTRA_QNAMEREF:
3438 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3439 break;
3440 default:
3441 xmlSchemaFreeMiscComponents(item);
3442 }
3443 }
3444 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003445 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003446 }
3447}
3448/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003449 * xmlSchemaFreeTypeList:
3450 * @type: a schema type structure
3451 *
3452 * Deallocate a Schema Type structure.
3453 */
3454static void
3455xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3456{
3457 xmlSchemaTypePtr next;
3458
3459 while (type != NULL) {
3460 next = type->redef;
3461 xmlSchemaFreeType(type);
3462 type = next;
3463 }
3464}
3465
3466/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003467 * xmlSchemaFree:
3468 * @schema: a schema structure
3469 *
3470 * Deallocate a Schema structure.
3471 */
3472void
3473xmlSchemaFree(xmlSchemaPtr schema)
3474{
3475 if (schema == NULL)
3476 return;
3477
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003478 if (schema->volatiles != NULL)
3479 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003480 if (schema->notaDecl != NULL)
3481 xmlHashFree(schema->notaDecl,
3482 (xmlHashDeallocator) xmlSchemaFreeNotation);
3483 if (schema->attrDecl != NULL)
3484 xmlHashFree(schema->attrDecl,
3485 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3486 if (schema->attrgrpDecl != NULL)
3487 xmlHashFree(schema->attrgrpDecl,
3488 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3489 if (schema->elemDecl != NULL)
3490 xmlHashFree(schema->elemDecl,
3491 (xmlHashDeallocator) xmlSchemaFreeElement);
3492 if (schema->typeDecl != NULL)
3493 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003494 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003495 if (schema->groupDecl != NULL)
3496 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003497 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003498 if (schema->idcDef != NULL)
3499 xmlHashFree(schema->idcDef,
3500 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003501 if (schema->schemasImports != NULL)
3502 xmlHashFree(schema->schemasImports,
3503 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003504 if (schema->includes != NULL) {
3505 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3506 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003508 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003509 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003510 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003511 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003512 xmlFree(schema);
3513}
3514
3515/************************************************************************
3516 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003517 * Debug functions *
3518 * *
3519 ************************************************************************/
3520
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003521#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003522
Daniel Veillard4255d502002-04-16 15:50:10 +00003523/**
3524 * xmlSchemaElementDump:
3525 * @elem: an element
3526 * @output: the file output
3527 *
3528 * Dump the element
3529 */
3530static void
3531xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003532 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003533 const xmlChar * namespace ATTRIBUTE_UNUSED,
3534 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003535{
3536 if (elem == NULL)
3537 return;
3538
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003539 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3540 fprintf(output, "Particle: %s", name);
3541 fprintf(output, ", term element: %s", elem->ref);
3542 if (elem->refNs != NULL)
3543 fprintf(output, " ns %s", elem->refNs);
3544 } else {
3545 fprintf(output, "Element");
3546 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3547 fprintf(output, " (global)");
3548 fprintf(output, ": %s ", elem->name);
3549 if (namespace != NULL)
3550 fprintf(output, "ns %s", namespace);
3551 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003552 fprintf(output, "\n");
3553 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003554 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003555 if (elem->maxOccurs >= UNBOUNDED)
3556 fprintf(output, "max: unbounded\n");
3557 else if (elem->maxOccurs != 1)
3558 fprintf(output, "max: %d\n", elem->maxOccurs);
3559 else
3560 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003561 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003562 /*
3563 * Misc other properties.
3564 */
3565 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3566 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3567 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3568 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3569 (elem->id != NULL)) {
3570 fprintf(output, " props: ");
3571 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3572 fprintf(output, "[fixed] ");
3573 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3574 fprintf(output, "[default] ");
3575 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3576 fprintf(output, "[abstract] ");
3577 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3578 fprintf(output, "[nillable] ");
3579 if (elem->id != NULL)
3580 fprintf(output, "[id: '%s'] ", elem->id);
3581 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003582 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003583 /*
3584 * Default/fixed value.
3585 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003586 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003587 fprintf(output, " value: '%s'\n", elem->value);
3588 /*
3589 * Type.
3590 */
3591 if (elem->namedType != NULL) {
3592 fprintf(output, " type: %s ", elem->namedType);
3593 if (elem->namedTypeNs != NULL)
3594 fprintf(output, "ns %s\n", elem->namedTypeNs);
3595 else
3596 fprintf(output, "\n");
3597 }
3598 /*
3599 * Substitution group.
3600 */
3601 if (elem->substGroup != NULL) {
3602 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3603 if (elem->substGroupNs != NULL)
3604 fprintf(output, "ns %s\n", elem->substGroupNs);
3605 else
3606 fprintf(output, "\n");
3607 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003608}
3609
3610/**
3611 * xmlSchemaAnnotDump:
3612 * @output: the file output
3613 * @annot: a annotation
3614 *
3615 * Dump the annotation
3616 */
3617static void
3618xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3619{
3620 xmlChar *content;
3621
3622 if (annot == NULL)
3623 return;
3624
3625 content = xmlNodeGetContent(annot->content);
3626 if (content != NULL) {
3627 fprintf(output, " Annot: %s\n", content);
3628 xmlFree(content);
3629 } else
3630 fprintf(output, " Annot: empty\n");
3631}
3632
3633/**
3634 * xmlSchemaTypeDump:
3635 * @output: the file output
3636 * @type: a type structure
3637 *
3638 * Dump a SchemaType structure
3639 */
3640static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003641xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3642{
3643 xmlChar *str = NULL;
3644 xmlSchemaTreeItemPtr term;
3645 char shift[100];
3646 int i;
3647
3648 if (particle == NULL)
3649 return;
3650 for (i = 0;((i < depth) && (i < 25));i++)
3651 shift[2 * i] = shift[2 * i + 1] = ' ';
3652 shift[2 * i] = shift[2 * i + 1] = 0;
3653 fprintf(output, shift);
3654 if (particle->children == NULL) {
3655 fprintf(output, "MISSING particle term\n");
3656 return;
3657 }
3658 term = particle->children;
3659 switch (term->type) {
3660 case XML_SCHEMA_TYPE_ELEMENT:
3661 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
3662 ((xmlSchemaElementPtr)term)->targetNamespace,
3663 ((xmlSchemaElementPtr)term)->name));
3664 break;
3665 case XML_SCHEMA_TYPE_SEQUENCE:
3666 fprintf(output, "SEQUENCE");
3667 break;
3668 case XML_SCHEMA_TYPE_CHOICE:
3669 fprintf(output, "CHOICE");
3670 break;
3671 case XML_SCHEMA_TYPE_ALL:
3672 fprintf(output, "ALL");
3673 break;
3674 case XML_SCHEMA_TYPE_ANY:
3675 fprintf(output, "ANY");
3676 break;
3677 default:
3678 fprintf(output, "UNKNOWN\n");
3679 return;
3680 }
3681 if (particle->minOccurs != 1)
3682 fprintf(output, " min: %d", particle->minOccurs);
3683 if (particle->maxOccurs >= UNBOUNDED)
3684 fprintf(output, " max: unbounded");
3685 else if (particle->maxOccurs != 1)
3686 fprintf(output, " max: %d", particle->maxOccurs);
3687 fprintf(output, "\n");
3688 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3689 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3690 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3691 (term->children != NULL)) {
3692 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3693 output, depth +1);
3694 }
3695 if (particle->next != NULL)
3696 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3697 output, depth);
3698}
3699/**
3700 * xmlSchemaTypeDump:
3701 * @output: the file output
3702 * @type: a type structure
3703 *
3704 * Dump a SchemaType structure
3705 */
3706static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003707xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3708{
3709 if (type == NULL) {
3710 fprintf(output, "Type: NULL\n");
3711 return;
3712 }
3713 fprintf(output, "Type: ");
3714 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003715 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003717 fprintf(output, "no name ");
3718 if (type->targetNamespace != NULL)
3719 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003720 switch (type->type) {
3721 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003722 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003723 break;
3724 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003725 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 break;
3727 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003728 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 break;
3730 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003731 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003732 break;
3733 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003734 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003735 break;
3736 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003737 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003738 break;
3739 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003740 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003741 break;
3742 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003743 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003744 break;
3745 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003746 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003747 break;
3748 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003749 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003750 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003751 }
3752 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003753 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003754 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003755 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003756 break;
3757 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003758 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003759 break;
3760 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003761 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003762 break;
3763 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003764 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003765 break;
3766 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003767 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003768 break;
3769 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003770 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003771 break;
3772 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003773 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003774 break;
3775 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003776 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003778 }
3779 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003780 if (type->base != NULL) {
3781 fprintf(output, " base type: %s", type->base);
3782 if (type->baseNs != NULL)
3783 fprintf(output, " ns %s\n", type->baseNs);
3784 else
3785 fprintf(output, "\n");
3786 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003787 if (type->annot != NULL)
3788 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003789#ifdef DUMP_CONTENT_MODEL
3790 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3791 (type->subtypes != NULL)) {
3792 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3793 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003794 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003795#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003796}
3797
3798/**
3799 * xmlSchemaDump:
3800 * @output: the file output
3801 * @schema: a schema structure
3802 *
3803 * Dump a Schema structure.
3804 */
3805void
3806xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3807{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003808 if (output == NULL)
3809 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003810 if (schema == NULL) {
3811 fprintf(output, "Schemas: NULL\n");
3812 return;
3813 }
3814 fprintf(output, "Schemas: ");
3815 if (schema->name != NULL)
3816 fprintf(output, "%s, ", schema->name);
3817 else
3818 fprintf(output, "no name, ");
3819 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003820 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003821 else
3822 fprintf(output, "no target namespace");
3823 fprintf(output, "\n");
3824 if (schema->annot != NULL)
3825 xmlSchemaAnnotDump(output, schema->annot);
3826
3827 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3828 output);
3829 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003830 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003831}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003832
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003833#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003834/**
3835 * xmlSchemaDebugDumpIDCTable:
3836 * @vctxt: the WXS validation context
3837 *
3838 * Displays the current IDC table for debug purposes.
3839 */
3840static void
3841xmlSchemaDebugDumpIDCTable(FILE * output,
3842 const xmlChar *namespaceName,
3843 const xmlChar *localName,
3844 xmlSchemaPSVIIDCBindingPtr bind)
3845{
3846 xmlChar *str = NULL, *value;
3847 xmlSchemaPSVIIDCNodePtr tab;
3848 xmlSchemaPSVIIDCKeyPtr key;
3849 int i, j, res;
3850
3851 fprintf(output, "IDC: TABLES on %s\n",
3852 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3853 FREE_AND_NULL(str)
3854
3855 if (bind == NULL)
3856 return;
3857 do {
3858 fprintf(output, "IDC: BINDING %s\n",
3859 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3860 bind->definition->name));
3861 FREE_AND_NULL(str)
3862 for (i = 0; i < bind->nbNodes; i++) {
3863 tab = bind->nodeTable[i];
3864 fprintf(output, " ( ");
3865 for (j = 0; j < bind->definition->nbFields; j++) {
3866 key = tab->keys[j];
3867 if ((key != NULL) && (key->compValue != NULL)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003868 res = xmlSchemaGetCanonValue(key->compValue, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003869 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003870 fprintf(output, "\"%s\" ", value);
3871 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003872 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003873 if (res == 0)
3874 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003875 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003876 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003877 else
3878 fprintf(output, "(key missing), ");
3879 }
3880 fprintf(output, ")\n");
3881 }
3882 bind = bind->next;
3883 } while (bind != NULL);
3884}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003885#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003886#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003887
3888/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003889 * *
3890 * Utilities *
3891 * *
3892 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003893
Daniel Veillardc0826a72004-08-10 14:17:33 +00003894/**
3895 * xmlSchemaGetPropNode:
3896 * @node: the element node
3897 * @name: the name of the attribute
3898 *
3899 * Seeks an attribute with a name of @name in
3900 * no namespace.
3901 *
3902 * Returns the attribute or NULL if not present.
3903 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003904static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003905xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003906{
3907 xmlAttrPtr prop;
3908
Daniel Veillardc0826a72004-08-10 14:17:33 +00003909 if ((node == NULL) || (name == NULL))
3910 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003911 prop = node->properties;
3912 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003913 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3914 return(prop);
3915 prop = prop->next;
3916 }
3917 return (NULL);
3918}
3919
3920/**
3921 * xmlSchemaGetPropNodeNs:
3922 * @node: the element node
3923 * @uri: the uri
3924 * @name: the name of the attribute
3925 *
3926 * Seeks an attribute with a local name of @name and
3927 * a namespace URI of @uri.
3928 *
3929 * Returns the attribute or NULL if not present.
3930 */
3931static xmlAttrPtr
3932xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3933{
3934 xmlAttrPtr prop;
3935
3936 if ((node == NULL) || (name == NULL))
3937 return(NULL);
3938 prop = node->properties;
3939 while (prop != NULL) {
3940 if ((prop->ns != NULL) &&
3941 xmlStrEqual(prop->name, BAD_CAST name) &&
3942 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003943 return(prop);
3944 prop = prop->next;
3945 }
3946 return (NULL);
3947}
3948
3949static const xmlChar *
3950xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3951{
3952 xmlChar *val;
3953 const xmlChar *ret;
3954
3955 val = xmlNodeGetContent(node);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003956 if (val == NULL)
3957 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003958 ret = xmlDictLookup(ctxt->dict, val, -1);
3959 xmlFree(val);
3960 return(ret);
3961}
3962
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003963/**
3964 * xmlSchemaGetProp:
3965 * @ctxt: the parser context
3966 * @node: the node
3967 * @name: the property name
3968 *
3969 * Read a attribute value and internalize the string
3970 *
3971 * Returns the string or NULL if not present.
3972 */
3973static const xmlChar *
3974xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3975 const char *name)
3976{
3977 xmlChar *val;
3978 const xmlChar *ret;
3979
3980 val = xmlGetProp(node, BAD_CAST name);
3981 if (val == NULL)
3982 return(NULL);
3983 ret = xmlDictLookup(ctxt->dict, val, -1);
3984 xmlFree(val);
3985 return(ret);
3986}
3987
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003988/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003989 * *
3990 * Parsing functions *
3991 * *
3992 ************************************************************************/
3993
3994/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003995 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003996 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003997 * @name: the element name
3998 * @ns: the element namespace
3999 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004000 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004001 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004002 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004003 */
4004static xmlSchemaElementPtr
4005xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004006 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004007{
4008 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004009
4010 if ((name == NULL) || (schema == NULL))
4011 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004012
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004013 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004014 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004015 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004016 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004017 } else
4018 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00004019 /*
4020 * This one was removed, since top level element declarations have
4021 * the target namespace specified in targetNamespace of the <schema>
4022 * information element, even if elementFormDefault is "unqualified".
4023 */
4024
4025 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004026 if (xmlStrEqual(namespace, schema->targetNamespace))
4027 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
4028 else
4029 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004030 if ((ret != NULL) &&
4031 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004032 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004033 }
William M. Bracke7091952004-05-11 15:09:58 +00004034 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004035
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 /*
4037 * Removed since imported components will be hold by the main schema only.
4038 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004040 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004042 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004043 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00004044 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00004045 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
4046 return (ret);
4047 } else
4048 ret = NULL;
4049 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004050 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004051#ifdef DEBUG
4052 if (ret == NULL) {
4053 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004054 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004055 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004056 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004057 namespace);
4058 }
4059#endif
4060 return (ret);
4061}
4062
4063/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004064 * xmlSchemaGetType:
4065 * @schema: the schemas context
4066 * @name: the type name
4067 * @ns: the type namespace
4068 *
4069 * Lookup a type in the schemas or the predefined types
4070 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004071 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004072 */
4073static xmlSchemaTypePtr
4074xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004075 const xmlChar * namespace)
4076{
Daniel Veillard4255d502002-04-16 15:50:10 +00004077 xmlSchemaTypePtr ret;
4078
4079 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004080 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004081 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004082 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 }
4086 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00004087 if (ret != NULL)
4088 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004089 /*
4090 * Removed, since the imported components will be grafted on the
4091 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004092 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004093 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004094 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004095 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004096 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004097 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004098 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4099 return (ret);
4100 } else
4101 ret = NULL;
4102 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004103 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004104#ifdef DEBUG
4105 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004106 if (namespace == NULL)
4107 fprintf(stderr, "Unable to lookup type %s", name);
4108 else
4109 fprintf(stderr, "Unable to lookup type %s:%s", name,
4110 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004111 }
4112#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004113 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004114}
4115
Daniel Veillard3646d642004-06-02 19:19:14 +00004116/**
4117 * xmlSchemaGetAttribute:
4118 * @schema: the context of the schema
4119 * @name: the name of the attribute
4120 * @ns: the target namespace of the attribute
4121 *
4122 * Lookup a an attribute in the schema or imported schemas
4123 *
4124 * Returns the attribute declaration or NULL if not found.
4125 */
4126static xmlSchemaAttributePtr
4127xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
4128 const xmlChar * namespace)
4129{
4130 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004131
4132 if ((name == NULL) || (schema == NULL))
4133 return (NULL);
4134
4135
4136 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4137 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
4138 return (ret);
4139 else
4140 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004141 /*
4142 * Removed, since imported components will be hold by the main schema only.
4143 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004144 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004146 else
4147 import = xmlHashLookup(schema->schemasImports, namespace);
4148 if (import != NULL) {
4149 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
4150 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4151 return (ret);
4152 } else
4153 ret = NULL;
4154 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004155 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004156#ifdef DEBUG
4157 if (ret == NULL) {
4158 if (namespace == NULL)
4159 fprintf(stderr, "Unable to lookup attribute %s", name);
4160 else
4161 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4162 namespace);
4163 }
4164#endif
4165 return (ret);
4166}
4167
4168/**
4169 * xmlSchemaGetAttributeGroup:
4170 * @schema: the context of the schema
4171 * @name: the name of the attribute group
4172 * @ns: the target namespace of the attribute group
4173 *
4174 * Lookup a an attribute group in the schema or imported schemas
4175 *
4176 * Returns the attribute group definition or NULL if not found.
4177 */
4178static xmlSchemaAttributeGroupPtr
4179xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4180 const xmlChar * namespace)
4181{
4182 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004183
4184 if ((name == NULL) || (schema == NULL))
4185 return (NULL);
4186
4187
4188 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4189 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4190 return (ret);
4191 else
4192 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004193 /*
4194 * Removed since imported components will be hold by the main schema only.
4195 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004196 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004197 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004198 else
4199 import = xmlHashLookup(schema->schemasImports, namespace);
4200 if (import != NULL) {
4201 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4202 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4203 return (ret);
4204 else
4205 ret = NULL;
4206 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004207 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004208#ifdef DEBUG
4209 if (ret == NULL) {
4210 if (namespace == NULL)
4211 fprintf(stderr, "Unable to lookup attribute group %s", name);
4212 else
4213 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4214 namespace);
4215 }
4216#endif
4217 return (ret);
4218}
4219
4220/**
4221 * xmlSchemaGetGroup:
4222 * @schema: the context of the schema
4223 * @name: the name of the group
4224 * @ns: the target namespace of the group
4225 *
4226 * Lookup a group in the schema or imported schemas
4227 *
4228 * Returns the group definition or NULL if not found.
4229 */
4230static xmlSchemaTypePtr
4231xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4232 const xmlChar * namespace)
4233{
4234 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004235
4236 if ((name == NULL) || (schema == NULL))
4237 return (NULL);
4238
Daniel Veillard3646d642004-06-02 19:19:14 +00004239 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004240 /*
4241 * Removed since imported components will be hold by the main schema only.
4242 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004243 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004244 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004245 else
4246 import = xmlHashLookup(schema->schemasImports, namespace);
4247 if (import != NULL) {
4248 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4249 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4250 return (ret);
4251 else
4252 ret = NULL;
4253 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004254 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004255#ifdef DEBUG
4256 if (ret == NULL) {
4257 if (namespace == NULL)
4258 fprintf(stderr, "Unable to lookup group %s", name);
4259 else
4260 fprintf(stderr, "Unable to lookup group %s:%s", name,
4261 namespace);
4262 }
4263#endif
4264 return (ret);
4265}
4266
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004267/**
4268 * xmlSchemaGetNamedComponent:
4269 * @schema: the schema
4270 * @name: the name of the group
4271 * @ns: the target namespace of the group
4272 *
4273 * Lookup a group in the schema or imported schemas
4274 *
4275 * Returns the group definition or NULL if not found.
4276 */
4277static xmlSchemaTreeItemPtr
4278xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4279 xmlSchemaTypeType itemType,
4280 const xmlChar *name,
4281 const xmlChar *targetNs)
4282{
4283 switch (itemType) {
4284 case XML_SCHEMA_TYPE_GROUP:
4285 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4286 name, targetNs));
4287 case XML_SCHEMA_TYPE_ELEMENT:
4288 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4289 name, targetNs));
4290 default:
4291 return (NULL);
4292 }
4293}
4294
Daniel Veillard4255d502002-04-16 15:50:10 +00004295/************************************************************************
4296 * *
4297 * Parsing functions *
4298 * *
4299 ************************************************************************/
4300
4301#define IS_BLANK_NODE(n) \
4302 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
4303
4304/**
4305 * xmlSchemaIsBlank:
4306 * @str: a string
4307 *
4308 * Check if a string is ignorable
4309 *
4310 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4311 */
4312static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004313xmlSchemaIsBlank(xmlChar * str)
4314{
Daniel Veillard4255d502002-04-16 15:50:10 +00004315 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004316 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00004318 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 return (0);
4320 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004321 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004322 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004323}
4324
4325/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004326 * xmlSchemaAddAssembledItem:
4327 * @ctxt: a schema parser context
4328 * @schema: the schema being built
4329 * @item: the item
4330 *
4331 * Add a item to the schema's list of current items.
4332 * This is used if the schema was already constructed and
4333 * new schemata need to be added to it.
4334 * *WARNING* this interface is highly subject to change.
4335 *
4336 * Returns 0 if suceeds and -1 if an internal error occurs.
4337 */
4338static int
4339xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4340 xmlSchemaTypePtr item)
4341{
4342 static int growSize = 100;
4343 xmlSchemaAssemblePtr ass;
4344
4345 ass = ctxt->assemble;
4346 if (ass->sizeItems < 0) {
4347 /* If disabled. */
4348 return (0);
4349 }
4350 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004351 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004352 if (ass->items == NULL) {
4353 xmlSchemaPErrMemory(ctxt,
4354 "allocating new item buffer", NULL);
4355 return (-1);
4356 }
4357 ass->sizeItems = growSize;
4358 } else if (ass->sizeItems <= ass->nbItems) {
4359 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004360 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004361 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4362 if (ass->items == NULL) {
4363 xmlSchemaPErrMemory(ctxt,
4364 "growing item buffer", NULL);
4365 ass->sizeItems = 0;
4366 return (-1);
4367 }
4368 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004369 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004370 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4371 return (0);
4372}
4373
4374/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004376 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004377 * @schema: the schema being built
4378 * @name: the item name
4379 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004380 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 * *WARNING* this interface is highly subject to change
4382 *
4383 * Returns the new struture or NULL in case of error
4384 */
4385static xmlSchemaNotationPtr
4386xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004387 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004388{
4389 xmlSchemaNotationPtr ret = NULL;
4390 int val;
4391
4392 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4393 return (NULL);
4394
4395 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004396 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 if (schema->notaDecl == NULL)
4398 return (NULL);
4399
4400 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4401 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 return (NULL);
4404 }
4405 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004406 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004407 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4408 ret);
4409 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004410 /*
4411 * TODO: This should never happen, since a unique name will be computed.
4412 * If it fails, then an other internal error must have occured.
4413 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4415 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004416 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 xmlFree(ret);
4419 return (NULL);
4420 }
4421 return (ret);
4422}
4423
4424
4425/**
4426 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004427 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004428 * @schema: the schema being built
4429 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004430 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004431 *
4432 * Add an XML schema Attrribute declaration
4433 * *WARNING* this interface is highly subject to change
4434 *
4435 * Returns the new struture or NULL in case of error
4436 */
4437static xmlSchemaAttributePtr
4438xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004439 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004440 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004441{
4442 xmlSchemaAttributePtr ret = NULL;
4443 int val;
4444
4445 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4446 return (NULL);
4447
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004448#ifdef DEBUG
4449 fprintf(stderr, "Adding attribute %s\n", name);
4450 if (namespace != NULL)
4451 fprintf(stderr, " target namespace %s\n", namespace);
4452#endif
4453
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004455 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 if (schema->attrDecl == NULL)
4457 return (NULL);
4458
4459 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4460 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004461 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004462 return (NULL);
4463 }
4464 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004465 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004466 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004467 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004468 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004469 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004470 if (topLevel) {
4471 xmlSchemaPCustomErr(ctxt,
4472 XML_SCHEMAP_REDEFINED_ATTR,
4473 NULL, NULL, node,
4474 "A global attribute declaration with the name '%s' does "
4475 "already exist", name);
4476 xmlFree(ret);
4477 return (NULL);
4478 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004479 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004480 /*
4481 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4482 * in the scenario:
4483 * 1. multiple top-level complex types have different target
4484 * namespaces but have the SAME NAME; this can happen if
4485 * schemata are imported
4486 * 2. those complex types contain attributes with an equal name
4487 * 3. those attributes are in no namespace
4488 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004489 */
4490 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004491 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004492 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004493
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004494 if (val != 0) {
4495 xmlSchemaPCustomErr(ctxt,
4496 XML_SCHEMAP_INTERNAL,
4497 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004498 "Internal error: xmlSchemaAddAttribute, "
4499 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004500 "could not be added to the hash.", name);
4501 xmlFree(ret);
4502 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004503 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004504 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004506 if (ctxt->assemble != NULL)
4507 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004508 return (ret);
4509}
4510
4511/**
4512 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004513 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 * @schema: the schema being built
4515 * @name: the item name
4516 *
4517 * Add an XML schema Attrribute Group declaration
4518 *
4519 * Returns the new struture or NULL in case of error
4520 */
4521static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004522xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004523 xmlSchemaPtr schema, const xmlChar * name,
4524 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004525{
4526 xmlSchemaAttributeGroupPtr ret = NULL;
4527 int val;
4528
4529 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4530 return (NULL);
4531
4532 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004533 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 if (schema->attrgrpDecl == NULL)
4535 return (NULL);
4536
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004537 ret =
4538 (xmlSchemaAttributeGroupPtr)
4539 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004541 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004542 return (NULL);
4543 }
4544 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004545 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004546 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004547 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004548 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004549 xmlSchemaPCustomErr(ctxt,
4550 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4551 NULL, NULL, node,
4552 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004553 xmlFree(ret);
4554 return (NULL);
4555 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004556 if (ctxt->assemble != NULL)
4557 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004558 return (ret);
4559}
4560
4561/**
4562 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004563 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004564 * @schema: the schema being built
4565 * @name: the type name
4566 * @namespace: the type namespace
4567 *
4568 * Add an XML schema Element declaration
4569 * *WARNING* this interface is highly subject to change
4570 *
4571 * Returns the new struture or NULL in case of error
4572 */
4573static xmlSchemaElementPtr
4574xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004575 const xmlChar * name, const xmlChar * namespace,
4576 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004577{
4578 xmlSchemaElementPtr ret = NULL;
4579 int val;
4580
4581 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4582 return (NULL);
4583
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004584#ifdef DEBUG
4585 fprintf(stderr, "Adding element %s\n", name);
4586 if (namespace != NULL)
4587 fprintf(stderr, " target namespace %s\n", namespace);
4588#endif
4589
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004591 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 if (schema->elemDecl == NULL)
4593 return (NULL);
4594
4595 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4596 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 return (NULL);
4599 }
4600 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004601 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004602 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004604 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004605 if (topLevel) {
4606 xmlSchemaPCustomErr(ctxt,
4607 XML_SCHEMAP_REDEFINED_ELEMENT,
4608 NULL, NULL, node,
4609 "A global element declaration with the name '%s' does "
4610 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004611 xmlFree(ret);
4612 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004613 } else {
4614 char buf[30];
4615
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004616 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004617 val = xmlHashAddEntry3(schema->elemDecl, name,
4618 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004619 if (val != 0) {
4620 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004621 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004622 NULL, NULL, node,
4623 "Internal error: xmlSchemaAddElement, "
4624 "a dublicate element declaration with the name '%s' "
4625 "could not be added to the hash.", name);
4626 xmlFree(ret);
4627 return (NULL);
4628 }
4629 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004630
Daniel Veillard4255d502002-04-16 15:50:10 +00004631 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004632 if (ctxt->assemble != NULL)
4633 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004634 return (ret);
4635}
4636
4637/**
4638 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004639 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004640 * @schema: the schema being built
4641 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004642 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004643 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004644 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004645 * *WARNING* this interface is highly subject to change
4646 *
4647 * Returns the new struture or NULL in case of error
4648 */
4649static xmlSchemaTypePtr
4650xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004651 const xmlChar * name, const xmlChar * namespace,
4652 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004653{
4654 xmlSchemaTypePtr ret = NULL;
4655 int val;
4656
4657 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4658 return (NULL);
4659
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004660#ifdef DEBUG
4661 fprintf(stderr, "Adding type %s\n", name);
4662 if (namespace != NULL)
4663 fprintf(stderr, " target namespace %s\n", namespace);
4664#endif
4665
Daniel Veillard4255d502002-04-16 15:50:10 +00004666 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004667 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004668 if (schema->typeDecl == NULL)
4669 return (NULL);
4670
4671 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4672 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004673 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004674 return (NULL);
4675 }
4676 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004677 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004678 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004679 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004680 if (val != 0) {
4681 if (ctxt->includes == 0) {
4682 xmlSchemaPCustomErr(ctxt,
4683 XML_SCHEMAP_REDEFINED_TYPE,
4684 NULL, NULL, node,
4685 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004686 xmlFree(ret);
4687 return (NULL);
4688 } else {
4689 xmlSchemaTypePtr prev;
4690
4691 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4692 if (prev == NULL) {
4693 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004694 XML_ERR_INTERNAL_ERROR,
4695 "Internal error: xmlSchemaAddType, on type "
4696 "'%s'.\n",
4697 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004698 xmlFree(ret);
4699 return (NULL);
4700 }
4701 ret->redef = prev->redef;
4702 prev->redef = ret;
4703 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004704 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004705 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004706 ret->minOccurs = 1;
4707 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004708 ret->attributeUses = NULL;
4709 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004710 if (ctxt->assemble != NULL)
4711 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004712 return (ret);
4713}
4714
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004715static xmlSchemaQNameRefPtr
4716xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4717 xmlSchemaTypeType refType,
4718 const xmlChar *refName,
4719 const xmlChar *refNs)
4720{
4721 xmlSchemaQNameRefPtr ret;
4722
4723 ret = (xmlSchemaQNameRefPtr)
4724 xmlMalloc(sizeof(xmlSchemaQNameRef));
4725 if (ret == NULL) {
4726 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4727 NULL);
4728 return (NULL);
4729 }
4730 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4731 ret->name = refName;
4732 ret->targetNamespace = refNs;
4733 ret->item = NULL;
4734 ret->itemType = refType;
4735 /*
4736 * Store the reference item in the schema.
4737 */
4738 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4739 return (ret);
4740}
4741
4742/**
4743 * xmlSchemaAddModelGroup:
4744 * @ctxt: a schema parser context
4745 * @schema: the schema being built
4746 * @type: the "compositor" type of the model group
4747 * @container: the internal component name
4748 * @node: the node in the schema doc
4749 *
4750 * Adds a schema model group
4751 * *WARNING* this interface is highly subject to change
4752 *
4753 * Returns the new struture or NULL in case of error
4754 */
4755static xmlSchemaModelGroupPtr
4756xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4757 xmlSchemaTypeType type, const xmlChar **container,
4758 xmlNodePtr node)
4759{
4760 xmlSchemaModelGroupPtr ret = NULL;
4761 xmlChar buf[30];
4762
4763 if ((ctxt == NULL) || (schema == NULL))
4764 return (NULL);
4765
4766#ifdef DEBUG
4767 fprintf(stderr, "Adding model group component\n");
4768#endif
4769 ret = (xmlSchemaModelGroupPtr)
4770 xmlMalloc(sizeof(xmlSchemaModelGroup));
4771 if (ret == NULL) {
4772 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4773 NULL);
4774 return (NULL);
4775 }
4776 ret->type = type;
4777 ret->annot = NULL;
4778 ret->node = node;
4779 ret->children = NULL;
4780 ret->next = NULL;
4781 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4782 if (container != NULL)
4783 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4784 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
4785 if (container != NULL)
4786 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4787 } else {
4788 if (container != NULL)
4789 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4790 }
4791 if (container != NULL)
4792 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4793 /*
4794 * Add to volatile items.
4795 * TODO: this should be changed someday.
4796 */
4797 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4798 xmlFree(ret);
4799 return (NULL);
4800 }
4801 return (ret);
4802}
4803
4804
4805/**
4806 * xmlSchemaAddParticle:
4807 * @ctxt: a schema parser context
4808 * @schema: the schema being built
4809 * @node: the corresponding node in the schema doc
4810 * @min: the minOccurs
4811 * @max: the maxOccurs
4812 *
4813 * Adds an XML schema particle component.
4814 * *WARNING* this interface is highly subject to change
4815 *
4816 * Returns the new struture or NULL in case of error
4817 */
4818static xmlSchemaParticlePtr
4819xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4820 xmlNodePtr node, int min, int max)
4821{
4822 xmlSchemaParticlePtr ret = NULL;
4823 if ((ctxt == NULL) || (schema == NULL))
4824 return (NULL);
4825
4826#ifdef DEBUG
4827 fprintf(stderr, "Adding particle component\n");
4828#endif
4829 ret = (xmlSchemaParticlePtr)
4830 xmlMalloc(sizeof(xmlSchemaParticle));
4831 if (ret == NULL) {
4832 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4833 NULL);
4834 return (NULL);
4835 }
4836 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4837 ret->annot = NULL;
4838 ret->node = node;
4839 ret->minOccurs = min;
4840 ret->maxOccurs = max;
4841 ret->next = NULL;
4842 ret->children = NULL;
4843
4844 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4845 xmlFree(ret);
4846 return (NULL);
4847 }
4848 return (ret);
4849}
4850
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004851/**
4852 * xmlSchemaAddGroup:
4853 * @ctxt: a schema validation context
4854 * @schema: the schema being built
4855 * @name: the group name
4856 *
4857 * Add an XML schema Group definition
4858 *
4859 * Returns the new struture or NULL in case of error
4860 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004861static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004862xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004863 const xmlChar *name, const xmlChar *namespaceName,
4864 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004865{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004866 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004867 int val;
4868
4869 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4870 return (NULL);
4871
4872 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004873 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004874 if (schema->groupDecl == NULL)
4875 return (NULL);
4876
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004877 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004878 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004879 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004880 return (NULL);
4881 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004882 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004883 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004884 ret->type = XML_SCHEMA_TYPE_GROUP;
4885 ret->node = node;
4886 ret->targetNamespace = namespaceName;
4887 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004888 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004889 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004890 XML_SCHEMAP_REDEFINED_GROUP,
4891 NULL, NULL, node,
4892 "A global model group definition with the name '%s' does already "
4893 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004894 xmlFree(ret);
4895 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004896 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004897 if (ctxt->assemble != NULL)
4898 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004899 return (ret);
4900}
4901
Daniel Veillard3646d642004-06-02 19:19:14 +00004902/**
4903 * xmlSchemaNewWildcardNs:
4904 * @ctxt: a schema validation context
4905 *
4906 * Creates a new wildcard namespace constraint.
4907 *
4908 * Returns the new struture or NULL in case of error
4909 */
4910static xmlSchemaWildcardNsPtr
4911xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4912{
4913 xmlSchemaWildcardNsPtr ret;
4914
4915 ret = (xmlSchemaWildcardNsPtr)
4916 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4917 if (ret == NULL) {
4918 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4919 return (NULL);
4920 }
4921 ret->value = NULL;
4922 ret->next = NULL;
4923 return (ret);
4924}
4925
4926/**
4927 * xmlSchemaAddWildcard:
4928 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004929 * @schema: a schema
4930 *
4931 * Adds a wildcard.
4932 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004933 *
4934 * Returns the new struture or NULL in case of error
4935 */
4936static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004937xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4938 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004939{
4940 xmlSchemaWildcardPtr ret = NULL;
4941
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004942 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004943 return (NULL);
4944
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004945#ifdef DEBUG
4946 fprintf(stderr, "Adding wildcard component\n");
4947#endif
4948
Daniel Veillard3646d642004-06-02 19:19:14 +00004949 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4950 if (ret == NULL) {
4951 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4952 return (NULL);
4953 }
4954 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004955 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004956 ret->minOccurs = 1;
4957 ret->maxOccurs = 1;
4958
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004959 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4960 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4961 "Failed to add a wildcard component to the list", NULL);
4962 xmlFree(ret);
4963 return (NULL);
4964 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004965 return (ret);
4966}
4967
Daniel Veillard4255d502002-04-16 15:50:10 +00004968/************************************************************************
4969 * *
4970 * Utilities for parsing *
4971 * *
4972 ************************************************************************/
4973
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004974#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004975/**
4976 * xmlGetQNameProp:
4977 * @ctxt: a schema validation context
4978 * @node: a subtree containing XML Schema informations
4979 * @name: the attribute name
4980 * @namespace: the result namespace if any
4981 *
4982 * Extract a QName Attribute value
4983 *
4984 * Returns the NCName or NULL if not found, and also update @namespace
4985 * with the namespace URI
4986 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004987static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004988xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004989 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004990{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004991 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004992 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004993 const xmlChar *ret, *prefix;
4994 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004995 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004996
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004997 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004998 attr = xmlSchemaGetPropNode(node, name);
4999 if (attr == NULL)
5000 return (NULL);
5001 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005002
Daniel Veillard4255d502002-04-16 15:50:10 +00005003 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005004 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005005
Daniel Veillardba0153a2004-04-01 10:42:31 +00005006 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00005007 ns = xmlSearchNs(node->doc, node, 0);
5008 if (ns) {
5009 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5010 return (val);
5011 }
5012 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005013 ret = xmlSplitQName3(val, &len);
5014 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005015 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005016 }
5017 ret = xmlDictLookup(ctxt->dict, ret, -1);
5018 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00005019
5020 ns = xmlSearchNs(node->doc, node, prefix);
5021 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005022 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
5023 NULL, NULL, (xmlNodePtr) attr,
5024 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005025 "The QName value '%s' has no corresponding namespace "
5026 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005027 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005028 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005029 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005030 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005031}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005032#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005033
5034/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005035 * xmlSchemaPValAttrNodeQNameValue:
5036 * @ctxt: a schema parser context
5037 * @schema: the schema context
5038 * @ownerDes: the designation of the parent element
5039 * @ownerItem: the parent as a schema object
5040 * @value: the QName value
5041 * @local: the resulting local part if found, the attribute value otherwise
5042 * @uri: the resulting namespace URI if found
5043 *
5044 * Extracts the local name and the URI of a QName value and validates it.
5045 * This one is intended to be used on attribute values that
5046 * should resolve to schema components.
5047 *
5048 * Returns 0, in case the QName is valid, a positive error code
5049 * if not valid and -1 if an internal error occurs.
5050 */
5051static int
5052xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5053 xmlSchemaPtr schema,
5054 xmlChar **ownerDes,
5055 xmlSchemaTypePtr ownerItem,
5056 xmlAttrPtr attr,
5057 const xmlChar *value,
5058 const xmlChar **uri,
5059 const xmlChar **prefix,
5060 const xmlChar **local)
5061{
5062 const xmlChar *pref;
5063 xmlNsPtr ns;
5064 int len, ret;
5065
5066 *uri = NULL;
5067 *local = NULL;
5068 if (prefix != 0)
5069 *prefix = NULL;
5070 ret = xmlValidateQName(value, 1);
5071 if (ret > 0) {
5072 xmlSchemaPSimpleTypeErr(ctxt,
5073 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5074 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005075 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5076 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005077 NULL, NULL, NULL);
5078 *local = value;
5079 return (ctxt->err);
5080 } else if (ret < 0)
5081 return (-1);
5082
5083 if (!strchr((char *) value, ':')) {
5084 ns = xmlSearchNs(attr->doc, attr->parent, 0);
5085 if (ns)
5086 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5087 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5088 /*
5089 * This one takes care of included schemas with no
5090 * target namespace.
5091 */
5092 *uri = schema->targetNamespace;
5093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005094 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005095 return (0);
5096 }
5097 /*
5098 * At this point xmlSplitQName3 has to return a local name.
5099 */
5100 *local = xmlSplitQName3(value, &len);
5101 *local = xmlDictLookup(ctxt->dict, *local, -1);
5102 pref = xmlDictLookup(ctxt->dict, value, len);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005103 if (prefix != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005104 *prefix = pref;
5105 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5106 if (ns == NULL) {
5107 xmlSchemaPSimpleTypeErr(ctxt,
5108 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5109 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005110 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
5111 "The QName value '%s' has no corresponding namespace "
5112 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005113 return (ctxt->err);
5114 } else {
5115 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5116 }
5117 return (0);
5118}
5119
5120/**
5121 * xmlSchemaPValAttrNodeQName:
5122 * @ctxt: a schema parser context
5123 * @schema: the schema context
5124 * @ownerDes: the designation of the owner element
5125 * @ownerItem: the owner as a schema object
5126 * @attr: the attribute node
5127 * @local: the resulting local part if found, the attribute value otherwise
5128 * @uri: the resulting namespace URI if found
5129 *
5130 * Extracts and validates the QName of an attribute value.
5131 * This one is intended to be used on attribute values that
5132 * should resolve to schema components.
5133 *
5134 * Returns 0, in case the QName is valid, a positive error code
5135 * if not valid and -1 if an internal error occurs.
5136 */
5137static int
5138xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5139 xmlSchemaPtr schema,
5140 xmlChar **ownerDes,
5141 xmlSchemaTypePtr ownerItem,
5142 xmlAttrPtr attr,
5143 const xmlChar **uri,
5144 const xmlChar **prefix,
5145 const xmlChar **local)
5146{
5147 const xmlChar *value;
5148
5149 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5150 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5151 ownerDes, ownerItem, attr, value, uri, prefix, local));
5152}
5153
5154/**
5155 * xmlSchemaPValAttrQName:
5156 * @ctxt: a schema parser context
5157 * @schema: the schema context
5158 * @ownerDes: the designation of the parent element
5159 * @ownerItem: the owner as a schema object
5160 * @ownerElem: the parent node of the attribute
5161 * @name: the name of the attribute
5162 * @local: the resulting local part if found, the attribute value otherwise
5163 * @uri: the resulting namespace URI if found
5164 *
5165 * Extracts and validates the QName of an attribute value.
5166 *
5167 * Returns 0, in case the QName is valid, a positive error code
5168 * if not valid and -1 if an internal error occurs.
5169 */
5170static int
5171xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5172 xmlSchemaPtr schema,
5173 xmlChar **ownerDes,
5174 xmlSchemaTypePtr ownerItem,
5175 xmlNodePtr ownerElem,
5176 const char *name,
5177 const xmlChar **uri,
5178 const xmlChar **prefix,
5179 const xmlChar **local)
5180{
5181 xmlAttrPtr attr;
5182
5183 attr = xmlSchemaGetPropNode(ownerElem, name);
5184 if (attr == NULL) {
5185 *local = NULL;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005186 if (prefix != NULL)
5187 *prefix = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005188 *uri = NULL;
5189 return (0);
5190 }
5191 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5192 ownerDes, ownerItem, attr, uri, prefix, local));
5193}
5194
5195/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005196 * xmlSchemaPValAttrID:
5197 * @ctxt: a schema parser context
5198 * @schema: the schema context
5199 * @ownerDes: the designation of the parent element
5200 * @ownerItem: the owner as a schema object
5201 * @ownerElem: the parent node of the attribute
5202 * @name: the name of the attribute
5203 *
5204 * Extracts and validates the ID of an attribute value.
5205 *
5206 * Returns 0, in case the ID is valid, a positive error code
5207 * if not valid and -1 if an internal error occurs.
5208 */
5209static int
5210xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5211 xmlChar **ownerDes,
5212 xmlSchemaTypePtr ownerItem,
5213 xmlNodePtr ownerElem,
5214 const xmlChar *name)
5215{
5216 int ret;
5217 xmlChar *value;
5218 xmlAttrPtr attr;
5219
5220 value = xmlGetNoNsProp(ownerElem, name);
5221 if (value == NULL)
5222 return (0);
5223
5224 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5225 if (attr == NULL)
5226 return (-1);
5227
5228 ret = xmlValidateNCName(BAD_CAST value, 1);
5229 if (ret == 0) {
5230 /*
5231 * NOTE: the IDness might have already be declared in the DTD
5232 */
5233 if (attr->atype != XML_ATTRIBUTE_ID) {
5234 xmlIDPtr res;
5235 xmlChar *strip;
5236
5237 /*
5238 * TODO: Use xmlSchemaStrip here; it's not exported at this
5239 * moment.
5240 */
5241 strip = xmlSchemaCollapseString(BAD_CAST value);
5242 if (strip != NULL)
5243 value = strip;
5244 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5245 if (res == NULL) {
5246 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5247 xmlSchemaPSimpleTypeErr(ctxt,
5248 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5249 ownerDes, ownerItem, (xmlNodePtr) attr,
5250 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005251 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005252 BAD_CAST value, NULL);
5253 } else
5254 attr->atype = XML_ATTRIBUTE_ID;
5255 if (strip != NULL)
5256 xmlFree(strip);
5257 }
5258 } else if (ret > 0) {
5259 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5260 xmlSchemaPSimpleTypeErr(ctxt,
5261 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5262 ownerDes, ownerItem, (xmlNodePtr) attr,
5263 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5264 NULL, BAD_CAST value, NULL, NULL, NULL);
5265 }
5266 xmlFree(value);
5267
5268 return (ret);
5269}
5270
5271/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005272 * xmlGetMaxOccurs:
5273 * @ctxt: a schema validation context
5274 * @node: a subtree containing XML Schema informations
5275 *
5276 * Get the maxOccurs property
5277 *
5278 * Returns the default if not found, or the value
5279 */
5280static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005281xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5282 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005283{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005284 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005285 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005286 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005287
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005288 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5289 if (attr == NULL)
5290 return (def);
5291 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005292
5293 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005294 if (max != UNBOUNDED) {
5295 xmlSchemaPSimpleTypeErr(ctxt,
5296 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5297 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5298 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5299 val, NULL, NULL, NULL);
5300 return (def);
5301 } else
5302 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005303 }
5304
5305 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005306 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005307 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005308 if (*cur == 0) {
5309 xmlSchemaPSimpleTypeErr(ctxt,
5310 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5311 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5312 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5313 val, NULL, NULL, NULL);
5314 return (def);
5315 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005316 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005317 ret = ret * 10 + (*cur - '0');
5318 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 }
William M. Brack76e95df2003-10-18 16:20:14 +00005320 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005321 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005322 /*
5323 * TODO: Restrict the maximal value to Integer.
5324 */
5325 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5326 xmlSchemaPSimpleTypeErr(ctxt,
5327 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5328 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5329 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5330 val, NULL, NULL, NULL);
5331 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005332 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005334}
5335
5336/**
5337 * xmlGetMinOccurs:
5338 * @ctxt: a schema validation context
5339 * @node: a subtree containing XML Schema informations
5340 *
5341 * Get the minOccurs property
5342 *
5343 * Returns the default if not found, or the value
5344 */
5345static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005346xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5347 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005349 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005350 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005351 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005352
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005353 attr = xmlSchemaGetPropNode(node, "minOccurs");
5354 if (attr == NULL)
5355 return (def);
5356 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005357 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005358 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005359 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005360 if (*cur == 0) {
5361 xmlSchemaPSimpleTypeErr(ctxt,
5362 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5363 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5364 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5365 val, NULL, NULL, NULL);
5366 return (def);
5367 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005368 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005369 ret = ret * 10 + (*cur - '0');
5370 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 }
William M. Brack76e95df2003-10-18 16:20:14 +00005372 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005373 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005374 /*
5375 * TODO: Restrict the maximal value to Integer.
5376 */
5377 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5378 xmlSchemaPSimpleTypeErr(ctxt,
5379 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5380 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5381 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5382 val, NULL, NULL, NULL);
5383 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005384 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005385 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005386}
5387
5388/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005389 * xmlSchemaPGetBoolNodeValue:
5390 * @ctxt: a schema validation context
5391 * @ownerDes: owner designation
5392 * @ownerItem: the owner as a schema item
5393 * @node: the node holding the value
5394 *
5395 * Converts a boolean string value into 1 or 0.
5396 *
5397 * Returns 0 or 1.
5398 */
5399static int
5400xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5401 xmlChar **ownerDes,
5402 xmlSchemaTypePtr ownerItem,
5403 xmlNodePtr node)
5404{
5405 xmlChar *value = NULL;
5406 int res = 0;
5407
5408 value = xmlNodeGetContent(node);
5409 /*
5410 * 3.2.2.1 Lexical representation
5411 * An instance of a datatype that is defined as ·boolean·
5412 * can have the following legal literals {true, false, 1, 0}.
5413 */
5414 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5415 res = 1;
5416 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5417 res = 0;
5418 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5419 res = 1;
5420 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
5421 res = 0;
5422 else {
5423 xmlSchemaPSimpleTypeErr(ctxt,
5424 XML_SCHEMAP_INVALID_BOOLEAN,
5425 ownerDes, ownerItem, node,
5426 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5427 "(1 | 0 | true | false)", BAD_CAST value,
5428 NULL, NULL, NULL);
5429 }
5430 if (value != NULL)
5431 xmlFree(value);
5432 return (res);
5433}
5434
5435/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 * xmlGetBooleanProp:
5437 * @ctxt: a schema validation context
5438 * @node: a subtree containing XML Schema informations
5439 * @name: the attribute name
5440 * @def: the default value
5441 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005442 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005443 *
5444 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005445 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005446 */
5447static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005448xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5449 xmlChar **ownerDes,
5450 xmlSchemaTypePtr ownerItem,
5451 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005452 const char *name, int def)
5453{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005454 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005455
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005456 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005457 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005458 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005459 /*
5460 * 3.2.2.1 Lexical representation
5461 * An instance of a datatype that is defined as ·boolean·
5462 * can have the following legal literals {true, false, 1, 0}.
5463 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005464 if (xmlStrEqual(val, BAD_CAST "true"))
5465 def = 1;
5466 else if (xmlStrEqual(val, BAD_CAST "false"))
5467 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005468 else if (xmlStrEqual(val, BAD_CAST "1"))
5469 def = 1;
5470 else if (xmlStrEqual(val, BAD_CAST "0"))
5471 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005472 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005473 xmlSchemaPSimpleTypeErr(ctxt,
5474 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005475 ownerDes, ownerItem,
5476 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00005477 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5478 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005479 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005480 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005481}
5482
5483/************************************************************************
5484 * *
5485 * Shema extraction from an Infoset *
5486 * *
5487 ************************************************************************/
5488static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5489 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005490 xmlNodePtr node,
5491 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005492static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5493 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005494 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005495 xmlNodePtr node,
5496 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005497static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5498 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005499 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005500 xmlNodePtr node,
5501 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005502static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5503 ctxt,
5504 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005505 xmlNodePtr node,
5506 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005507static xmlSchemaAttributeGroupPtr
5508xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005509 xmlSchemaPtr schema, xmlNodePtr node,
5510 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005511static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5512 xmlSchemaPtr schema,
5513 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005514static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005515xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5516 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005517
5518/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005519 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005520 *
5521 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005522 * @ownerDes: the designation of the parent element
5523 * @ownerItem: the schema object owner if existent
5524 * @attr: the schema attribute node being validated
5525 * @value: the value
5526 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005527 *
5528 * Validates a value against the given built-in type.
5529 * This one is intended to be used internally for validation
5530 * of schema attribute values during parsing of the schema.
5531 *
5532 * Returns 0 if the value is valid, a positive error code
5533 * number otherwise and -1 in case of an internal or API error.
5534 */
5535static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
5537 xmlChar **ownerDes,
5538 xmlSchemaTypePtr ownerItem,
5539 xmlAttrPtr attr,
5540 const xmlChar *value,
5541 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005542{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005543
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 int ret = 0;
5545
5546 /*
5547 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5548 * one is really meant to be used internally, so better not.
5549 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005550 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005551 return (-1);
5552 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5553 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005554 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005555 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005556 "type '%s' is not a built-in type.\n",
5557 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005558 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005559 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005560 switch (type->builtInType) {
5561 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005562 case XML_SCHEMAS_QNAME:
5563 case XML_SCHEMAS_ANYURI:
5564 case XML_SCHEMAS_TOKEN:
5565 case XML_SCHEMAS_LANGUAGE:
5566 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
5567 break;
5568
5569 /*
5570 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005571 ret = xmlValidateNCName(value, 1);
5572 break;
5573 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00005574 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005575 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005576 "Internal error: xmlSchemaPvalueAttrNode, use "
5577 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
5578 "for extracting QName valueues instead.\n",
5579 NULL, NULL);
5580 return (-1);
5581 case XML_SCHEMAS_ANYURI:
5582 if (value != NULL) {
5583 xmlURIPtr uri = xmlParseURI((const char *) value);
5584 if (uri == NULL)
5585 ret = 1;
5586 else
5587 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005588 }
5589 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 case XML_SCHEMAS_TOKEN: {
5591 const xmlChar *cur = value;
5592
5593 if (IS_BLANK_CH(*cur)) {
5594 ret = 1;
5595 } else while (*cur != 0) {
5596 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
5597 ret = 1;
5598 break;
5599 } else if (*cur == ' ') {
5600 cur++;
5601 if ((*cur == 0) || (*cur == ' ')) {
5602 ret = 1;
5603 break;
5604 }
5605 } else {
5606 cur++;
5607 }
5608 }
5609 }
5610 break;
5611 case XML_SCHEMAS_LANGUAGE:
5612 if (xmlCheckLanguageID(value) != 1)
5613 ret = 1;
5614 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005615 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005616 default: {
5617 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005618 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005619 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005620 "valueidation using the type '%s' is not implemented "
5621 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00005622 type->name, NULL);
5623 return (-1);
5624 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005625 }
5626 /*
5627 * TODO: Should we use the S4S error codes instead?
5628 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005629 if (ret < 0) {
5630 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
5631 XML_SCHEMAP_INTERNAL,
5632 "Internal error: xmlSchemaPValAttrNodeValue, "
5633 "failed to validate a schema attribute value.\n",
5634 NULL, NULL);
5635 return (-1);
5636 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005637 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
5638 xmlSchemaPSimpleTypeErr(ctxt,
5639 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
5640 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005641 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005642 NULL, NULL, NULL);
5643 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
5644 } else {
5645 xmlSchemaPSimpleTypeErr(ctxt,
5646 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
5647 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005648 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005649 NULL, NULL, NULL);
5650 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
5651 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005652 }
5653 return (ret);
5654}
5655
5656/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005657 * xmlSchemaPValAttrNode:
5658 *
5659 * @ctxt: a schema parser context
5660 * @ownerDes: the designation of the parent element
5661 * @ownerItem: the schema object owner if existent
5662 * @attr: the schema attribute node being validated
5663 * @type: the built-in type to be validated against
5664 * @value: the resulting value if any
5665 *
5666 * Extracts and validates a value against the given built-in type.
5667 * This one is intended to be used internally for validation
5668 * of schema attribute values during parsing of the schema.
5669 *
5670 * Returns 0 if the value is valid, a positive error code
5671 * number otherwise and -1 in case of an internal or API error.
5672 */
5673static int
5674xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5675 xmlChar **ownerDes,
5676 xmlSchemaTypePtr ownerItem,
5677 xmlAttrPtr attr,
5678 xmlSchemaTypePtr type,
5679 const xmlChar **value)
5680{
5681 const xmlChar *val;
5682
5683 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
5684 return (-1);
5685
5686 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5687 if (value != NULL)
5688 *value = val;
5689
5690 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
5691 val, type));
5692}
5693
5694/**
5695 * xmlSchemaPValAttr:
5696 *
5697 * @ctxt: a schema parser context
5698 * @node: the element node of the attribute
5699 * @ownerDes: the designation of the parent element
5700 * @ownerItem: the schema object owner if existent
5701 * @ownerElem: the owner element node
5702 * @name: the name of the schema attribute node
5703 * @type: the built-in type to be validated against
5704 * @value: the resulting value if any
5705 *
5706 * Extracts and validates a value against the given built-in type.
5707 * This one is intended to be used internally for validation
5708 * of schema attribute values during parsing of the schema.
5709 *
5710 * Returns 0 if the value is valid, a positive error code
5711 * number otherwise and -1 in case of an internal or API error.
5712 */
5713static int
5714xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
5715 xmlChar **ownerDes,
5716 xmlSchemaTypePtr ownerItem,
5717 xmlNodePtr ownerElem,
5718 const char *name,
5719 xmlSchemaTypePtr type,
5720 const xmlChar **value)
5721{
5722 xmlAttrPtr attr;
5723
5724 if ((ctxt == NULL) || (type == NULL)) {
5725 if (value != NULL)
5726 *value = NULL;
5727 return (-1);
5728 }
5729 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5730 if (value != NULL)
5731 *value = NULL;
5732 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005733 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 "Internal error: xmlSchemaPValAttr, the given "
5735 "type '%s' is not a built-in type.\n",
5736 type->name, NULL);
5737 return (-1);
5738 }
5739 attr = xmlSchemaGetPropNode(ownerElem, name);
5740 if (attr == NULL) {
5741 if (value != NULL)
5742 *value = NULL;
5743 return (0);
5744 }
5745 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
5746 type, value));
5747}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005748
5749static int
5750xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5751 xmlSchemaPtr schema,
5752 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005753 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005754 const xmlChar *namespaceName)
5755{
5756 if (xmlStrEqual(schema->targetNamespace, namespaceName))
5757 return (1);
5758 if (pctxt->localImports != NULL) {
5759 int i;
5760 for (i = 0; i < pctxt->nbLocalImports; i++)
5761 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5762 return (1);
5763 }
5764 if (namespaceName == NULL)
5765 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005766 NULL, (xmlSchemaTypePtr) item, node,
5767 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005768 "namespace are not valid, since not indicated by an import "
5769 "statement", NULL);
5770 else
5771 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005772 NULL, (xmlSchemaTypePtr) item, node,
5773 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005774 "namespace '%s' are not valid, since not indicated by an import "
5775 "statement", namespaceName);
5776 return (0);
5777}
5778
Daniel Veillardc0826a72004-08-10 14:17:33 +00005779/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005780 * xmlSchemaParseAttrDecls:
5781 * @ctxt: a schema validation context
5782 * @schema: the schema being built
5783 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005784 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005785 *
5786 * parse a XML schema attrDecls declaration corresponding to
5787 * <!ENTITY % attrDecls
5788 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5789 */
5790static xmlNodePtr
5791xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5792 xmlNodePtr child, xmlSchemaTypePtr type)
5793{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005794 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005795
Daniel Veillard4255d502002-04-16 15:50:10 +00005796 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005797 (IS_SCHEMA(child, "attributeGroup"))) {
5798 attr = NULL;
5799 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005800 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005801 } else if (IS_SCHEMA(child, "attributeGroup")) {
5802 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005803 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 }
5805 if (attr != NULL) {
5806 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005807 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5808 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5809 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005810 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 lastattr = attr;
5812 } else {
5813 lastattr->next = attr;
5814 lastattr = attr;
5815 }
5816 }
5817 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005818 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005819 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005820}
5821
5822/**
5823 * xmlSchemaParseAnnotation:
5824 * @ctxt: a schema validation context
5825 * @schema: the schema being built
5826 * @node: a subtree containing XML Schema informations
5827 *
5828 * parse a XML schema Attrribute declaration
5829 * *WARNING* this interface is highly subject to change
5830 *
William M. Bracke7091952004-05-11 15:09:58 +00005831 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005832 * 1 in case of success.
5833 */
5834static xmlSchemaAnnotPtr
5835xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5836 xmlNodePtr node)
5837{
5838 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005839 xmlNodePtr child = NULL;
5840 xmlAttrPtr attr;
5841 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005842
Daniel Veillardc0826a72004-08-10 14:17:33 +00005843 /*
5844 * INFO: S4S completed.
5845 */
5846 /*
5847 * id = ID
5848 * {any attributes with non-schema namespace . . .}>
5849 * Content: (appinfo | documentation)*
5850 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005851 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5852 return (NULL);
5853 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005854 attr = node->properties;
5855 while (attr != NULL) {
5856 if (((attr->ns == NULL) &&
5857 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5858 ((attr->ns != NULL) &&
5859 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5860
5861 xmlSchemaPIllegalAttrErr(ctxt,
5862 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5863 NULL, NULL, attr);
5864 }
5865 attr = attr->next;
5866 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005867 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005868 /*
5869 * And now for the children...
5870 */
5871 child = node->children;
5872 while (child != NULL) {
5873 if (IS_SCHEMA(child, "appinfo")) {
5874 /* TODO: make available the content of "appinfo". */
5875 /*
5876 * source = anyURI
5877 * {any attributes with non-schema namespace . . .}>
5878 * Content: ({any})*
5879 */
5880 attr = child->properties;
5881 while (attr != NULL) {
5882 if (((attr->ns == NULL) &&
5883 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5884 ((attr->ns != NULL) &&
5885 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005886
Daniel Veillardc0826a72004-08-10 14:17:33 +00005887 xmlSchemaPIllegalAttrErr(ctxt,
5888 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5889 NULL, NULL, attr);
5890 }
5891 attr = attr->next;
5892 }
5893 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5894 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5895 child = child->next;
5896 } else if (IS_SCHEMA(child, "documentation")) {
5897 /* TODO: make available the content of "documentation". */
5898 /*
5899 * source = anyURI
5900 * {any attributes with non-schema namespace . . .}>
5901 * Content: ({any})*
5902 */
5903 attr = child->properties;
5904 while (attr != NULL) {
5905 if (attr->ns == NULL) {
5906 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5907 xmlSchemaPIllegalAttrErr(ctxt,
5908 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5909 NULL, NULL, attr);
5910 }
5911 } else {
5912 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5913 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5914 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5915
5916 xmlSchemaPIllegalAttrErr(ctxt,
5917 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5918 NULL, NULL, attr);
5919 }
5920 }
5921 attr = attr->next;
5922 }
5923 /*
5924 * Attribute "xml:lang".
5925 */
5926 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5927 if (attr != NULL)
5928 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5929 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5930 child = child->next;
5931 } else {
5932 if (!barked)
5933 xmlSchemaPContentErr(ctxt,
5934 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5935 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5936 barked = 1;
5937 child = child->next;
5938 }
5939 }
5940
Daniel Veillard4255d502002-04-16 15:50:10 +00005941 return (ret);
5942}
5943
5944/**
5945 * xmlSchemaParseFacet:
5946 * @ctxt: a schema validation context
5947 * @schema: the schema being built
5948 * @node: a subtree containing XML Schema informations
5949 *
5950 * parse a XML schema Facet declaration
5951 * *WARNING* this interface is highly subject to change
5952 *
5953 * Returns the new type structure or NULL in case of error
5954 */
5955static xmlSchemaFacetPtr
5956xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005957 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005958{
5959 xmlSchemaFacetPtr facet;
5960 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005961 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005962
5963 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5964 return (NULL);
5965
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005966 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005967 if (facet == NULL) {
5968 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5969 return (NULL);
5970 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005971 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005972 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005973 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005974 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5975 "Facet %s has no value\n", node->name, NULL);
5976 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005977 return (NULL);
5978 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005981 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005982 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005983 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005985 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005986 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005987 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005989 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005990 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005991 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005992 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005993 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005994 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005995 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005996 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005997 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005999 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006000 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6001 } else if (IS_SCHEMA(node, "minLength")) {
6002 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6003 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006004 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6005 "Unknown facet type %s\n", node->name, NULL);
6006 xmlSchemaFreeFacet(facet);
6007 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006008 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006009 xmlSchemaPValAttrID(ctxt, NULL,
6010 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006011 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006012 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6013 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6014 const xmlChar *fixed;
6015
6016 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6017 if (fixed != NULL) {
6018 if (xmlStrEqual(fixed, BAD_CAST "true"))
6019 facet->fixed = 1;
6020 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006021 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006022 child = node->children;
6023
6024 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006025 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6026 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006027 }
6028 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006029 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6030 "Facet %s has unexpected child content\n",
6031 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 }
6033 return (facet);
6034}
6035
6036/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006037 * xmlSchemaParseWildcardNs:
6038 * @ctxt: a schema parser context
6039 * @wildc: the wildcard, already created
6040 * @node: a subtree containing XML Schema informations
6041 *
6042 * Parses the attribute "processContents" and "namespace"
6043 * of a xsd:anyAttribute and xsd:any.
6044 * *WARNING* this interface is highly subject to change
6045 *
6046 * Returns 0 if everything goes fine, a positive error code
6047 * if something is not valid and -1 if an internal error occurs.
6048 */
6049static int
6050xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6051 xmlSchemaPtr schema,
6052 xmlSchemaWildcardPtr wildc,
6053 xmlNodePtr node)
6054{
6055 const xmlChar *pc, *ns, *dictnsItem;
6056 int ret = 0;
6057 xmlChar *nsItem;
6058 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6059 xmlAttrPtr attr;
6060
6061 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6062 if ((pc == NULL)
6063 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6064 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6065 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6066 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6067 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6068 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6069 } else {
6070 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006071 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006072 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00006073 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006074 NULL, NULL, NULL);
6075 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006076 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006077 }
6078 /*
6079 * Build the namespace constraints.
6080 */
6081 attr = xmlSchemaGetPropNode(node, "namespace");
6082 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006083 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006084 wildc->any = 1;
6085 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6086 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6087 if (wildc->negNsSet == NULL) {
6088 return (-1);
6089 }
6090 wildc->negNsSet->value = schema->targetNamespace;
6091 } else {
6092 const xmlChar *end, *cur;
6093
6094 cur = ns;
6095 do {
6096 while (IS_BLANK_CH(*cur))
6097 cur++;
6098 end = cur;
6099 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6100 end++;
6101 if (end == cur)
6102 break;
6103 nsItem = xmlStrndup(cur, end - cur);
6104 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6105 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6106 xmlSchemaPSimpleTypeErr(ctxt,
6107 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6108 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006109 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006110 "((##any | ##other) | List of (anyURI | "
6111 "(##targetNamespace | ##local)))",
6112 nsItem, NULL, NULL, NULL);
6113 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6114 } else {
6115 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6116 dictnsItem = schema->targetNamespace;
6117 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6118 dictnsItem = NULL;
6119 } else {
6120 /*
6121 * Validate the item (anyURI).
6122 */
6123 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
6124 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6125 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6126 }
6127 /*
6128 * Avoid dublicate namespaces.
6129 */
6130 tmp = wildc->nsSet;
6131 while (tmp != NULL) {
6132 if (dictnsItem == tmp->value)
6133 break;
6134 tmp = tmp->next;
6135 }
6136 if (tmp == NULL) {
6137 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6138 if (tmp == NULL) {
6139 xmlFree(nsItem);
6140 return (-1);
6141 }
6142 tmp->value = dictnsItem;
6143 tmp->next = NULL;
6144 if (wildc->nsSet == NULL)
6145 wildc->nsSet = tmp;
6146 else
6147 lastNs->next = tmp;
6148 lastNs = tmp;
6149 }
6150
6151 }
6152 xmlFree(nsItem);
6153 cur = end;
6154 } while (*cur != 0);
6155 }
6156 return (ret);
6157}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006158
6159static int
6160xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006161 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006162 xmlNodePtr node,
6163 int minOccurs,
6164 int maxOccurs) {
6165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006166 if ((maxOccurs == 0) && ( minOccurs == 0))
6167 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006168 if (maxOccurs != UNBOUNDED) {
6169 /*
6170 * TODO: Maby we should better not create the particle,
6171 * if min/max is invalid, since it could confuse the build of the
6172 * content model.
6173 */
6174 /*
6175 * 3.9.6 Schema Component Constraint: Particle Correct
6176 *
6177 */
6178 if (maxOccurs < 1) {
6179 /*
6180 * 2.2 {max occurs} must be greater than or equal to 1.
6181 */
6182 xmlSchemaPCustomAttrErr(ctxt,
6183 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006184 NULL, NULL,
6185 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006186 "The value must be greater than or equal to 1");
6187 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6188 } else if (minOccurs > maxOccurs) {
6189 /*
6190 * 2.1 {min occurs} must not be greater than {max occurs}.
6191 */
6192 xmlSchemaPCustomAttrErr(ctxt,
6193 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006194 NULL, NULL,
6195 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006196 "The value must not be greater than the value of 'maxOccurs'");
6197 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6198 }
6199 }
6200 return (0);
6201}
6202
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006204 * xmlSchemaParseAny:
6205 * @ctxt: a schema validation context
6206 * @schema: the schema being built
6207 * @node: a subtree containing XML Schema informations
6208 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006209 * Parsea a XML schema <any> element. A particle and wildcard
6210 * will be created (except if minOccurs==maxOccurs==0, in this case
6211 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006212 * *WARNING* this interface is highly subject to change
6213 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006214 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006215 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006216static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006217xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6218 xmlNodePtr node)
6219{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006220 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006221 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006222 xmlSchemaWildcardPtr wild;
6223 int min, max;
6224 xmlAttrPtr attr;
6225 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006226
6227 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6228 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006229 /*
6230 * Check for illegal attributes.
6231 */
6232 attr = node->properties;
6233 while (attr != NULL) {
6234 if (attr->ns == NULL) {
6235 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6236 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6237 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6238 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6239 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6240 xmlSchemaPIllegalAttrErr(ctxt,
6241 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6242 NULL, NULL, attr);
6243 }
6244 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6245 xmlSchemaPIllegalAttrErr(ctxt,
6246 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6247 NULL, NULL, attr);
6248 }
6249 attr = attr->next;
6250 }
6251 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6252 /*
6253 * minOccurs/maxOccurs.
6254 */
6255 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006256 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006257 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6258 "nonNegativeInteger");
6259 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6260 /*
6261 * Create & parse the wildcard.
6262 */
6263 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6264 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006265 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006266 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006267 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006268 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006269 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006270 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006271 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006272 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006273 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006274 }
6275 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006276 xmlSchemaPContentErr(ctxt,
6277 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6278 NULL, NULL, node, child,
6279 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006281 /*
6282 * No component if minOccurs==maxOccurs==0.
6283 */
6284 if ((min == 0) && (max == 0)) {
6285 /* Don't free the wildcard, since it's already on the list. */
6286 return (NULL);
6287 }
6288 /*
6289 * Create the particle.
6290 */
6291 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6292 if (particle == NULL)
6293 return (NULL);
6294 particle->annot = annot;
6295 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006296
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006297 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006298}
6299
6300/**
6301 * xmlSchemaParseNotation:
6302 * @ctxt: a schema validation context
6303 * @schema: the schema being built
6304 * @node: a subtree containing XML Schema informations
6305 *
6306 * parse a XML schema Notation declaration
6307 *
6308 * Returns the new structure or NULL in case of error
6309 */
6310static xmlSchemaNotationPtr
6311xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006312 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006313{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006314 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006315 xmlSchemaNotationPtr ret;
6316 xmlNodePtr child = NULL;
6317
6318 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6319 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006320 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006321 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006322 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6323 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006324 return (NULL);
6325 }
6326 ret = xmlSchemaAddNotation(ctxt, schema, name);
6327 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006328 return (NULL);
6329 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006330 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006331
6332 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6333 node, BAD_CAST "id");
6334
6335 if (IS_SCHEMA(child, "annotation")) {
6336 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6337 child = child->next;
6338 }
6339
Daniel Veillard4255d502002-04-16 15:50:10 +00006340 child = node->children;
6341 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006342 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6343 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006344 }
6345 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006346 xmlSchemaPContentErr(ctxt,
6347 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6348 NULL, NULL, node, child,
6349 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006350 }
6351
6352 return (ret);
6353}
6354
6355/**
6356 * xmlSchemaParseAnyAttribute:
6357 * @ctxt: a schema validation context
6358 * @schema: the schema being built
6359 * @node: a subtree containing XML Schema informations
6360 *
6361 * parse a XML schema AnyAttrribute declaration
6362 * *WARNING* this interface is highly subject to change
6363 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006364 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006365 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006366static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006367xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6368 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006369{
Daniel Veillard3646d642004-06-02 19:19:14 +00006370 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006371 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006372 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006373
6374 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6375 return (NULL);
6376
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006377 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6378 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006379 if (ret == NULL) {
6380 return (NULL);
6381 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006382 /*
6383 * Check for illegal attributes.
6384 */
6385 attr = node->properties;
6386 while (attr != NULL) {
6387 if (attr->ns == NULL) {
6388 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6389 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6390 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6391 xmlSchemaPIllegalAttrErr(ctxt,
6392 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6393 NULL, NULL, attr);
6394 }
6395 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6396 xmlSchemaPIllegalAttrErr(ctxt,
6397 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6398 NULL, NULL, attr);
6399 }
6400 attr = attr->next;
6401 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006402 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6403 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006404 /*
6405 * Parse the namespace list.
6406 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006407 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006408 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006409 /*
6410 * And now for the children...
6411 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006412 child = node->children;
6413 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006414 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6415 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006416 }
6417 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006418 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006419 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6420 NULL, NULL, node, child,
6421 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006422 }
6423
6424 return (ret);
6425}
6426
6427
6428/**
6429 * xmlSchemaParseAttribute:
6430 * @ctxt: a schema validation context
6431 * @schema: the schema being built
6432 * @node: a subtree containing XML Schema informations
6433 *
6434 * parse a XML schema Attrribute declaration
6435 * *WARNING* this interface is highly subject to change
6436 *
William M. Bracke7091952004-05-11 15:09:58 +00006437 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006438 */
6439static xmlSchemaAttributePtr
6440xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006441 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006442{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006443 const xmlChar *name, *attrValue;
6444 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006445 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 xmlNodePtr child = NULL;
6447 xmlAttrPtr attr, nameAttr;
6448 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006449
6450 /*
6451 * Note that the w3c spec assumes the schema to be validated with schema
6452 * for schemas beforehand.
6453 *
6454 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006455 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006456
6457 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6458 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006459 attr = xmlSchemaGetPropNode(node, "ref");
6460 nameAttr = xmlSchemaGetPropNode(node, "name");
6461
6462 if ((attr == NULL) && (nameAttr == NULL)) {
6463 /*
6464 * 3.2.3 : 3.1
6465 * One of ref or name must be present, but not both
6466 */
6467 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6468 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
6469 "One of the attributes 'ref' or 'name' must be present");
6470 return (NULL);
6471 }
6472 if ((topLevel) || (attr == NULL)) {
6473 if (nameAttr == NULL) {
6474 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6475 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
6476 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006477 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 }
6479 } else
6480 isRef = 1;
6481
6482 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006483 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006484 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
6485
6486 /*
6487 * Parse as attribute reference.
6488 */
6489 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6490 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6491 &refPrefix, &ref) != 0) {
6492 return (NULL);
6493 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006494 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006496 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006497 if (ret == NULL) {
6498 if (repName != NULL)
6499 xmlFree(repName);
6500 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006501 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006502 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6503 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006504 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006506 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006507 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6508 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006509 /*
6510 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6511 */
6512 if (nameAttr != NULL)
6513 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6514 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6515 "ref", "name");
6516 /*
6517 * Check for illegal attributes.
6518 */
6519 attr = node->properties;
6520 while (attr != NULL) {
6521 if (attr->ns == NULL) {
6522 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6523 xmlStrEqual(attr->name, BAD_CAST "form")) {
6524 /*
6525 * 3.2.3 : 3.2
6526 * If ref is present, then all of <simpleType>,
6527 * form and type must be absent.
6528 */
6529 xmlSchemaPIllegalAttrErr(ctxt,
6530 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
6531 (xmlSchemaTypePtr) ret, attr);
6532 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6533 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6534 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6535 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6536 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6537 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
6538 xmlSchemaPIllegalAttrErr(ctxt,
6539 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6540 &repName, (xmlSchemaTypePtr) ret, attr);
6541 }
6542 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6543 xmlSchemaPIllegalAttrErr(ctxt,
6544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6545 &repName, (xmlSchemaTypePtr) ret, attr);
6546 }
6547 attr = attr->next;
6548 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006549 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006550 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006551
6552 /*
6553 * Parse as attribute declaration.
6554 */
6555 if (xmlSchemaPValAttrNode(ctxt,
6556 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
6557 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6558 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006559 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 /*
6561 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6562 */
6563 /*
6564 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6565 */
6566 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
6567 xmlSchemaPSimpleTypeErr(ctxt,
6568 XML_SCHEMAP_NO_XMLNS,
6569 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006570 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006571 "The value must not match 'xmlns'",
6572 NULL, NULL);
6573 if (repName != NULL)
6574 xmlFree(repName);
6575 return (NULL);
6576 }
6577 /*
6578 * Evaluate the target namespace
6579 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006580 if (topLevel) {
6581 ns = schema->targetNamespace;
6582 } else {
6583 attr = xmlSchemaGetPropNode(node, "form");
6584 if (attr != NULL) {
6585 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6586 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6587 ns = schema->targetNamespace;
6588 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6589 xmlSchemaPSimpleTypeErr(ctxt,
6590 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6591 &repName, NULL, (xmlNodePtr) attr,
6592 NULL, "(qualified | unqualified)",
6593 attrValue, NULL, NULL, NULL);
6594 }
6595 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6596 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006597 }
6598 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006599 if (ret == NULL) {
6600 if (repName != NULL)
6601 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006602 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006603 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006604 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006605 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 if (topLevel)
6607 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
6608 /*
6609 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6610 */
6611 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
6612 xmlSchemaPCustomErr(ctxt,
6613 XML_SCHEMAP_NO_XSI,
6614 &repName, (xmlSchemaTypePtr) ret, node,
6615 "The target namespace must not match '%s'",
6616 xmlSchemaInstanceNs);
6617 }
6618 /*
6619 * Check for illegal attributes.
6620 */
6621 attr = node->properties;
6622 while (attr != NULL) {
6623 if (attr->ns == NULL) {
6624 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6625 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6626 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6627 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6628 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
6629 if ((topLevel) ||
6630 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6631 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
6632 xmlSchemaPIllegalAttrErr(ctxt,
6633 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6634 &repName, (xmlSchemaTypePtr) ret, attr);
6635 }
6636 }
6637 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6638 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6639 &repName, (xmlSchemaTypePtr) ret, attr);
6640 }
6641 attr = attr->next;
6642 }
6643 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
6644 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006645 }
6646 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6647 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006648 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006649 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006650 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006651 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6652 if (ret->defValue != NULL)
6653 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
6654 /*
6655 * Attribute "default".
6656 */
6657 attr = xmlSchemaGetPropNode(node, "default");
6658 if (attr != NULL) {
6659 /*
6660 * 3.2.3 : 1
6661 * default and fixed must not both be present.
6662 */
6663 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6664 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6665 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6666 } else
6667 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6668 }
6669 if (topLevel == 0) {
6670 /*
6671 * Attribute "use".
6672 */
6673 attr = xmlSchemaGetPropNode(node, "use");
6674 if (attr != NULL) {
6675 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6676 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6677 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6678 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6679 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6680 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6681 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6682 else
6683 xmlSchemaPSimpleTypeErr(ctxt,
6684 XML_SCHEMAP_INVALID_ATTR_USE,
6685 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006686 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006687 attrValue, NULL, NULL, NULL);
6688 } else
6689 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6690 /*
6691 * 3.2.3 : 2
6692 * If default and use are both present, use must have
6693 * the actual value optional.
6694 */
6695 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6696 (ret->defValue != NULL) &&
6697 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
6698 xmlSchemaPSimpleTypeErr(ctxt,
6699 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6700 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006701 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006702 "The value must be 'optional' if the attribute "
6703 "'default' is present as well", NULL, NULL);
6704 }
6705 }
6706 /*
6707 * And now for the children...
6708 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006709 child = node->children;
6710 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006711 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6712 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006713 }
6714 if (isRef) {
6715 if (child != NULL) {
6716 if (IS_SCHEMA(child, "simpleType"))
6717 /*
6718 * 3.2.3 : 3.2
6719 * If ref is present, then all of <simpleType>,
6720 * form and type must be absent.
6721 */
6722 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6723 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6724 "(annotation?)");
6725 else
6726 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6727 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6728 "(annotation?)");
6729 }
6730 } else {
6731 if (IS_SCHEMA(child, "simpleType")) {
6732 if (ret->typeName != NULL) {
6733 /*
6734 * 3.2.3 : 4
6735 * type and <simpleType> must not both be present.
6736 */
6737 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6738 &repName, (xmlSchemaTypePtr) ret, node, child,
6739 "The attribute 'type' and the <simpleType> child "
6740 "are mutually exclusive", NULL);
6741 } else
6742 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6743 child = child->next;
6744 }
6745 if (child != NULL)
6746 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6747 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6748 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006749 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006750 /*
6751 * Cleanup.
6752 */
6753 if (repName != NULL)
6754 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006755 return (ret);
6756}
6757
6758/**
6759 * xmlSchemaParseAttributeGroup:
6760 * @ctxt: a schema validation context
6761 * @schema: the schema being built
6762 * @node: a subtree containing XML Schema informations
6763 *
6764 * parse a XML schema Attribute Group declaration
6765 * *WARNING* this interface is highly subject to change
6766 *
6767 * Returns the attribute group or NULL in case of error.
6768 */
6769static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006770xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006771 xmlSchemaPtr schema, xmlNodePtr node,
6772 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006773{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006774 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006775 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006776 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006777 const xmlChar *oldcontainer;
6778 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006779
6780 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6781 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006782
6783 nameAttr = xmlSchemaGetPropNode(node, "name");
6784 attr = xmlSchemaGetPropNode(node, "ref");
6785 if ((topLevel) || (attr == NULL)) {
6786 /*
6787 * Parse as an attribute group definition.
6788 * Note that those are allowed at top level only.
6789 */
6790 if (nameAttr == NULL) {
6791 xmlSchemaPMissingAttrErr(ctxt,
6792 XML_SCHEMAP_S4S_ATTR_MISSING,
6793 NULL, NULL, node, "name", NULL);
6794 return (NULL);
6795 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006796 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
6797 * (xmlNodePtr) nameAttr);
6798 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006799 /*
6800 * The name is crucial, exit if invalid.
6801 */
6802 if (xmlSchemaPValAttrNode(ctxt,
6803 NULL, NULL, nameAttr,
6804 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6805 return (NULL);
6806 }
6807 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6808 if (ret == NULL)
6809 return (NULL);
6810 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6811 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6812 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006813 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006814 } else {
6815 char buf[50];
6816 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6817
6818 /*
6819 * Parse as an attribute group definition reference.
6820 */
6821 if (attr == NULL) {
6822 xmlSchemaPMissingAttrErr(ctxt,
6823 XML_SCHEMAP_S4S_ATTR_MISSING,
6824 NULL, NULL, node, "ref", NULL);
6825 }
6826 xmlSchemaPValAttrNodeQName(ctxt, schema,
6827 NULL, NULL, attr, &refNs, &refPrefix, &ref);
6828
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006829 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006830 name = (const xmlChar *) buf;
6831 if (name == NULL) {
6832 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6833 "attribute group definition reference", node);
6834 return (NULL);
6835 }
6836 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6837 if (ret == NULL)
6838 return (NULL);
6839 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6840 ret->ref = ref;
6841 ret->refNs = refNs;
6842 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006843 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006844 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006845 xmlSchemaCheckReference(ctxt, schema, node,
6846 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006847 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006848 /*
6849 * Check for illegal attributes.
6850 */
6851 attr = node->properties;
6852 while (attr != NULL) {
6853 if (attr->ns == NULL) {
6854 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6855 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
6856 (!xmlStrEqual(attr->name, BAD_CAST "id")))
6857 {
6858 xmlSchemaPIllegalAttrErr(ctxt,
6859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6860 NULL, NULL, attr);
6861 }
6862 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6863 xmlSchemaPIllegalAttrErr(ctxt,
6864 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6865 NULL, NULL, attr);
6866 }
6867 attr = attr->next;
6868 }
6869 /* TODO: Validate "id" ? */
6870 /*
6871 * And now for the children...
6872 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006873 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006874 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006875 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006876 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006877 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6878 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006880 if (topLevel) {
6881 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6882 if (IS_SCHEMA(child, "anyAttribute")) {
6883 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6884 child = child->next;
6885 }
6886 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006888 xmlSchemaPContentErr(ctxt,
6889 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6890 NULL, NULL, node, child, NULL,
6891 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006892 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006893 ctxt->container = oldcontainer;
6894 return (ret);
6895}
6896
6897/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006898 * xmlSchemaPValAttrFormDefault:
6899 * @value: the value
6900 * @flags: the flags to be modified
6901 * @flagQualified: the specific flag for "qualified"
6902 *
6903 * Returns 0 if the value is valid, 1 otherwise.
6904 */
6905static int
6906xmlSchemaPValAttrFormDefault(const xmlChar *value,
6907 int *flags,
6908 int flagQualified)
6909{
6910 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6911 if ((*flags & flagQualified) == 0)
6912 *flags |= flagQualified;
6913 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6914 return (1);
6915
6916 return (0);
6917}
6918
6919/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006920 * xmlSchemaPValAttrBlockFinal:
6921 * @value: the value
6922 * @flags: the flags to be modified
6923 * @flagAll: the specific flag for "#all"
6924 * @flagExtension: the specific flag for "extension"
6925 * @flagRestriction: the specific flag for "restriction"
6926 * @flagSubstitution: the specific flag for "substitution"
6927 * @flagList: the specific flag for "list"
6928 * @flagUnion: the specific flag for "union"
6929 *
6930 * Validates the value of the attribute "final" and "block". The value
6931 * is converted into the specified flag values and returned in @flags.
6932 *
6933 * Returns 0 if the value is valid, 1 otherwise.
6934 */
6935
6936static int
6937xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6938 int *flags,
6939 int flagAll,
6940 int flagExtension,
6941 int flagRestriction,
6942 int flagSubstitution,
6943 int flagList,
6944 int flagUnion)
6945{
6946 int ret = 0;
6947
6948 /*
6949 * TODO: This does not check for dublicate entries.
6950 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006951 if ((flags == NULL) || (value == NULL))
6952 return (-1);
6953 if (value[0] == 0)
6954 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006955 if (xmlStrEqual(value, BAD_CAST "#all")) {
6956 if (flagAll != -1)
6957 *flags |= flagAll;
6958 else {
6959 if (flagExtension != -1)
6960 *flags |= flagExtension;
6961 if (flagRestriction != -1)
6962 *flags |= flagRestriction;
6963 if (flagSubstitution != -1)
6964 *flags |= flagSubstitution;
6965 if (flagList != -1)
6966 *flags |= flagList;
6967 if (flagUnion != -1)
6968 *flags |= flagUnion;
6969 }
6970 } else {
6971 const xmlChar *end, *cur = value;
6972 xmlChar *item;
6973
6974 do {
6975 while (IS_BLANK_CH(*cur))
6976 cur++;
6977 end = cur;
6978 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6979 end++;
6980 if (end == cur)
6981 break;
6982 item = xmlStrndup(cur, end - cur);
6983 if (xmlStrEqual(item, BAD_CAST "extension")) {
6984 if (flagExtension != -1) {
6985 if ((*flags & flagExtension) == 0)
6986 *flags |= flagExtension;
6987 } else
6988 ret = 1;
6989 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6990 if (flagRestriction != -1) {
6991 if ((*flags & flagRestriction) == 0)
6992 *flags |= flagRestriction;
6993 } else
6994 ret = 1;
6995 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6996 if (flagSubstitution != -1) {
6997 if ((*flags & flagSubstitution) == 0)
6998 *flags |= flagSubstitution;
6999 } else
7000 ret = 1;
7001 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7002 if (flagList != -1) {
7003 if ((*flags & flagList) == 0)
7004 *flags |= flagList;
7005 } else
7006 ret = 1;
7007 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7008 if (flagUnion != -1) {
7009 if ((*flags & flagUnion) == 0)
7010 *flags |= flagUnion;
7011 } else
7012 ret = 1;
7013 } else
7014 ret = 1;
7015 if (item != NULL)
7016 xmlFree(item);
7017 cur = end;
7018 } while ((ret == 0) && (*cur != 0));
7019 }
7020
7021 return (ret);
7022}
7023
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007024static int
7025xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007026 xmlSchemaIDCPtr idc,
7027 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007028 xmlAttrPtr attr,
7029 int isField)
7030{
7031 xmlNodePtr node;
7032
7033 /*
7034 * c-selector-xpath:
7035 * Schema Component Constraint: Selector Value OK
7036 *
7037 * TODO: 1 The {selector} must be a valid XPath expression, as defined
7038 * in [XPath].
7039 */
7040 if (selector == NULL) {
7041 xmlSchemaPErr(ctxt, idc->node,
7042 XML_SCHEMAP_INTERNAL,
7043 "Internal error: xmlSchemaCheckCSelectorXPath, "
7044 "the selector is not specified.\n", NULL, NULL);
7045 return (-1);
7046 }
7047 if (attr == NULL)
7048 node = idc->node;
7049 else
7050 node = (xmlNodePtr) attr;
7051 if (selector->xpath == NULL) {
7052 xmlSchemaPCustomErr(ctxt,
7053 /* TODO: Adjust error code. */
7054 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7055 NULL, NULL, node,
7056 "The XPath expression of the selector is not valid", NULL);
7057 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7058 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007059 const xmlChar **nsArray = NULL;
7060 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007061 /*
7062 * Compile the XPath expression.
7063 */
7064 /*
7065 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007066 * TODO: Call xmlPatterncompile with different options for selector/
7067 * field.
7068 */
7069 nsList = xmlGetNsList(attr->doc, attr->parent);
7070 /*
7071 * Build an array of prefixes and namespaces.
7072 */
7073 if (nsList != NULL) {
7074 int i, count = 0;
7075 xmlNsPtr ns;
7076
7077 for (i = 0; nsList[i] != NULL; i++)
7078 count++;
7079
7080 nsArray = (const xmlChar **) xmlMalloc(
7081 (count * 2 + 1) * sizeof(const xmlChar *));
7082 if (nsArray == NULL) {
7083 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7084 NULL);
7085 return (-1);
7086 }
7087 for (i = 0; i < count; i++) {
7088 ns = nsList[i];
7089 nsArray[2 * i] = nsList[i]->href;
7090 nsArray[2 * i + 1] = nsList[i]->prefix;
7091 }
7092 nsArray[count * 2] = NULL;
7093 xmlFree(nsList);
7094 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007095 /*
7096 * TODO: Differentiate between "selector" and "field".
7097 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007098 if (isField)
7099 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00007100 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007101 else
7102 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00007103 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007104 if (nsArray != NULL)
7105 xmlFree((xmlChar **) nsArray);
7106
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007107 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007108 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007109 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007110 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7111 NULL, NULL, node,
7112 "The XPath expression '%s' could not be "
7113 "compiled", selector->xpath);
7114 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007115 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007116 }
7117 return (0);
7118}
7119
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007120#define ADD_ANNOTATION(annot) \
7121 xmlSchemaAnnotPtr cur = item->annot; \
7122 if (item->annot == NULL) { \
7123 item->annot = annot; \
7124 return (annot); \
7125 } \
7126 cur = item->annot; \
7127 if (cur->next != NULL) { \
7128 cur = cur->next; \
7129 } \
7130 cur->next = annot;
7131
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007132/**
7133 * xmlSchemaAssignAnnotation:
7134 * @item: the schema component
7135 * @annot: the annotation
7136 *
7137 * Adds the annotation to the given schema component.
7138 *
7139 * Returns the given annotaion.
7140 */
7141static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007142xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7143 xmlSchemaAnnotPtr annot)
7144{
7145 if ((annItem == NULL) || (annot == NULL))
7146 return (NULL);
7147 switch (annItem->type) {
7148 case XML_SCHEMA_TYPE_ELEMENT: {
7149 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7150 ADD_ANNOTATION(annot)
7151 }
7152 break;
7153 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7154 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7155 ADD_ANNOTATION(annot)
7156 }
7157 break;
7158 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7159 case XML_SCHEMA_TYPE_ANY: {
7160 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7161 ADD_ANNOTATION(annot)
7162 }
7163 break;
7164 case XML_SCHEMA_TYPE_PARTICLE:
7165 case XML_SCHEMA_TYPE_IDC_KEY:
7166 case XML_SCHEMA_TYPE_IDC_KEYREF:
7167 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
7168 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7169 ADD_ANNOTATION(annot)
7170 }
7171 break;
7172 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7173 xmlSchemaAttributeGroupPtr item =
7174 (xmlSchemaAttributeGroupPtr) annItem;
7175 ADD_ANNOTATION(annot)
7176 }
7177 break;
7178 case XML_SCHEMA_TYPE_NOTATION: {
7179 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7180 ADD_ANNOTATION(annot)
7181 }
7182 break;
7183 case XML_SCHEMA_FACET_MININCLUSIVE:
7184 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7185 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7186 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7187 case XML_SCHEMA_FACET_TOTALDIGITS:
7188 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7189 case XML_SCHEMA_FACET_PATTERN:
7190 case XML_SCHEMA_FACET_ENUMERATION:
7191 case XML_SCHEMA_FACET_WHITESPACE:
7192 case XML_SCHEMA_FACET_LENGTH:
7193 case XML_SCHEMA_FACET_MAXLENGTH:
7194 case XML_SCHEMA_FACET_MINLENGTH: {
7195 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7196 ADD_ANNOTATION(annot)
7197 }
7198 break;
7199 case XML_SCHEMA_TYPE_SIMPLE:
7200 case XML_SCHEMA_TYPE_COMPLEX: {
7201 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7202 ADD_ANNOTATION(annot)
7203 }
7204 break;
7205 case XML_SCHEMA_TYPE_GROUP: {
7206 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7207 ADD_ANNOTATION(annot)
7208 }
7209 break;
7210 case XML_SCHEMA_TYPE_SEQUENCE:
7211 case XML_SCHEMA_TYPE_CHOICE:
7212 case XML_SCHEMA_TYPE_ALL: {
7213 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7214 ADD_ANNOTATION(annot)
7215 }
7216 break;
7217 default:
7218 xmlSchemaPCustomErr(NULL,
7219 XML_SCHEMAP_INTERNAL,
7220 NULL, NULL, NULL,
7221 "Internal error: xmlSchemaAddAnnotation, "
7222 "The item is not a annotated schema component", NULL);
7223 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007225 return (annot);
7226}
7227
7228/**
7229 * xmlSchemaParseIDCSelectorAndField:
7230 * @ctxt: a schema validation context
7231 * @schema: the schema being built
7232 * @node: a subtree containing XML Schema informations
7233 *
7234 * Parses a XML Schema identity-contraint definition's
7235 * <selector> and <field> elements.
7236 *
7237 * Returns the parsed identity-constraint definition.
7238 */
7239static xmlSchemaIDCSelectPtr
7240xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
7241 xmlSchemaPtr schema,
7242 xmlSchemaIDCPtr idc,
7243 xmlNodePtr node,
7244 int isField)
7245{
7246 xmlSchemaIDCSelectPtr item;
7247 xmlNodePtr child = NULL;
7248 xmlAttrPtr attr;
7249
7250 /*
7251 * Check for illegal attributes.
7252 */
7253 attr = node->properties;
7254 while (attr != NULL) {
7255 if (attr->ns == NULL) {
7256 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7257 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
7258 xmlSchemaPIllegalAttrErr(ctxt,
7259 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7260 NULL, NULL, attr);
7261 }
7262 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7263 xmlSchemaPIllegalAttrErr(ctxt,
7264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7265 NULL, NULL, attr);
7266 }
7267 attr = attr->next;
7268 }
7269 /*
7270 * Create the item.
7271 */
7272 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7273 if (item == NULL) {
7274 xmlSchemaPErrMemory(ctxt,
7275 "allocating a 'selector' of an identity-constraint definition",
7276 NULL);
7277 return (NULL);
7278 }
7279 memset(item, 0, sizeof(xmlSchemaIDCSelect));
7280 /*
7281 * Attribute "xpath" (mandatory).
7282 */
7283 attr = xmlSchemaGetPropNode(node, "xpath");
7284 if (attr == NULL) {
7285 xmlSchemaPMissingAttrErr(ctxt,
7286 XML_SCHEMAP_S4S_ATTR_MISSING,
7287 NULL, NULL, node,
7288 "name", NULL);
7289 } else {
7290 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7291 /*
7292 * URGENT TODO: "field"s have an other syntax than "selector"s.
7293 */
7294
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007295 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7296 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007297 xmlSchemaPErr(ctxt,
7298 (xmlNodePtr) attr,
7299 XML_SCHEMAP_INTERNAL,
7300 "Internal error: xmlSchemaParseIDCSelectorAndField, "
7301 "validating the XPath expression of a IDC selector.\n",
7302 NULL, NULL);
7303 }
7304
7305 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007306 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007307 /*
7308 * And now for the children...
7309 */
7310 child = node->children;
7311 if (IS_SCHEMA(child, "annotation")) {
7312 /*
7313 * Add the annotation to the parent IDC.
7314 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007315 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007316 xmlSchemaParseAnnotation(ctxt, schema, child));
7317 child = child->next;
7318 }
7319 if (child != NULL) {
7320 xmlSchemaPContentErr(ctxt,
7321 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7322 NULL, NULL, node, child,
7323 NULL, "(annotation?)");
7324 }
7325
7326 return (item);
7327}
7328
7329/**
7330 * xmlSchemaParseIDC:
7331 * @ctxt: a schema validation context
7332 * @schema: the schema being built
7333 * @node: a subtree containing XML Schema informations
7334 *
7335 * Parses a XML Schema identity-contraint definition.
7336 *
7337 * Returns the parsed identity-constraint definition.
7338 */
7339static xmlSchemaIDCPtr
7340xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
7341 xmlSchemaPtr schema,
7342 xmlNodePtr node,
7343 xmlSchemaTypeType idcCategory,
7344 const xmlChar *targetNamespace)
7345{
7346 xmlSchemaIDCPtr item = NULL;
7347 xmlNodePtr child = NULL;
7348 xmlAttrPtr attr;
7349 const xmlChar *name = NULL;
7350 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7351 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007352
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007353 /*
7354 * Check for illegal attributes.
7355 */
7356 attr = node->properties;
7357 while (attr != NULL) {
7358 if (attr->ns == NULL) {
7359 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7360 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7361 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7362 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
7363 xmlSchemaPIllegalAttrErr(ctxt,
7364 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7365 NULL, NULL, attr);
7366 }
7367 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7368 xmlSchemaPIllegalAttrErr(ctxt,
7369 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7370 NULL, NULL, attr);
7371 }
7372 attr = attr->next;
7373 }
7374 /*
7375 * Attribute "name" (mandatory).
7376 */
7377 attr = xmlSchemaGetPropNode(node, "name");
7378 if (attr == NULL) {
7379 xmlSchemaPMissingAttrErr(ctxt,
7380 XML_SCHEMAP_S4S_ATTR_MISSING,
7381 NULL, NULL, node,
7382 "name", NULL);
7383 return (NULL);
7384 } else if (xmlSchemaPValAttrNode(ctxt,
7385 NULL, NULL, attr,
7386 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7387 return (NULL);
7388 }
7389 /*
7390 * Create the component.
7391 */
7392 if (schema->idcDef == NULL)
7393 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
7394 if (schema->idcDef == NULL)
7395 return (NULL);
7396
7397 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7398 if (item == NULL) {
7399 xmlSchemaPErrMemory(ctxt,
7400 "allocating an identity-constraint definition", NULL);
7401 return (NULL);
7402 }
7403 /*
7404 * Add the IDC to the list of IDCs on the schema component.
7405 */
7406 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
7407 if (resAdd != 0) {
7408 xmlSchemaPCustomErrExt(ctxt,
7409 XML_SCHEMAP_REDEFINED_TYPE,
7410 NULL, NULL, node,
7411 "An identity-constraint definition with the name '%s' "
7412 "and targetNamespace '%s' does already exist",
7413 name, targetNamespace, NULL);
7414 xmlFree(item);
7415 return (NULL);
7416 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007417 memset(item, 0, sizeof(xmlSchemaIDC));
7418 item->name = name;
7419 item->type = idcCategory;
7420 item->node = node;
7421 /*
7422 * The target namespace of the parent element declaration.
7423 */
7424 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007425 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7426 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007427 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7428 /*
7429 * Attribute "refer" (mandatory).
7430 */
7431 attr = xmlSchemaGetPropNode(node, "refer");
7432 if (attr == NULL) {
7433 xmlSchemaPMissingAttrErr(ctxt,
7434 XML_SCHEMAP_S4S_ATTR_MISSING,
7435 NULL, NULL, node,
7436 "refer", NULL);
7437 } else {
7438 /*
7439 * Create a reference item.
7440 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007441 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
7442 NULL, NULL);
7443 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007444 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007445 xmlSchemaPValAttrNodeQName(ctxt, schema,
7446 NULL, NULL, attr,
7447 &(item->ref->targetNamespace), 0,
7448 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007449 xmlSchemaCheckReference(ctxt, schema, node,
7450 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007451 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007452 }
7453 }
7454 /*
7455 * And now for the children...
7456 */
7457 child = node->children;
7458 if (IS_SCHEMA(child, "annotation")) {
7459 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7460 child = child->next;
7461 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007462 if (child == NULL) {
7463 xmlSchemaPContentErr(ctxt,
7464 XML_SCHEMAP_S4S_ELEM_MISSING,
7465 NULL, NULL, node, child,
7466 "A child element is missing",
7467 "(annotation?, (selector, field+))");
7468 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007469 /*
7470 * Child element <selector>.
7471 */
7472 if (IS_SCHEMA(child, "selector")) {
7473 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7474 item, child, 0);
7475 child = child->next;
7476 /*
7477 * Child elements <field>.
7478 */
7479 if (IS_SCHEMA(child, "field")) {
7480 do {
7481 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7482 item, child, 1);
7483 if (field != NULL) {
7484 field->index = item->nbFields;
7485 item->nbFields++;
7486 if (lastField != NULL)
7487 lastField->next = field;
7488 else
7489 item->fields = field;
7490 lastField = field;
7491 }
7492 child = child->next;
7493 } while (IS_SCHEMA(child, "field"));
7494 } else {
7495 xmlSchemaPContentErr(ctxt,
7496 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7497 NULL, NULL, node, child,
7498 NULL, "(annotation?, (selector, field+))");
7499 }
7500 }
7501 if (child != NULL) {
7502 xmlSchemaPContentErr(ctxt,
7503 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7504 NULL, NULL, node, child,
7505 NULL, "(annotation?, (selector, field+))");
7506 }
7507
7508 return (item);
7509}
7510
Daniel Veillardc0826a72004-08-10 14:17:33 +00007511/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007512 * xmlSchemaParseElement:
7513 * @ctxt: a schema validation context
7514 * @schema: the schema being built
7515 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007516 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007517 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007518 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007519 * *WARNING* this interface is highly subject to change
7520 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007521 * Returns the element declaration or a particle; NULL in case
7522 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007523 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007524static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007525xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007526 xmlNodePtr node, int topLevel)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007527{
7528 xmlSchemaElementPtr decl = NULL;
7529 xmlSchemaParticlePtr particle = NULL;
7530 xmlSchemaAnnotPtr annot = NULL;
7531 xmlNodePtr child = NULL;
7532 xmlAttrPtr attr, nameAttr;
7533 int min, max, isRef = 0;
7534 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007535
7536 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7537 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007538
Daniel Veillard4255d502002-04-16 15:50:10 +00007539 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007540 return (NULL);
7541 /*
7542 * If we get a "ref" attribute on a local <element> we will assume it's
7543 * a reference - even if there's a "name" attribute; this seems to be more
7544 * robust.
7545 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 nameAttr = xmlSchemaGetPropNode(node, "name");
7547 attr = xmlSchemaGetPropNode(node, "ref");
7548 if ((topLevel) || (attr == NULL)) {
7549 if (nameAttr == NULL) {
7550 xmlSchemaPMissingAttrErr(ctxt,
7551 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007552 NULL, NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007553 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007554 }
7555 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007556 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007557
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007558 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7559 child = node->children;
7560 if (IS_SCHEMA(child, "annotation")) {
7561 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7562 child = child->next;
7563 }
7564 /*
7565 * Skip particle part if a global declaration.
7566 */
7567 if (topLevel)
7568 goto declaration_part;
7569 /*
7570 * The particle part ==================================================
7571 */
7572 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7573 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7574 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7575 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7576 if (particle == NULL)
7577 goto return_null;
7578
7579 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7580
7581 if (isRef) {
7582 const xmlChar *refNs = NULL, *ref = NULL;
7583 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007584 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007585 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007586 */
7587 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007588 NULL, NULL, attr, &refNs, NULL, &ref);
7589 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007590 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007591 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007592 */
7593 if (nameAttr != NULL) {
7594 xmlSchemaPMutualExclAttrErr(ctxt,
7595 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007596 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007597 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007598 /*
7599 * Check for illegal attributes.
7600 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007601 attr = node->properties;
7602 while (attr != NULL) {
7603 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007604 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7605 xmlStrEqual(attr->name, BAD_CAST "name") ||
7606 xmlStrEqual(attr->name, BAD_CAST "id") ||
7607 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7608 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7609 {
7610 attr = attr->next;
7611 continue;
7612 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007613 /* SPEC (3.3.3 : 2.2) */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007614 xmlSchemaPCustomAttrErr(ctxt,
7615 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007616 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007617 "Only the attributes 'minOccurs', 'maxOccurs' and "
7618 "'id' are allowed in addition to 'ref'");
7619 break;
7620 }
7621 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7622 xmlSchemaPIllegalAttrErr(ctxt,
7623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007624 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007625 }
7626 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007627 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007628 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007629 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007630 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007631 if (child != NULL) {
7632 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7633 NULL, NULL, node, child, NULL, "(annotation?)");
7634 }
7635 if ((min == 0) && (max == 0))
7636 goto return_null;
7637 /*
7638 * Create the reference item.
7639 */
7640 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7641 ref, refNs);
7642 if (refer == NULL)
7643 goto return_null;
7644 particle->children = (xmlSchemaTreeItemPtr) refer;
7645 particle->annot = annot;
7646 /*
7647 * Add to assembled items; the reference need to be resolved.
7648 */
7649 if (ctxt->assemble != NULL)
7650 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7651
7652 return ((xmlSchemaBasicItemPtr) particle);
7653 }
7654 /*
7655 * The declaration part ===============================================
7656 */
7657declaration_part:
7658 {
7659 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7660 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7661
7662 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007664 goto return_null;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 /*
7666 * Evaluate the target namespace.
7667 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007668 if (topLevel) {
7669 ns = schema->targetNamespace;
7670 } else {
7671 attr = xmlSchemaGetPropNode(node, "form");
7672 if (attr != NULL) {
7673 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7674 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007675 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007676 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
7677 xmlSchemaPSimpleTypeErr(ctxt,
7678 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007679 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007680 NULL, "(qualified | unqualified)",
7681 attrValue, NULL, NULL, NULL);
7682 }
7683 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7684 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00007685 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007686 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
7687 if (decl == NULL) {
7688 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007689 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007690 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7691 decl->node = node;
7692 decl->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007693 /*
7694 * Check for illegal attributes.
7695 */
William M. Bracke7091952004-05-11 15:09:58 +00007696 attr = node->properties;
7697 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 if (attr->ns == NULL) {
7699 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7700 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7701 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7702 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7703 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7704 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007705 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7706 {
7707 if (topLevel == 0) {
7708 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007709 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007710 (!xmlStrEqual(attr->name, BAD_CAST "form")))
7711 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007712 xmlSchemaPIllegalAttrErr(ctxt,
7713 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7714 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007715 }
7716 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7717 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
7718 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7719
7720 xmlSchemaPIllegalAttrErr(ctxt,
7721 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007722 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007723 }
7724 }
7725 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7726
7727 xmlSchemaPIllegalAttrErr(ctxt,
7728 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007729 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007730 }
7731 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 }
William M. Bracke7091952004-05-11 15:09:58 +00007733 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007734 * Extract/validate attributes.
7735 */
7736 if (topLevel) {
7737 /*
7738 * Process top attributes of global element declarations here.
7739 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007740 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7741 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
7742 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7743 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7744 &(decl->substGroupNs), NULL, &(decl->substGroup));
7745 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007746 node, "abstract", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007747 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007748 /*
7749 * Attribute "final".
7750 */
7751 attr = xmlSchemaGetPropNode(node, "final");
7752 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007753 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7754 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7755 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7756 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007757 } else {
7758 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007760 -1,
7761 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7762 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
7763 xmlSchemaPSimpleTypeErr(ctxt,
7764 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007765 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007766 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007767 attrValue, NULL, NULL, NULL);
7768 }
7769 }
7770 }
7771 /*
7772 * Attribute "block".
7773 */
7774 attr = xmlSchemaGetPropNode(node, "block");
7775 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007776 /*
7777 * Apply default "block" values.
7778 */
7779 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7780 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7781 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7782 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7783 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7784 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007785 } else {
7786 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007787 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007788 -1,
7789 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
7790 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
7791 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7792 xmlSchemaPSimpleTypeErr(ctxt,
7793 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007794 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007795 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00007796 "restriction | substitution))", attrValue,
7797 NULL, NULL, NULL);
7798 }
7799 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007800 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007801 node, "nillable", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007802 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007803
Daniel Veillardc0826a72004-08-10 14:17:33 +00007804 xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007805 NULL, (xmlSchemaTypePtr) decl, node,
7806 "type", &(decl->namedTypeNs), NULL, &(decl->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00007807
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007808 decl->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007809 attr = xmlSchemaGetPropNode(node, "fixed");
7810 if (attr != NULL) {
7811 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007812 if (decl->value != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007813 /*
7814 * 3.3.3 : 1
7815 * default and fixed must not both be present.
7816 */
7817 xmlSchemaPMutualExclAttrErr(ctxt,
7818 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007819 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007820 "default", "fixed");
7821 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007822 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7823 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007824 }
William M. Bracke7091952004-05-11 15:09:58 +00007825 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007826 /*
7827 * And now for the children...
7828 */
7829 oldcontainer = ctxt->container;
7830 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007831 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007832 /*
7833 * 3.3.3 : 3
7834 * "type" and either <simpleType> or <complexType> are mutually
7835 * exclusive
7836 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007837 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007838 xmlSchemaPContentErr(ctxt,
7839 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007840 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007841 "The attribute 'type' and the <complexType> child are "
7842 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007843 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007844 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007845 child = child->next;
7846 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007847 /*
7848 * 3.3.3 : 3
7849 * "type" and either <simpleType> or <complexType> are
7850 * mutually exclusive
7851 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007852 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007853 xmlSchemaPContentErr(ctxt,
7854 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007855 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007856 "The attribute 'type' and the <simpleType> child are "
7857 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007858 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007859 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007860 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007861 }
William M. Bracke7091952004-05-11 15:09:58 +00007862 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007863 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007864 if (IS_SCHEMA(child, "unique")) {
7865 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007866 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007867 } else if (IS_SCHEMA(child, "key")) {
7868 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007869 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007870 } else if (IS_SCHEMA(child, "keyref")) {
7871 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007872 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007873 }
7874 if (lastIDC != NULL)
7875 lastIDC->next = curIDC;
7876 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007877 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007878 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007879 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007880 }
7881 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007882 xmlSchemaPContentErr(ctxt,
7883 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007884 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007885 NULL, "(annotation?, ((simpleType | complexType)?, "
7886 "(unique | key | keyref)*))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007887 }
7888 ctxt->container = oldcontainer;
7889 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007890 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007891 /*
7892 * NOTE: Element Declaration Representation OK 4. will be checked at a
7893 * different layer.
7894 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007895 FREE_AND_NULL(des)
7896 if (topLevel)
7897 return ((xmlSchemaBasicItemPtr) decl);
7898 else {
7899 particle->children = (xmlSchemaTreeItemPtr) decl;
7900 return ((xmlSchemaBasicItemPtr) particle);
7901 }
7902
7903return_null:
7904 FREE_AND_NULL(des)
7905 if (annot != NULL)
7906 xmlSchemaFreeAnnot(annot);
7907 if (particle != NULL)
7908 xmlSchemaFreeParticle(particle);
7909 if (decl != NULL)
7910 xmlSchemaFreeElement(decl);
7911 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007912}
7913
7914/**
7915 * xmlSchemaParseUnion:
7916 * @ctxt: a schema validation context
7917 * @schema: the schema being built
7918 * @node: a subtree containing XML Schema informations
7919 *
7920 * parse a XML schema Union definition
7921 * *WARNING* this interface is highly subject to change
7922 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 * Returns -1 in case of internal error, 0 in case of success and a positive
7924 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007925 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007926static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007927xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007928 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007929{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007930 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007932 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007933 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007934
7935 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007936 return (-1);
7937 /* Not a component, don't create it. */
7938 type = ctxt->ctxtType;
7939 /*
7940 * Mark the simple type as being of variety "union".
7941 */
7942 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007943 /*
7944 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7945 * then the ·simple ur-type definition·."
7946 */
7947 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007948 /*
7949 * Check for illegal attributes.
7950 */
7951 attr = node->properties;
7952 while (attr != NULL) {
7953 if (attr->ns == NULL) {
7954 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7955 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7956 xmlSchemaPIllegalAttrErr(ctxt,
7957 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007958 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007959 }
7960 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7961 xmlSchemaPIllegalAttrErr(ctxt,
7962 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007963 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007964 }
7965 attr = attr->next;
7966 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007967 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007968 /*
7969 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007970 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007971 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007972 attr = xmlSchemaGetPropNode(node, "memberTypes");
7973 if (attr != NULL) {
7974 const xmlChar *end;
7975 xmlChar *tmp;
7976 const xmlChar *localName, *nsName;
7977 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7978 xmlSchemaQNameRefPtr ref;
7979
7980 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7981 type->ref = cur;
7982 do {
7983 while (IS_BLANK_CH(*cur))
7984 cur++;
7985 end = cur;
7986 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7987 end++;
7988 if (end == cur)
7989 break;
7990 tmp = xmlStrndup(cur, end - cur);
7991 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7992 NULL, attr, BAD_CAST tmp, &nsName, NULL, &localName) == 0) {
7993 /*
7994 * Create the member type link.
7995 */
7996 link = (xmlSchemaTypeLinkPtr)
7997 xmlMalloc(sizeof(xmlSchemaTypeLink));
7998 if (link == NULL) {
7999 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8000 "allocating a type link", NULL);
8001 return (-1);
8002 }
8003 link->type = NULL;
8004 link->next = NULL;
8005 if (lastLink == NULL)
8006 type->memberTypes = link;
8007 else
8008 lastLink->next = link;
8009 lastLink = link;
8010 /*
8011 * Create a reference item.
8012 */
8013 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
8014 localName, nsName);
8015 if (ref == NULL) {
8016 FREE_AND_NULL(tmp)
8017 return (-1);
8018 }
8019 /*
8020 * Assign the reference to the link, it will be resolved
8021 * later during fixup of the union simple type.
8022 */
8023 link->type = (xmlSchemaTypePtr) ref;
8024 }
8025 FREE_AND_NULL(tmp)
8026 cur = end;
8027 } while (*cur != 0);
8028
8029 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008030 /*
8031 * And now for the children...
8032 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008033 child = node->children;
8034 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008035 /*
8036 * Add the annotation to the simple type ancestor.
8037 */
8038 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8039 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008040 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008041 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008042 if (IS_SCHEMA(child, "simpleType")) {
8043 xmlSchemaTypePtr subtype, last = NULL;
8044
8045 /*
8046 * Anchor the member types in the "subtypes" field of the
8047 * simple type.
8048 */
8049 while (IS_SCHEMA(child, "simpleType")) {
8050 subtype = (xmlSchemaTypePtr)
8051 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8052 if (subtype != NULL) {
8053 if (last == NULL) {
8054 type->subtypes = subtype;
8055 last = subtype;
8056 } else {
8057 last->next = subtype;
8058 last = subtype;
8059 }
8060 last->next = NULL;
8061 }
8062 child = child->next;
8063 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008064 }
8065 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008066 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008067 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8068 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
8069 }
8070 if ((attr == NULL) && (type->subtypes == NULL)) {
8071 /*
8072 * src-union-memberTypes-or-simpleTypes
8073 * Either the memberTypes [attribute] of the <union> element must
8074 * be non-empty or there must be at least one simpleType [child].
8075 */
8076 xmlSchemaPCustomErr(ctxt,
8077 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8078 NULL, NULL, node,
8079 "Either the attribute 'memberTypes' or "
8080 "at least one <simpleType> child must be present", NULL);
8081 }
8082 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008083}
8084
8085/**
8086 * xmlSchemaParseList:
8087 * @ctxt: a schema validation context
8088 * @schema: the schema being built
8089 * @node: a subtree containing XML Schema informations
8090 *
8091 * parse a XML schema List definition
8092 * *WARNING* this interface is highly subject to change
8093 *
William M. Bracke7091952004-05-11 15:09:58 +00008094 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008095 * 1 in case of success.
8096 */
8097static xmlSchemaTypePtr
8098xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008099 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008100{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008101 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008102 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008103 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008104
8105 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8106 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008107 /* Not a component, don't create it. */
8108 type = ctxt->ctxtType;
8109 /*
8110 * Mark the type as being of variety "list".
8111 */
8112 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008113 /*
8114 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8115 * then the ·simple ur-type definition·."
8116 */
8117 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008118 /*
8119 * Check for illegal attributes.
8120 */
8121 attr = node->properties;
8122 while (attr != NULL) {
8123 if (attr->ns == NULL) {
8124 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8125 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
8126 xmlSchemaPIllegalAttrErr(ctxt,
8127 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008128 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008129 }
8130 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8131 xmlSchemaPIllegalAttrErr(ctxt,
8132 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008133 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008134 }
8135 attr = attr->next;
8136 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008137
8138 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8139
William M. Brack2f2a6632004-08-20 23:09:47 +00008140 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008141 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8142 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008143 */
8144 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008145 node, "itemType", &(type->refNs), NULL, &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008146 /*
8147 * And now for the children...
8148 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008149 child = node->children;
8150 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008151 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8152 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008153 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008154 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008155 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008156 /*
8157 * src-list-itemType-or-simpleType
8158 * Either the itemType [attribute] or the <simpleType> [child] of
8159 * the <list> element must be present, but not both.
8160 */
8161 if (type->ref != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008162 xmlSchemaPCustomErr(ctxt,
8163 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008164 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008165 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008166 "are mutually exclusive", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008167 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008168 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008169 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008170 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008171 } else if (type->ref == NULL) {
8172 xmlSchemaPCustomErr(ctxt,
8173 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8174 NULL, NULL, node,
8175 "Either the attribute 'itemType' or the <simpleType> child "
8176 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008177 }
8178 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008179 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008180 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8181 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008182 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008183 if ((type->ref == NULL) &&
8184 (type->subtypes == NULL) &&
8185 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
8186 xmlSchemaPCustomErr(ctxt,
8187 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8188 NULL, NULL, node,
8189 "Either the attribute 'itemType' or the <simpleType> child "
8190 "must be present", NULL);
8191 }
8192 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008193}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008194
Daniel Veillard4255d502002-04-16 15:50:10 +00008195/**
8196 * xmlSchemaParseSimpleType:
8197 * @ctxt: a schema validation context
8198 * @schema: the schema being built
8199 * @node: a subtree containing XML Schema informations
8200 *
8201 * parse a XML schema Simple Type definition
8202 * *WARNING* this interface is highly subject to change
8203 *
William M. Bracke7091952004-05-11 15:09:58 +00008204 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008205 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008206 */
8207static xmlSchemaTypePtr
8208xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008209 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008210{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008211 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008212 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008213 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008214 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008215
8216 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8217 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008218
Daniel Veillardc0826a72004-08-10 14:17:33 +00008219 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008220 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008221 if (attr == NULL) {
8222 xmlSchemaPMissingAttrErr(ctxt,
8223 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008224 NULL, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008225 "name", NULL);
8226 return (NULL);
8227 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008229 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008230 return (NULL);
8231 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008232 }
8233
8234 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008235 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008236
Daniel Veillard01fa6152004-06-29 17:04:39 +00008237 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008238 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008239 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008240 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008241 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008242 if (type == NULL)
8243 return (NULL);
8244 type->node = node;
8245 type->type = XML_SCHEMA_TYPE_SIMPLE;
8246 /*
8247 * Check for illegal attributes.
8248 */
8249 attr = node->properties;
8250 while (attr != NULL) {
8251 if (attr->ns == NULL) {
8252 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
8253 xmlSchemaPIllegalAttrErr(ctxt,
8254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008255 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008256 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008257 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8258 xmlSchemaPIllegalAttrErr(ctxt,
8259 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008260 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008261 }
8262 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008263 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008264 } else {
8265 /*
8266 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008267 *
8268 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008269 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008270 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008271 if (type == NULL)
8272 return (NULL);
8273 type->node = node;
8274 type->type = XML_SCHEMA_TYPE_SIMPLE;
8275 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8276 /*
8277 * Check for illegal attributes.
8278 */
8279 attr = node->properties;
8280 while (attr != NULL) {
8281 if (attr->ns == NULL) {
8282 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8283 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008284 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008285 xmlSchemaPIllegalAttrErr(ctxt,
8286 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008287 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008288 }
8289 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8290 xmlSchemaPIllegalAttrErr(ctxt,
8291 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008293 }
8294 attr = attr->next;
8295 }
8296 /*
8297 * Attribute "final".
8298 */
8299 attr = xmlSchemaGetPropNode(node, "final");
8300 if (attr == NULL) {
8301 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8302 } else {
8303 attrValue = xmlSchemaGetProp(ctxt, node, "final");
8304 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8305 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
8306 XML_SCHEMAS_TYPE_FINAL_LIST,
8307 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8308
8309 xmlSchemaPSimpleTypeErr(ctxt,
8310 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008311 NULL, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008312 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008313 attrValue, NULL, NULL, NULL);
8314 }
8315 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008316 }
8317 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008318 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008319 /*
8320 * And now for the children...
8321 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008322 oldCtxtType = ctxt->ctxtType;
8323 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008324 ctxt->ctxtType = type;
8325 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008326 child = node->children;
8327 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008328 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8329 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008330 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008331 if (child == NULL) {
8332 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8333 NULL, type, node, child, NULL,
8334 "(annotation?, (restriction | list | union))");
8335 } else if (IS_SCHEMA(child, "restriction")) {
8336 xmlSchemaParseRestriction(ctxt, schema, child,
8337 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008338 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008339 } else if (IS_SCHEMA(child, "list")) {
8340 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008341 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008342 } else if (IS_SCHEMA(child, "union")) {
8343 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008344 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008345 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008346 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008347 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008348 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008349 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008350 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008351 ctxt->parentItem = oldParentItem;
8352 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008353
Daniel Veillard4255d502002-04-16 15:50:10 +00008354 return (type);
8355}
8356
Daniel Veillard4255d502002-04-16 15:50:10 +00008357/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008358 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008359 * @ctxt: a schema validation context
8360 * @schema: the schema being built
8361 * @node: a subtree containing XML Schema informations
8362 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008363 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008364 * *WARNING* this interface is highly subject to change
8365 *
William M. Bracke7091952004-05-11 15:09:58 +00008366 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008367 * 1 in case of success.
8368 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369static xmlSchemaTreeItemPtr
8370xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8371 xmlSchemaPtr schema,
8372 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008373{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008374 xmlSchemaParticlePtr item;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008375 xmlNodePtr child = NULL;
8376 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008377 const xmlChar *ref = NULL, *refNs = NULL;
8378 int min, max;
8379
8380 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8381 return (NULL);
8382
8383 attr = xmlSchemaGetPropNode(node, "ref");
8384 if (attr == NULL) {
8385 xmlSchemaPMissingAttrErr(ctxt,
8386 XML_SCHEMAP_S4S_ATTR_MISSING,
8387 NULL, NULL, node,
8388 "ref", NULL);
8389 return (NULL);
8390 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
8391 attr, &refNs, NULL, &ref) != 0) {
8392 return (NULL);
8393 }
8394 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8395 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8396 "(nonNegativeInteger | unbounded)");
8397 /*
8398 * Check for illegal attributes.
8399 */
8400 attr = node->properties;
8401 while (attr != NULL) {
8402 if (attr->ns == NULL) {
8403 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
8404 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8405 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8406 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
8407 xmlSchemaPIllegalAttrErr(ctxt,
8408 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8409 NULL, NULL, attr);
8410 }
8411 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8412 xmlSchemaPIllegalAttrErr(ctxt,
8413 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8414 NULL, NULL, attr);
8415 }
8416 attr = attr->next;
8417 }
8418 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8419 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8420 if (item == NULL)
8421 return (NULL);
8422 /*
8423 * Create a reference item as the term; it will be substituted for
8424 * the model group after the reference has been resolved.
8425 */
8426 item->children = (xmlSchemaTreeItemPtr)
8427 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8428 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8429 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8430 /*
8431 * And now for the children...
8432 */
8433 child = node->children;
8434 /* TODO: Is annotation even allowed for a model group reference? */
8435 if (IS_SCHEMA(child, "annotation")) {
8436 /*
8437 * TODO: What to do exactly with the annotation?
8438 */
8439 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8440 child = child->next;
8441 }
8442 if (child != NULL) {
8443 xmlSchemaPContentErr(ctxt,
8444 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8445 NULL, NULL, node, child, NULL,
8446 "(annotation?)");
8447 }
8448 /*
8449 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8450 */
8451 if ((min == 0) && (max == 0))
8452 return (NULL);
8453 if (ctxt->assemble != NULL)
8454 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8455 return ((xmlSchemaTreeItemPtr) item);
8456}
8457
8458/**
8459 * xmlSchemaParseModelGroupDefinition:
8460 * @ctxt: a schema validation context
8461 * @schema: the schema being built
8462 * @node: a subtree containing XML Schema informations
8463 *
8464 * Parses a XML schema model group definition.
8465 * *WARNING* this interface is highly subject to change
8466 *
8467 * Returns -1 in case of error, 0 if the declaration is improper and
8468 * 1 in case of success.
8469 */
8470static xmlSchemaModelGroupDefPtr
8471xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8472 xmlSchemaPtr schema,
8473 xmlNodePtr node)
8474{
8475 xmlSchemaModelGroupDefPtr item;
8476 xmlNodePtr child = NULL;
8477 xmlAttrPtr attr;
8478 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008479
8480 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008481 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008482
8483 attr = xmlSchemaGetPropNode(node, "name");
8484 if (attr == NULL) {
8485 xmlSchemaPMissingAttrErr(ctxt,
8486 XML_SCHEMAP_S4S_ATTR_MISSING,
8487 NULL, NULL, node,
8488 "name", NULL);
8489 return (NULL);
8490 } else if (xmlSchemaPValAttrNode(ctxt,
8491 NULL, NULL, attr,
8492 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8493 return (NULL);
8494 }
8495 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8496 if (item == NULL)
8497 return (NULL);
8498 /*
8499 * Check for illegal attributes.
8500 */
8501 attr = node->properties;
8502 while (attr != NULL) {
8503 if (attr->ns == NULL) {
8504 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8505 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
8506 xmlSchemaPIllegalAttrErr(ctxt,
8507 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8508 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008509 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008510 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8511 xmlSchemaPIllegalAttrErr(ctxt,
8512 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8513 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008514 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008515 attr = attr->next;
8516 }
8517 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8518 /*
8519 * And now for the children...
8520 */
8521 child = node->children;
8522 if (IS_SCHEMA(child, "annotation")) {
8523 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8524 child = child->next;
8525 }
8526 if (IS_SCHEMA(child, "all")) {
8527 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8528 XML_SCHEMA_TYPE_ALL, 0);
8529 child = child->next;
8530 } else if (IS_SCHEMA(child, "choice")) {
8531 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8532 XML_SCHEMA_TYPE_CHOICE, 0);
8533 child = child->next;
8534 } else if (IS_SCHEMA(child, "sequence")) {
8535 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8536 XML_SCHEMA_TYPE_SEQUENCE, 0);
8537 child = child->next;
8538 }
8539 if (child != NULL) {
8540 xmlSchemaPContentErr(ctxt,
8541 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8542 NULL, NULL, node, child, NULL,
8543 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008544 }
8545
8546 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008547}
8548
8549/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008550 * xmlSchemaCleanupDoc:
8551 * @ctxt: a schema validation context
8552 * @node: the root of the document.
8553 *
8554 * removes unwanted nodes in a schemas document tree
8555 */
8556static void
8557xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8558{
8559 xmlNodePtr delete, cur;
8560
8561 if ((ctxt == NULL) || (root == NULL)) return;
8562
8563 /*
8564 * Remove all the blank text nodes
8565 */
8566 delete = NULL;
8567 cur = root;
8568 while (cur != NULL) {
8569 if (delete != NULL) {
8570 xmlUnlinkNode(delete);
8571 xmlFreeNode(delete);
8572 delete = NULL;
8573 }
8574 if (cur->type == XML_TEXT_NODE) {
8575 if (IS_BLANK_NODE(cur)) {
8576 if (xmlNodeGetSpacePreserve(cur) != 1) {
8577 delete = cur;
8578 }
8579 }
8580 } else if ((cur->type != XML_ELEMENT_NODE) &&
8581 (cur->type != XML_CDATA_SECTION_NODE)) {
8582 delete = cur;
8583 goto skip_children;
8584 }
8585
8586 /*
8587 * Skip to next node
8588 */
8589 if (cur->children != NULL) {
8590 if ((cur->children->type != XML_ENTITY_DECL) &&
8591 (cur->children->type != XML_ENTITY_REF_NODE) &&
8592 (cur->children->type != XML_ENTITY_NODE)) {
8593 cur = cur->children;
8594 continue;
8595 }
8596 }
8597 skip_children:
8598 if (cur->next != NULL) {
8599 cur = cur->next;
8600 continue;
8601 }
8602
8603 do {
8604 cur = cur->parent;
8605 if (cur == NULL)
8606 break;
8607 if (cur == root) {
8608 cur = NULL;
8609 break;
8610 }
8611 if (cur->next != NULL) {
8612 cur = cur->next;
8613 break;
8614 }
8615 } while (cur != NULL);
8616 }
8617 if (delete != NULL) {
8618 xmlUnlinkNode(delete);
8619 xmlFreeNode(delete);
8620 delete = NULL;
8621 }
8622}
8623
William M. Brack2f2a6632004-08-20 23:09:47 +00008624
8625/**
8626 * xmlSchemaImportSchema
8627 *
8628 * @ctxt: a schema validation context
8629 * @schemaLocation: an URI defining where to find the imported schema
8630 *
8631 * import a XML schema
8632 * *WARNING* this interface is highly subject to change
8633 *
8634 * Returns -1 in case of error and 1 in case of success.
8635 */
8636#if 0
8637static xmlSchemaImportPtr
8638xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8639 const xmlChar *schemaLocation)
8640{
8641 xmlSchemaImportPtr import;
8642 xmlSchemaParserCtxtPtr newctxt;
8643
8644 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8645 if (newctxt == NULL) {
8646 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8647 NULL);
8648 return (NULL);
8649 }
8650 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8651 /* Keep the same dictionnary for parsing, really */
8652 xmlDictReference(ctxt->dict);
8653 newctxt->dict = ctxt->dict;
8654 newctxt->includes = 0;
8655 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8656
8657 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8658 ctxt->userData);
8659
8660 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8661 if (import == NULL) {
8662 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8663 NULL);
8664 xmlSchemaFreeParserCtxt(newctxt);
8665 return (NULL);
8666 }
8667
8668 memset(import, 0, sizeof(xmlSchemaImport));
8669 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8670 import->schema = xmlSchemaParse(newctxt);
8671
8672 if (import->schema == NULL) {
8673 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008674 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008675 "Failed to import schema from location \"%s\".\n",
8676 schemaLocation, NULL);
8677
8678 xmlSchemaFreeParserCtxt(newctxt);
8679 /* The schemaLocation is held by the dictionary.
8680 if (import->schemaLocation != NULL)
8681 xmlFree((xmlChar *)import->schemaLocation);
8682 */
8683 xmlFree(import);
8684 return NULL;
8685 }
8686
8687 xmlSchemaFreeParserCtxt(newctxt);
8688 return import;
8689}
8690#endif
8691
8692static void
8693xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8694{
8695 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8696 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8697
8698 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8699 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8700
8701 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8702 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8703 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8704 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8705 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8706 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8707 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8708 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8709
8710 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8711 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8712 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8713 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8714 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8715 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8716}
8717
8718static void
8719xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
8720 xmlSchemaPtr schema,
8721 xmlNodePtr node)
8722{
8723 xmlAttrPtr attr;
8724 const xmlChar *val;
8725
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008726 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8727 if (schema->version == NULL)
8728 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8729 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8730 else
8731 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8732 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8733
William M. Brack2f2a6632004-08-20 23:09:47 +00008734 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
8735 if (attr != NULL) {
8736 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8737 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8738 XML_SCHEMAS_QUALIF_ELEM) != 0) {
8739 xmlSchemaPSimpleTypeErr(ctxt,
8740 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
8741 NULL, NULL, (xmlNodePtr) attr, NULL,
8742 "(qualified | unqualified)", val, NULL, NULL, NULL);
8743 }
8744 }
8745
8746 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
8747 if (attr != NULL) {
8748 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8749 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8750 XML_SCHEMAS_QUALIF_ATTR) != 0) {
8751 xmlSchemaPSimpleTypeErr(ctxt,
8752 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
8753 NULL, NULL, (xmlNodePtr) attr, NULL,
8754 "(qualified | unqualified)", val, NULL, NULL, NULL);
8755 }
8756 }
8757
8758 attr = xmlSchemaGetPropNode(node, "finalDefault");
8759 if (attr != NULL) {
8760 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8761 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8762 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8763 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8764 -1,
8765 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8766 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8767 xmlSchemaPSimpleTypeErr(ctxt,
8768 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8769 NULL, NULL, (xmlNodePtr) attr, NULL,
8770 "(#all | List of (extension | restriction | list | union))",
8771 val, NULL, NULL, NULL);
8772 }
8773 }
8774
8775 attr = xmlSchemaGetPropNode(node, "blockDefault");
8776 if (attr != NULL) {
8777 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8778 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8779 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8780 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8781 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8782 xmlSchemaPSimpleTypeErr(ctxt,
8783 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8784 NULL, NULL, (xmlNodePtr) attr, NULL,
8785 "(#all | List of (extension | restriction | substitution))",
8786 val, NULL, NULL, NULL);
8787 }
8788 }
8789}
8790
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008791/**
8792 * xmlSchemaParseSchemaTopLevel:
8793 * @ctxt: a schema validation context
8794 * @schema: the schemas
8795 * @nodes: the list of top level nodes
8796 *
8797 * Returns the internal XML Schema structure built from the resource or
8798 * NULL in case of error
8799 */
8800static void
8801xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8802 xmlSchemaPtr schema, xmlNodePtr nodes)
8803{
8804 xmlNodePtr child;
8805 xmlSchemaAnnotPtr annot;
8806
8807 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8808 return;
8809
8810 child = nodes;
8811 while ((IS_SCHEMA(child, "include")) ||
8812 (IS_SCHEMA(child, "import")) ||
8813 (IS_SCHEMA(child, "redefine")) ||
8814 (IS_SCHEMA(child, "annotation"))) {
8815 if (IS_SCHEMA(child, "annotation")) {
8816 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8817 if (schema->annot == NULL)
8818 schema->annot = annot;
8819 else
8820 xmlSchemaFreeAnnot(annot);
8821 } else if (IS_SCHEMA(child, "import")) {
8822 xmlSchemaParseImport(ctxt, schema, child);
8823 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008824 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008825 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008826 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008827 } else if (IS_SCHEMA(child, "redefine")) {
8828 TODO
8829 }
8830 child = child->next;
8831 }
8832 while (child != NULL) {
8833 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008834 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008835 child = child->next;
8836 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008837 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008838 child = child->next;
8839 } else if (IS_SCHEMA(child, "element")) {
8840 xmlSchemaParseElement(ctxt, schema, child, 1);
8841 child = child->next;
8842 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008843 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008844 child = child->next;
8845 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008846 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008847 child = child->next;
8848 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008849 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008850 child = child->next;
8851 } else if (IS_SCHEMA(child, "notation")) {
8852 xmlSchemaParseNotation(ctxt, schema, child);
8853 child = child->next;
8854 } else {
8855 xmlSchemaPErr2(ctxt, NULL, child,
8856 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008857 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008858 child->name, NULL);
8859 child = child->next;
8860 }
8861 while (IS_SCHEMA(child, "annotation")) {
8862 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8863 if (schema->annot == NULL)
8864 schema->annot = annot;
8865 else
8866 xmlSchemaFreeAnnot(annot);
8867 child = child->next;
8868 }
8869 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008870 ctxt->parentItem = NULL;
8871 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008872}
8873
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008874static xmlSchemaImportPtr
8875xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
8876 xmlHashTablePtr *imports,
8877 const xmlChar *nsName)
8878{
8879 xmlSchemaImportPtr ret;
8880
8881 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008882 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008883 if (*imports == NULL) {
8884 xmlSchemaPCustomErr(ctxt,
8885 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8886 NULL, NULL, (xmlNodePtr) ctxt->doc,
8887 "Internal error: failed to build the import table",
8888 NULL);
8889 return (NULL);
8890 }
8891 }
8892 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8893 if (ret == NULL) {
8894 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8895 return (NULL);
8896 }
8897 memset(ret, 0, sizeof(xmlSchemaImport));
8898 if (nsName == NULL)
8899 nsName = XML_SCHEMAS_NO_NAMESPACE;
8900 xmlHashAddEntry(*imports, nsName, ret);
8901
8902 return (ret);
8903}
8904
8905static int
8906xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008907 xmlSchemaPtr schema,
8908 xmlNodePtr node,
8909 const xmlChar *nsName,
8910 const xmlChar *location,
8911 xmlDocPtr *doc,
8912 const xmlChar **targetNamespace,
8913 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008914{
8915 xmlParserCtxtPtr parserCtxt;
8916 xmlSchemaImportPtr import;
8917 const xmlChar *ns;
8918 xmlNodePtr root;
8919
8920 /*
8921 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8922 * <xsi:noNamespaceSchemaLocation>.
8923 */
8924 *doc = NULL;
8925 /*
8926 * Given that the schemaLocation [attribute] is only a hint, it is open
8927 * to applications to ignore all but the first <import> for a given
8928 * namespace, regardless of the ·actual value· of schemaLocation, but
8929 * such a strategy risks missing useful information when new
8930 * schemaLocations are offered.
8931 *
8932 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8933 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8934 * valid or not.
8935 * We will follow XSV here.
8936 */
8937 if (location == NULL) {
8938 /*
8939 * Schema Document Location Strategy:
8940 *
8941 * 3 Based on the namespace name, identify an existing schema document,
8942 * either as a resource which is an XML document or a <schema> element
8943 * information item, in some local schema repository;
8944 *
8945 * 5 Attempt to resolve the namespace name to locate such a resource.
8946 *
8947 * NOTE: Those stategies are not supported, so we will skip.
8948 */
8949 return (0);
8950 }
8951 if (nsName == NULL)
8952 ns = XML_SCHEMAS_NO_NAMESPACE;
8953 else
8954 ns = nsName;
8955
8956 import = xmlHashLookup(schema->schemasImports, ns);
8957 if (import != NULL) {
8958 /*
8959 * There was a valid resource for the specified namespace already
8960 * defined, so skip.
8961 * TODO: This might be changed someday to allow import of
8962 * components from multiple documents for a single target namespace.
8963 */
8964 return (0);
8965 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008966
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008967 /*
8968 * Schema Document Location Strategy:
8969 *
8970 * 2 Based on the location URI, identify an existing schema document,
8971 * either as a resource which is an XML document or a <schema> element
8972 * information item, in some local schema repository;
8973 *
8974 * 4 Attempt to resolve the location URI, to locate a resource on the
8975 * web which is or contains or references a <schema> element;
8976 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8977 *
8978 */
8979 if ((absolute == 0) && (node != NULL)) {
8980 xmlChar *base, *URI;
8981
8982 base = xmlNodeGetBase(node->doc, node);
8983 if (base == NULL) {
8984 URI = xmlBuildURI(location, node->doc->URL);
8985 } else {
8986 URI = xmlBuildURI(location, base);
8987 xmlFree(base);
8988 }
8989 if (URI != NULL) {
8990 location = xmlDictLookup(ctxt->dict, URI, -1);
8991 xmlFree(URI);
8992 }
8993 }
8994 parserCtxt = xmlNewParserCtxt();
8995 if (parserCtxt == NULL) {
8996 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8997 "allocating a parser context", NULL);
8998 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008999 }
9000
9001 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9002 xmlDictFree(parserCtxt->dict);
9003 parserCtxt->dict = ctxt->dict;
9004 xmlDictReference(parserCtxt->dict);
9005 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009006
9007 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
9008 NULL, SCHEMAS_PARSE_OPTIONS);
9009
9010 /*
9011 * 2.1 The referent is (a fragment of) a resource which is an
9012 * XML document (see clause 1.1), which in turn corresponds to
9013 * a <schema> element information item in a well-formed information
9014 * set, which in turn corresponds to a valid schema.
9015 * TODO: What to do with the "fragment" stuff?
9016 *
9017 * 2.2 The referent is a <schema> element information item in
9018 * a well-formed information set, which in turn corresponds
9019 * to a valid schema.
9020 * NOTE: 2.2 won't apply, since only XML documents will be processed
9021 * here.
9022 */
9023 if (*doc == NULL) {
9024 xmlErrorPtr lerr;
9025 /*
9026 * It is *not* an error for the application schema reference
9027 * strategy to fail.
9028 *
9029 * If the doc is NULL and the parser error is an IO error we
9030 * will assume that the resource could not be located or accessed.
9031 *
9032 * TODO: Try to find specific error codes to react only on
9033 * localisation failures.
9034 *
9035 * TODO, FIXME: Check the spec: is a namespace added to the imported
9036 * namespaces, even if the schemaLocation did not provide
9037 * a resource? I guess so, since omitting the "schemaLocation"
9038 * attribute, imports a namespace as well.
9039 */
9040 lerr = xmlGetLastError();
9041 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
9042 xmlFreeParserCtxt(parserCtxt);
9043 return(0);
9044 }
9045
9046 xmlSchemaPCustomErr(ctxt,
9047 XML_SCHEMAP_SRC_IMPORT_2_1,
9048 NULL, NULL, node,
9049 "Failed to parse the resource '%s' for import",
9050 location);
9051 xmlFreeParserCtxt(parserCtxt);
9052 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9053 }
9054 xmlFreeParserCtxt(parserCtxt);
9055
9056 root = xmlDocGetRootElement(*doc);
9057 if (root == NULL) {
9058 xmlSchemaPCustomErr(ctxt,
9059 XML_SCHEMAP_SRC_IMPORT_2_1,
9060 NULL, NULL, node,
9061 "The XML document '%s' to be imported has no document "
9062 "element", location);
9063 xmlFreeDoc(*doc);
9064 *doc = NULL;
9065 return (XML_SCHEMAP_SRC_IMPORT_2_1);
9066 }
9067
9068 xmlSchemaCleanupDoc(ctxt, root);
9069
9070 if (!IS_SCHEMA(root, "schema")) {
9071 xmlSchemaPCustomErr(ctxt,
9072 XML_SCHEMAP_SRC_IMPORT_2_1,
9073 NULL, NULL, node,
9074 "The XML document '%s' to be imported is not a XML schema document",
9075 location);
9076 xmlFreeDoc(*doc);
9077 *doc = NULL;
9078 return (XML_SCHEMAP_SRC_IMPORT_2_1);
9079 }
9080 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
9081 /*
9082 * Schema Representation Constraint: Import Constraints and Semantics
9083 */
9084 if (nsName == NULL) {
9085 if (*targetNamespace != NULL) {
9086 xmlSchemaPCustomErr(ctxt,
9087 XML_SCHEMAP_SRC_IMPORT_3_2,
9088 NULL, NULL, node,
9089 "The XML schema to be imported is not expected "
9090 "to have a target namespace; this differs from "
9091 "its target namespace of '%s'", *targetNamespace);
9092 xmlFreeDoc(*doc);
9093 *doc = NULL;
9094 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9095 }
9096 } else {
9097 if (*targetNamespace == NULL) {
9098 xmlSchemaPCustomErr(ctxt,
9099 XML_SCHEMAP_SRC_IMPORT_3_1,
9100 NULL, NULL, node,
9101 "The XML schema to be imported is expected to have a target "
9102 "namespace of '%s'", nsName);
9103 xmlFreeDoc(*doc);
9104 *doc = NULL;
9105 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9106 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
9107 xmlSchemaPCustomErrExt(ctxt,
9108 XML_SCHEMAP_SRC_IMPORT_3_1,
9109 NULL, NULL, node,
9110 "The XML schema to be imported is expected to have a "
9111 "target namespace of '%s'; this differs from "
9112 "its target namespace of '%s'",
9113 nsName, *targetNamespace, NULL);
9114 xmlFreeDoc(*doc);
9115 *doc = NULL;
9116 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9117 }
9118 }
9119
9120 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
9121 if (import == NULL) {
9122 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9123 NULL, NULL, NULL,
9124 "Internal error: xmlSchemaAcquireSchemaDoc, "
9125 "failed to build import table", NULL);
9126 xmlFreeDoc(*doc);
9127 *doc = NULL;
9128 return (-1);
9129 }
9130 import->schemaLocation = location;
9131 import->doc = *doc;
9132 return (0);
9133}
William M. Brack2f2a6632004-08-20 23:09:47 +00009134
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009135static void
9136xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9137 xmlSchemaPtr schema,
9138 const xmlChar *targetNamespace,
9139 xmlNodePtr node)
9140{
9141 const xmlChar *oldURL, **oldLocImps, *oldTNS;
9142 int oldFlags, oldNumLocImps, oldSizeLocImps;
9143
9144 /*
9145 * Save and reset the context & schema.
9146 */
9147 oldURL = pctxt->URL;
9148 /* TODO: Is using the doc->URL here correct? */
9149 pctxt->URL = node->doc->URL;
9150 oldLocImps = pctxt->localImports;
9151 pctxt->localImports = NULL;
9152 oldNumLocImps = pctxt->nbLocalImports;
9153 pctxt->nbLocalImports = 0;
9154 oldSizeLocImps = pctxt->sizeLocalImports;
9155 pctxt->sizeLocalImports = 0;
9156 oldFlags = schema->flags;
9157 xmlSchemaClearSchemaDefaults(schema);
9158 oldTNS = schema->targetNamespace;
9159 schema->targetNamespace = targetNamespace;
9160 /*
9161 * Parse the schema.
9162 */
9163 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9164 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9165 /*
9166 * Restore the context & schema.
9167 */
9168 schema->flags = oldFlags;
9169 schema->targetNamespace = oldTNS;
9170 if (pctxt->localImports != NULL)
9171 xmlFree((xmlChar *) pctxt->localImports);
9172 pctxt->localImports = oldLocImps;
9173 pctxt->nbLocalImports = oldNumLocImps;
9174 pctxt->sizeLocalImports = oldSizeLocImps;
9175 pctxt->URL = oldURL;
9176}
9177
William M. Brack2f2a6632004-08-20 23:09:47 +00009178/**
9179 * xmlSchemaParseImport:
9180 * @ctxt: a schema validation context
9181 * @schema: the schema being built
9182 * @node: a subtree containing XML Schema informations
9183 *
9184 * parse a XML schema Import definition
9185 * *WARNING* this interface is highly subject to change
9186 *
9187 * Returns 0 in case of success, a positive error code if
9188 * not valid and -1 in case of an internal error.
9189 */
9190static int
9191xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9192 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009193{
9194 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009195 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009196 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009197 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009198 xmlAttrPtr attr;
9199 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009200 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009201
9202 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9203 return (-1);
9204
9205 /*
9206 * Check for illegal attributes.
9207 */
9208 attr = node->properties;
9209 while (attr != NULL) {
9210 if (attr->ns == NULL) {
9211 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9212 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9213 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9214 xmlSchemaPIllegalAttrErr(ctxt,
9215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9216 NULL, NULL, attr);
9217 }
9218 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9219 xmlSchemaPIllegalAttrErr(ctxt,
9220 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9221 NULL, NULL, attr);
9222 }
9223 attr = attr->next;
9224 }
9225 /*
9226 * Extract and validate attributes.
9227 */
9228 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9229 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009230 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009231 xmlSchemaPSimpleTypeErr(ctxt,
9232 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9233 NULL, NULL, node,
9234 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009235 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009236 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9237 }
9238
9239 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9240 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9241 &schemaLocation) != 0) {
9242 xmlSchemaPSimpleTypeErr(ctxt,
9243 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9244 NULL, NULL, node,
9245 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009246 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009247 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
9248 }
9249 /*
9250 * And now for the children...
9251 */
9252 child = node->children;
9253 if (IS_SCHEMA(child, "annotation")) {
9254 /*
9255 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009256 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009257 */
9258 child = child->next;
9259 }
9260 if (child != NULL) {
9261 xmlSchemaPContentErr(ctxt,
9262 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9263 NULL, NULL, node, child, NULL,
9264 "(annotation?)");
9265 }
9266 /*
9267 * Apply additional constraints.
9268 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009269 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009270 /*
9271 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9272 * must not match the ·actual value· of the enclosing <schema>'s
9273 * targetNamespace [attribute].
9274 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009275 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009276 xmlSchemaPCustomErr(ctxt,
9277 XML_SCHEMAP_SRC_IMPORT_1_1,
9278 NULL, NULL, node,
9279 "The value of the attribute 'namespace' must not match "
9280 "the target namespace '%s' of the importing schema",
9281 schema->targetNamespace);
9282 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9283 }
9284 } else {
9285 /*
9286 * 1.2 If the namespace [attribute] is not present, then the enclosing
9287 * <schema> must have a targetNamespace [attribute].
9288 */
9289 if (schema->targetNamespace == NULL) {
9290 xmlSchemaPCustomErr(ctxt,
9291 XML_SCHEMAP_SRC_IMPORT_1_2,
9292 NULL, NULL, node,
9293 "The attribute 'namespace' must be existent if "
9294 "the importing schema has no target namespace",
9295 NULL);
9296 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9297 }
9298 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009299 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009300 * Add the namespace to the list of locally imported namespace.
9301 */
9302 if (ctxt->localImports == NULL) {
9303 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
9304 sizeof(const xmlChar*));
9305 ctxt->sizeLocalImports = 10;
9306 ctxt->nbLocalImports = 0;
9307 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9308 ctxt->sizeLocalImports *= 2;
9309 ctxt->localImports = (const xmlChar **) xmlRealloc(
9310 (xmlChar **) ctxt->localImports,
9311 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9312 }
9313 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9314 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009315 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009316 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009317 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009318 schemaLocation, &doc, &targetNamespace, 0);
9319 if (ret != 0) {
9320 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009321 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009322 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009323 } else if (doc != NULL) {
9324 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9325 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009326 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009327
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009328 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009329}
9330
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009331/**
9332 * xmlSchemaParseInclude:
9333 * @ctxt: a schema validation context
9334 * @schema: the schema being built
9335 * @node: a subtree containing XML Schema informations
9336 *
9337 * parse a XML schema Include definition
9338 *
William M. Bracke7091952004-05-11 15:09:58 +00009339 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009340 * 1 in case of success.
9341 */
9342static int
9343xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9344 xmlNodePtr node)
9345{
9346 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009347 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009348 xmlDocPtr doc = NULL;
9349 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009350 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009351 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009352 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009353 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009354
9355
9356 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9357 return (-1);
9358
9359 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009360 * Check for illegal attributes.
9361 */
9362 attr = node->properties;
9363 while (attr != NULL) {
9364 if (attr->ns == NULL) {
9365 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9366 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9367 xmlSchemaPIllegalAttrErr(ctxt,
9368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9369 NULL, NULL, attr);
9370 }
9371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9372 xmlSchemaPIllegalAttrErr(ctxt,
9373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9374 NULL, NULL, attr);
9375 }
9376 attr = attr->next;
9377 }
9378 /*
9379 * Extract and validate attributes.
9380 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009381 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009382 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009383 * Preliminary step, extract the URI-Reference for the include and
9384 * make an URI from the base.
9385 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009386 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9387 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009388 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009389 xmlChar *uri = NULL;
9390
9391 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9392 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009393 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009394 base = xmlNodeGetBase(node->doc, node);
9395 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009396 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009397 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009398 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009399 xmlFree(base);
9400 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009401 if (uri == NULL) {
9402 xmlSchemaPErr(ctxt,
9403 node,
9404 XML_SCHEMAP_INTERNAL,
9405 "Internal error: xmlSchemaParseInclude, "
9406 "could not build an URI from the schemaLocation.\n",
9407 NULL, NULL);
9408 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009409 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009410 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9411 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009412 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009413 xmlSchemaPMissingAttrErr(ctxt,
9414 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9415 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009416 goto exit_invalid;
9417 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009418 /*
9419 * And now for the children...
9420 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009421 child = node->children;
9422 while (IS_SCHEMA(child, "annotation")) {
9423 /*
9424 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009425 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009426 */
9427 child = child->next;
9428 }
9429 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009430 xmlSchemaPContentErr(ctxt,
9431 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9432 NULL, NULL, node, child, NULL,
9433 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009434 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009435 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009436 * Report self-inclusion.
9437 */
9438 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9439 xmlSchemaPCustomErr(ctxt,
9440 XML_SCHEMAP_SRC_INCLUDE,
9441 NULL, NULL, node,
9442 "The schema document '%s' cannot include itself.",
9443 schemaLocation);
9444 return (XML_SCHEMAP_SRC_INCLUDE);
9445 }
9446 /*
9447 * Check if this one was already processed to avoid incorrect
9448 * duplicate component errors and infinite circular inclusion.
9449 */
9450 include = schema->includes;
9451 while (include != NULL) {
9452 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9453 targetNamespace = include->origTargetNamespace;
9454 if (targetNamespace == NULL) {
9455 /*
9456 * Chameleon include: skip only if it was build for
9457 * the targetNamespace of the including schema.
9458 */
9459 if (xmlStrEqual(schema->targetNamespace,
9460 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009461 goto check_targetNamespace;
9462 }
9463 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009464 goto check_targetNamespace;
9465 }
9466 }
9467 include = include->next;
9468 }
9469 /*
9470 * First step is to parse the input document into an DOM/Infoset
9471 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009472 */
9473 parserCtxt = xmlNewParserCtxt();
9474 if (parserCtxt == NULL) {
9475 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9476 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009477 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009478 }
9479
9480 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9481 xmlDictFree(parserCtxt->dict);
9482 parserCtxt->dict = ctxt->dict;
9483 xmlDictReference(parserCtxt->dict);
9484 }
9485
9486 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
9487 NULL, SCHEMAS_PARSE_OPTIONS);
9488 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009489 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009490 /*
9491 * TODO: It is not an error for the ·actual value· of the
9492 * schemaLocation [attribute] to fail to resolve it all, in which
9493 * case no corresponding inclusion is performed.
9494 * So do we need a warning report here?
9495 */
9496 xmlSchemaPCustomErr(ctxt,
9497 XML_SCHEMAP_FAILED_LOAD,
9498 NULL, NULL, node,
9499 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009501 }
9502
9503 /*
9504 * Then extract the root of the schema
9505 */
9506 root = xmlDocGetRootElement(doc);
9507 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009508 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009510 NULL, NULL, node,
9511 "The included document '%s' has no document "
9512 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009513 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009514 }
9515
9516 /*
9517 * Remove all the blank text nodes
9518 */
9519 xmlSchemaCleanupDoc(ctxt, root);
9520
9521 /*
9522 * Check the schemas top level element
9523 */
9524 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009525 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009526 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009527 NULL, NULL, node,
9528 "The document '%s' to be included is not a schema document",
9529 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009530 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009531 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009532
William M. Brack2f2a6632004-08-20 23:09:47 +00009533 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009534 /*
9535 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9536 * value· is identical to the ·actual value· of the targetNamespace
9537 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9538 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009539check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009540 if (targetNamespace != NULL) {
9541 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009542 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009543 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009544 NULL, NULL, node,
9545 "The target namespace of the included schema "
9546 "'%s' has to be absent, since the including schema "
9547 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009548 schemaLocation);
9549 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009550 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9551 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009552 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009553 NULL, NULL, node,
9554 "The target namespace '%s' of the included schema '%s' "
9555 "differs from '%s' of the including schema",
9556 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009557 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009558 }
9559 } else if (schema->targetNamespace != NULL) {
9560 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
9561 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
9562 } else
9563 wasConvertingNs = 1;
9564 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009565
9566 if (include != NULL)
9567 goto exit;
9568
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009569 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009570 * URGENT TODO: If the schema is a chameleon-include then copy the
9571 * components into the including schema and modify the targetNamespace
9572 * of those components, do nothing otherwise.
9573 * NOTE: This is currently worked-around by compiling the chameleon
9574 * for every destinct including targetNamespace; thus not performant at
9575 * the moment.
9576 * TODO: Check when the namespace in wildcards for chameleons needs
9577 * to be converted: before we built wildcard intersections or after.
9578 */
9579 /*
9580 * Register the include.
9581 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009582 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9583 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009584 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9585 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009586 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009587 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009588 include->next = schema->includes;
9589 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009590 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009591 * TODO: Use the resolved URI for the this location, since it might
9592 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009593 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009594 include->schemaLocation = schemaLocation;
9595 include->doc = doc;
9596 /*
9597 * In case of chameleons, the original target namespace will differ
9598 * from the resulting namespace.
9599 */
9600 include->origTargetNamespace = targetNamespace;
9601 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009602#ifdef DEBUG_INCLUDES
9603 if (targetNamespace != schema->targetNamespace)
9604 xmlGenericError(xmlGenericErrorContext,
9605 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9606 " into TNS '%s'\n", schemaLocation,
9607 targetNamespace, schema->targetNamespace);
9608 else
9609 xmlGenericError(xmlGenericErrorContext,
9610 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9611 targetNamespace);
9612#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009613 /*
9614 * Compile the included schema.
9615 */
9616 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9617
9618exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009619 /*
9620 * Remove the converting flag.
9621 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009622 if ((wasConvertingNs == 0) &&
9623 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009624 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009625 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009626
9627exit_invalid:
9628 if (doc != NULL) {
9629 if (include != NULL)
9630 include->doc = NULL;
9631 xmlFreeDoc(doc);
9632 }
9633 return (ctxt->err);
9634
9635exit_failure:
9636 if (doc != NULL) {
9637 if (include != NULL)
9638 include->doc = NULL;
9639 xmlFreeDoc(doc);
9640 }
9641 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009642}
9643
9644/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009645 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009646 * @ctxt: a schema validation context
9647 * @schema: the schema being built
9648 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 * @type: the "compositor" type
9650 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009651 *
9652 * parse a XML schema Sequence definition
9653 * *WARNING* this interface is highly subject to change
9654 *
William M. Bracke7091952004-05-11 15:09:58 +00009655 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009656 * 1 in case of success.
9657 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009658static xmlSchemaTreeItemPtr
9659xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9660 xmlNodePtr node, xmlSchemaTypeType type,
9661 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009662{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009663 xmlSchemaModelGroupPtr item;
9664 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009665 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009666 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009667 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009668 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009669
9670 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009671 return (NULL);
9672 /*
9673 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009674 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009675 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9676 if (item == NULL)
9677 return (NULL);
9678
9679 if (withParticle) {
9680 if (type == XML_SCHEMA_TYPE_ALL) {
9681 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
9682 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
9683 } else {
9684 /* choice + sequence */
9685 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
9686 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9687 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009688 }
9689 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009690 /*
9691 * Create a particle
9692 */
9693 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9694 if (particle == NULL)
9695 return (NULL);
9696 particle->children = (xmlSchemaTreeItemPtr) item;
9697 /*
9698 * Check for illegal attributes.
9699 */
9700 attr = node->properties;
9701 while (attr != NULL) {
9702 if (attr->ns == NULL) {
9703 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9704 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9705 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
9706 xmlSchemaPIllegalAttrErr(ctxt,
9707 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9708 NULL, NULL, attr);
9709 }
9710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009711 xmlSchemaPIllegalAttrErr(ctxt,
9712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009713 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009714 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009715 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009716 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009717 } else {
9718 /*
9719 * Check for illegal attributes.
9720 */
9721 attr = node->properties;
9722 while (attr != NULL) {
9723 if (attr->ns == NULL) {
9724 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9725 xmlSchemaPIllegalAttrErr(ctxt,
9726 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9727 NULL, NULL, attr);
9728 }
9729 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9730 xmlSchemaPIllegalAttrErr(ctxt,
9731 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9732 NULL, NULL, attr);
9733 }
9734 attr = attr->next;
9735 }
9736
William M. Brack2f2a6632004-08-20 23:09:47 +00009737 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009738
William M. Brack2f2a6632004-08-20 23:09:47 +00009739 /*
9740 * Extract and validate attributes.
9741 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009742 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009743 /*
9744 * And now for the children...
9745 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009746 child = node->children;
9747 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009748 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009749 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009750 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009751 oldcontainer = ctxt->container;
9752 ctxt->container = container;
9753 if (type == XML_SCHEMA_TYPE_ALL) {
9754 xmlSchemaParticlePtr part, last = NULL;
9755
9756 while (IS_SCHEMA(child, "element")) {
9757 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9758 schema, child, 0);
9759 if (part != NULL) {
9760 if (part->minOccurs > 1)
9761 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
9762 NULL, NULL, child,
9763 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9764 if (part->maxOccurs > 1)
9765 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
9766 NULL, NULL, child,
9767 "Invalid value for maxOccurs (must be 0 or 1)",
9768 NULL);
9769 if (last == NULL)
9770 item->children = (xmlSchemaTreeItemPtr) part;
9771 else
9772 last->next = (xmlSchemaTreeItemPtr) part;
9773 last = part;
9774 }
9775 child = child->next;
9776 }
9777 if (child != NULL) {
9778 xmlSchemaPContentErr(ctxt,
9779 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9780 NULL, NULL, node, child, NULL,
9781 "(annotation?, (annotation?, element*)");
9782 }
9783 } else {
9784 /* choice + sequence */
9785 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9786
9787 while ((IS_SCHEMA(child, "element")) ||
9788 (IS_SCHEMA(child, "group")) ||
9789 (IS_SCHEMA(child, "any")) ||
9790 (IS_SCHEMA(child, "choice")) ||
9791 (IS_SCHEMA(child, "sequence"))) {
9792
9793 if (IS_SCHEMA(child, "element")) {
9794 part = (xmlSchemaTreeItemPtr)
9795 xmlSchemaParseElement(ctxt, schema, child, 0);
9796 } else if (IS_SCHEMA(child, "group")) {
9797 part =
9798 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9799 } else if (IS_SCHEMA(child, "any")) {
9800 part = (xmlSchemaTreeItemPtr)
9801 xmlSchemaParseAny(ctxt, schema, child);
9802 } else if (IS_SCHEMA(child, "choice")) {
9803 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9804 XML_SCHEMA_TYPE_CHOICE, 1);
9805 } else if (IS_SCHEMA(child, "sequence")) {
9806 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9807 XML_SCHEMA_TYPE_SEQUENCE, 1);
9808 }
9809 if (part != NULL) {
9810 if (last == NULL)
9811 item->children = part;
9812 else
9813 last->next = part;
9814 last = part;
9815 }
9816 child = child->next;
9817 }
9818 if (child != NULL) {
9819 xmlSchemaPContentErr(ctxt,
9820 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9821 NULL, NULL, node, child, NULL,
9822 "(annotation?, (element | group | choice | sequence | any)*)");
9823 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009826 if (withParticle) {
9827 if ((min == 0) && (max == 0))
9828 return (NULL);
9829 else
9830 return ((xmlSchemaTreeItemPtr) particle);
9831 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009832 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009833}
9834
9835/**
9836 * xmlSchemaParseRestriction:
9837 * @ctxt: a schema validation context
9838 * @schema: the schema being built
9839 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009840 *
9841 * parse a XML schema Restriction definition
9842 * *WARNING* this interface is highly subject to change
9843 *
9844 * Returns the type definition or NULL in case of error
9845 */
9846static xmlSchemaTypePtr
9847xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009848 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009849{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009850 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009851 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 char buf[30];
9853 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009854 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009855
9856 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9857 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009858 /* Not a component, don't create it. */
9859 type = ctxt->ctxtType;
9860 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
9861
9862 /*
9863 * TODO: Is the container needed at all? the anonymous
9864 * items inside should generate unique names already.
9865 */
9866 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
9867 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009868 /*
9869 * Check for illegal attributes.
9870 */
9871 attr = node->properties;
9872 while (attr != NULL) {
9873 if (attr->ns == NULL) {
9874 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9875 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9876 xmlSchemaPIllegalAttrErr(ctxt,
9877 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009878 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009879 }
9880 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9881 xmlSchemaPIllegalAttrErr(ctxt,
9882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009883 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009884 }
9885 attr = attr->next;
9886 }
9887 /*
9888 * Extract and validate attributes.
9889 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009890 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009891 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009892 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009893 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009894 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009895 NULL, NULL, node, "base",
9896 &(type->baseNs), NULL,
9897 &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009898 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009899 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009900 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 XML_SCHEMAP_S4S_ATTR_MISSING,
William M. Brack2f2a6632004-08-20 23:09:47 +00009902 NULL, type, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009903 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009904 /*
9905 * And now for the children...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009906 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009907 child = node->children;
9908 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009909 /*
9910 * Add the annotation to the simple type ancestor.
9911 */
9912 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9913 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009914 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916 oldcontainer = ctxt->container;
9917 ctxt->container = container;
9918 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9919 /*
9920 * Corresponds to <simpleType><restriction><simpleType>.
9921 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009922 if (IS_SCHEMA(child, "simpleType")) {
9923 if (type->base != NULL) {
9924 /*
9925 * src-restriction-base-or-simpleType
9926 * Either the base [attribute] or the simpleType [child] of the
9927 * <restriction> element must be present, but not both.
9928 */
9929 xmlSchemaPContentErr(ctxt,
9930 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009931 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009932 "The attribute 'base' and the <simpleType> child are "
9933 "mutually exclusive", NULL);
9934 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009935 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009936 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009937 }
9938 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009939 } else if (type->base == NULL) {
9940 xmlSchemaPContentErr(ctxt,
9941 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9942 NULL, NULL, node, child,
9943 "Either the attribute 'base' or a <simpleType> child "
9944 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009945 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009946 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9947 /*
9948 * Corresponds to <complexType><complexContent><restriction>...
9949 * followed by:
9950 *
9951 * Model groups <all>, <choice> and <sequence>.
9952 */
9953 if (IS_SCHEMA(child, "all")) {
9954 type->subtypes = (xmlSchemaTypePtr)
9955 xmlSchemaParseModelGroup(ctxt, schema, child,
9956 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009957 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009958 } else if (IS_SCHEMA(child, "choice")) {
9959 type->subtypes = (xmlSchemaTypePtr)
9960 xmlSchemaParseModelGroup(ctxt,
9961 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9962 child = child->next;
9963 } else if (IS_SCHEMA(child, "sequence")) {
9964 type->subtypes = (xmlSchemaTypePtr)
9965 xmlSchemaParseModelGroup(ctxt, schema, child,
9966 XML_SCHEMA_TYPE_SEQUENCE, 1);
9967 child = child->next;
9968 /*
9969 * Model group reference <group>.
9970 */
9971 } else if (IS_SCHEMA(child, "group")) {
9972 type->subtypes = (xmlSchemaTypePtr)
9973 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9974 child = child->next;
9975 }
9976 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9977 xmlSchemaTypePtr contType, baseType = NULL;
9978 /*
9979 * Corresponds to <complexType><simpleContent><restriction>...
9980 *
9981 * SPEC (content type):
9982 * "1 If the type definition ·resolved· to by the ·actual value· of
9983 * the base [attribute] is a complex type definition whose own
9984 * {content type} is a simple type definition and the <restriction>
9985 * alternative is chosen, then starting from either" ...
9986 *
9987 * "1.1 the simple type definition corresponding to the <simpleType>
9988 * among the [children] of <restriction> if there is one;"
9989 */
9990 if (IS_SCHEMA(child, "simpleType")) {
9991
9992 baseType = (xmlSchemaTypePtr)
9993 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9994 if (baseType == NULL)
9995 return (NULL);
9996 child = child->next;
9997 }
9998 /*
9999 * SPEC
10000 * "... a simple type definition which restricts the simple type
10001 * definition identified in clause 1.1 or clause 1.2 with a set
10002 * of facet components"
10003 *
10004 * Create the anonymous simple type, which will be the content type
10005 * of the complex type.
10006 * Note that we will use the same node as for the <restriction> to
10007 * have it somehow anchored in the schema doc.
10008 */
10009 snprintf(buf, 29, "#scST%d", ctxt->counter++ + 1);
10010 contType = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
10011 container, node);
10012 if (contType == NULL)
10013 return (NULL);
10014 contType->node = node;
10015 contType->type = XML_SCHEMA_TYPE_SIMPLE;
10016 contType->baseType = baseType;
10017 type->contentTypeDef = contType;
William M. Brack2f2a6632004-08-20 23:09:47 +000010018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010019
10020 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
10021 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
10022 xmlSchemaFacetPtr facet, lastfacet = NULL;
10023 xmlSchemaTypePtr facetHolder;
10024
10025 if (parentType == XML_SCHEMA_TYPE_SIMPLE)
10026 facetHolder = type;
10027 else
10028 facetHolder = type->contentTypeDef;
10029 /*
10030 * Corresponds to <complexType><simpleContent><restriction>...
10031 * <simpleType><restriction>...
10032 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010033
Daniel Veillard01fa6152004-06-29 17:04:39 +000010034 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010035 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010036 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010037 /*
10038 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
10039 * Simple Type Definition Schema Representation Constraint:
10040 * *Single Facet Value*
10041 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010042 while ((IS_SCHEMA(child, "minInclusive")) ||
10043 (IS_SCHEMA(child, "minExclusive")) ||
10044 (IS_SCHEMA(child, "maxInclusive")) ||
10045 (IS_SCHEMA(child, "maxExclusive")) ||
10046 (IS_SCHEMA(child, "totalDigits")) ||
10047 (IS_SCHEMA(child, "fractionDigits")) ||
10048 (IS_SCHEMA(child, "pattern")) ||
10049 (IS_SCHEMA(child, "enumeration")) ||
10050 (IS_SCHEMA(child, "whiteSpace")) ||
10051 (IS_SCHEMA(child, "length")) ||
10052 (IS_SCHEMA(child, "maxLength")) ||
10053 (IS_SCHEMA(child, "minLength"))) {
10054 facet = xmlSchemaParseFacet(ctxt, schema, child);
10055 if (facet != NULL) {
10056 if (lastfacet == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010057 facetHolder->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010058 else
10059 lastfacet->next = facet;
10060 lastfacet = facet;
10061 lastfacet->next = NULL;
10062 }
10063 child = child->next;
10064 }
10065 /*
10066 * Create links for derivation and validation.
10067 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010068 if (facetHolder->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010069 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10070
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010071 facet = facetHolder->facets;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010072 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010073 facetLink = (xmlSchemaFacetLinkPtr)
10074 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010075 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010076 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010077 xmlFree(facetLink);
10078 return (NULL);
10079 }
10080 facetLink->facet = facet;
10081 facetLink->next = NULL;
10082 if (lastFacetLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010083 facetHolder->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010084 else
10085 lastFacetLink->next = facetLink;
10086 lastFacetLink = facetLink;
10087 facet = facet->next;
10088 } while (facet != NULL);
10089 }
10090 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010091 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10092 /*
10093 * Attribute uses/declarations.
10094 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010095 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010096 /*
10097 * Attribute wildcard.
10098 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010099 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 type->attributeWildcard =
10101 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010102 child = child->next;
10103 }
10104 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010105 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010106 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010107 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010108 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10109 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010110 "annotation?, (group | all | choice | sequence)?, "
10111 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010112 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010113 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010114 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10115 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010116 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10117 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10118 "length | minLength | maxLength | enumeration | whiteSpace | "
10119 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10120 } else {
10121 /* Simple type */
10122 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010123 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10124 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010125 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10126 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10127 "length | minLength | maxLength | enumeration | whiteSpace | "
10128 "pattern)*))");
10129 }
10130 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010131 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010132 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010133}
10134
10135/**
10136 * xmlSchemaParseExtension:
10137 * @ctxt: a schema validation context
10138 * @schema: the schema being built
10139 * @node: a subtree containing XML Schema informations
10140 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010141 * Parses an <extension>, which is found inside a
10142 * <simpleContent> or <complexContent>.
10143 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010144 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010145 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010146 */
10147static xmlSchemaTypePtr
10148xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010149 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010150{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010151 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010152 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010153 char buf[30];
10154 const xmlChar *oldcontainer, *container;
10155 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010156
10157 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10158 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010159 /* Not a component, don't create it. */
10160 type = ctxt->ctxtType;
10161 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010162
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010163 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10164 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10165 /*
10166 * Check for illegal attributes.
10167 */
10168 attr = node->properties;
10169 while (attr != NULL) {
10170 if (attr->ns == NULL) {
10171 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10172 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
10173 xmlSchemaPIllegalAttrErr(ctxt,
10174 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10175 NULL, NULL, attr);
10176 }
10177 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10178 xmlSchemaPIllegalAttrErr(ctxt,
10179 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10180 NULL, NULL, attr);
10181 }
10182 attr = attr->next;
10183 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010184
10185 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010186
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010187 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010188 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010189 */
10190 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010191 NULL, NULL, node, "base", &(type->baseNs), NULL,
10192 &(type->base)) == 0) && (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010193 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010194 XML_SCHEMAP_S4S_ATTR_MISSING,
10195 NULL, NULL, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010196 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010197 /*
10198 * And now for the children...
10199 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010200 child = node->children;
10201 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010202 /*
10203 * Add the annotation to the type ancestor.
10204 */
10205 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10206 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010207 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010208 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 oldcontainer = ctxt->container;
10210 ctxt->container = container;
10211 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10212 /*
10213 * Corresponds to <complexType><complexContent><extension>... and:
10214 *
10215 * Model groups <all>, <choice>, <sequence> and <group>.
10216 */
10217 if (IS_SCHEMA(child, "all")) {
10218 type->subtypes = (xmlSchemaTypePtr)
10219 xmlSchemaParseModelGroup(ctxt, schema,
10220 child, XML_SCHEMA_TYPE_ALL, 1);
10221 child = child->next;
10222 } else if (IS_SCHEMA(child, "choice")) {
10223 type->subtypes = (xmlSchemaTypePtr)
10224 xmlSchemaParseModelGroup(ctxt, schema,
10225 child, XML_SCHEMA_TYPE_CHOICE, 1);
10226 child = child->next;
10227 } else if (IS_SCHEMA(child, "sequence")) {
10228 type->subtypes = (xmlSchemaTypePtr)
10229 xmlSchemaParseModelGroup(ctxt, schema,
10230 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10231 child = child->next;
10232 } else if (IS_SCHEMA(child, "group")) {
10233 type->subtypes = (xmlSchemaTypePtr)
10234 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10235 child = child->next;
10236 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010237 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010238 if (child != NULL) {
10239 /*
10240 * Attribute uses/declarations.
10241 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010242 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010243 /*
10244 * Attribute wildcard.
10245 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010246 if (IS_SCHEMA(child, "anyAttribute")) {
10247 ctxt->ctxtType->attributeWildcard =
10248 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10249 child = child->next;
10250 }
10251 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010252 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010253 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10254 /* Complex content extension. */
10255 xmlSchemaPContentErr(ctxt,
10256 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10257 NULL, NULL, node, child, NULL,
10258 "(annotation?, ((group | all | choice | sequence)?, "
10259 "((attribute | attributeGroup)*, anyAttribute?)))");
10260 } else {
10261 /* Simple content extension. */
10262 xmlSchemaPContentErr(ctxt,
10263 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10264 NULL, NULL, node, child, NULL,
10265 "(annotation?, ((attribute | attributeGroup)*, "
10266 "anyAttribute?))");
10267 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010268 }
10269 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010270 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010271}
10272
10273/**
10274 * xmlSchemaParseSimpleContent:
10275 * @ctxt: a schema validation context
10276 * @schema: the schema being built
10277 * @node: a subtree containing XML Schema informations
10278 *
10279 * parse a XML schema SimpleContent definition
10280 * *WARNING* this interface is highly subject to change
10281 *
10282 * Returns the type definition or NULL in case of error
10283 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010284static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010285xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10286 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010287{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010288 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010289 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010290 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010291
10292 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010293 return (-1);
10294 /* Not a component, don't create it. */
10295 type = ctxt->ctxtType;
10296 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10297 /*
10298 * Check for illegal attributes.
10299 */
10300 attr = node->properties;
10301 while (attr != NULL) {
10302 if (attr->ns == NULL) {
10303 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
10304 xmlSchemaPIllegalAttrErr(ctxt,
10305 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10306 NULL, NULL, attr);
10307 }
10308 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10309 xmlSchemaPIllegalAttrErr(ctxt,
10310 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10311 NULL, NULL, attr);
10312 }
10313 attr = attr->next;
10314 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010315
10316 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010317
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010318 /*
10319 * And now for the children...
10320 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010321 child = node->children;
10322 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010323 /*
10324 * Add the annotation to the complex type ancestor.
10325 */
10326 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10327 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010328 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010329 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010330 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010331 xmlSchemaParseRestriction(ctxt, schema, child,
10332 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010333 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010334 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010335 xmlSchemaParseExtension(ctxt, schema, child,
10336 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010337 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010338 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010339 if (child != NULL) {
10340 xmlSchemaPContentErr(ctxt,
10341 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10342 NULL, NULL, node, child, NULL,
10343 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010344 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010345 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010346}
10347
10348/**
10349 * xmlSchemaParseComplexContent:
10350 * @ctxt: a schema validation context
10351 * @schema: the schema being built
10352 * @node: a subtree containing XML Schema informations
10353 *
10354 * parse a XML schema ComplexContent definition
10355 * *WARNING* this interface is highly subject to change
10356 *
10357 * Returns the type definition or NULL in case of error
10358 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010359static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010360xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10361 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010362{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010363 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010364 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010365 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010366
10367 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010368 return (-1);
10369 /* Not a component, don't create it. */
10370 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 /*
10372 * Check for illegal attributes.
10373 */
10374 attr = node->properties;
10375 while (attr != NULL) {
10376 if (attr->ns == NULL) {
10377 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10378 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
10379 {
10380 xmlSchemaPIllegalAttrErr(ctxt,
10381 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10382 NULL, NULL, attr);
10383 }
10384 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10385 xmlSchemaPIllegalAttrErr(ctxt,
10386 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10387 NULL, NULL, attr);
10388 }
10389 attr = attr->next;
10390 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010391
10392 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10393
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010394 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010395 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010396 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010397 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10398 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10399 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010401 child = node->children;
10402 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010403 /*
10404 * Add the annotation to the complex type ancestor.
10405 */
10406 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10407 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010408 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010409 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010410 if (IS_SCHEMA(child, "restriction")) {
10411 xmlSchemaParseRestriction(ctxt, schema, child,
10412 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010413 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010414 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010415 xmlSchemaParseExtension(ctxt, schema, child,
10416 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010417 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010418 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010419 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010420 xmlSchemaPContentErr(ctxt,
10421 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10422 NULL, NULL, node, child,
10423 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010425 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010426}
10427
10428/**
10429 * xmlSchemaParseComplexType:
10430 * @ctxt: a schema validation context
10431 * @schema: the schema being built
10432 * @node: a subtree containing XML Schema informations
10433 *
10434 * parse a XML schema Complex Type definition
10435 * *WARNING* this interface is highly subject to change
10436 *
10437 * Returns the type definition or NULL in case of error
10438 */
10439static xmlSchemaTypePtr
10440xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010441 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010442{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010443 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010444 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010445 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010446 xmlAttrPtr attr;
10447 const xmlChar *attrValue;
10448 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010449 char buf[40];
10450
Daniel Veillard4255d502002-04-16 15:50:10 +000010451
10452 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10453 return (NULL);
10454
Daniel Veillard01fa6152004-06-29 17:04:39 +000010455 ctxtType = ctxt->ctxtType;
10456
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010457 if (topLevel) {
10458 attr = xmlSchemaGetPropNode(node, "name");
10459 if (attr == NULL) {
10460 xmlSchemaPMissingAttrErr(ctxt,
10461 XML_SCHEMAP_S4S_ATTR_MISSING,
10462 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
10463 "name", NULL);
10464 return (NULL);
10465 } else if (xmlSchemaPValAttrNode(ctxt,
10466 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
10467 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10468 return (NULL);
10469 }
10470 }
10471
10472 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010473 /*
10474 * Parse as local complex type definition.
10475 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010476 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010477 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10478 if (type == NULL)
10479 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010480 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010481 type->node = node;
10482 type->type = XML_SCHEMA_TYPE_COMPLEX;
10483 /*
10484 * TODO: We need the target namespace.
10485 */
10486 } else {
10487 /*
10488 * Parse as global complex type definition.
10489 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010490 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010491 if (type == NULL)
10492 return (NULL);
10493 type->node = node;
10494 type->type = XML_SCHEMA_TYPE_COMPLEX;
10495 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
10496 /*
10497 * Set defaults.
10498 */
10499 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010500 }
10501 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010502 /*
10503 * Handle attributes.
10504 */
10505 attr = node->properties;
10506 while (attr != NULL) {
10507 if (attr->ns == NULL) {
10508 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10509 /*
10510 * Attribute "id".
10511 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010512 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10513 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010514 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10515 /*
10516 * Attribute "mixed".
10517 */
10518 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10519 (xmlNodePtr) attr))
10520 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10521 } else if (topLevel) {
10522 /*
10523 * Attributes of global complex type definitions.
10524 */
10525 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10526 /* Pass. */
10527 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10528 /*
10529 * Attribute "abstract".
10530 */
10531 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10532 (xmlNodePtr) attr))
10533 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10534 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10535 /*
10536 * Attribute "final".
10537 */
10538 attrValue = xmlSchemaGetNodeContent(ctxt,
10539 (xmlNodePtr) attr);
10540 if (xmlSchemaPValAttrBlockFinal(attrValue,
10541 &(type->flags),
10542 -1,
10543 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10544 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10545 -1, -1, -1) != 0)
10546 {
10547 xmlSchemaPSimpleTypeErr(ctxt,
10548 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10549 &des, type, (xmlNodePtr) attr,
10550 NULL,
10551 "(#all | List of (extension | restriction))",
10552 attrValue, NULL, NULL, NULL);
10553 }
10554 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10555 /*
10556 * Attribute "block".
10557 */
10558 attrValue = xmlSchemaGetNodeContent(ctxt,
10559 (xmlNodePtr) attr);
10560 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
10561 -1,
10562 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
10563 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
10564 -1, -1, -1) != 0) {
10565 xmlSchemaPSimpleTypeErr(ctxt,
10566 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10567 &des, type, (xmlNodePtr) attr,
10568 NULL,
10569 "(#all | List of (extension | restriction)) ",
10570 attrValue, NULL, NULL, NULL);
10571 }
10572 } else {
10573 xmlSchemaPIllegalAttrErr(ctxt,
10574 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10575 &des, type, attr);
10576 }
10577 } else {
10578 xmlSchemaPIllegalAttrErr(ctxt,
10579 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10580 &des, type, attr);
10581 }
10582 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10583 xmlSchemaPIllegalAttrErr(ctxt,
10584 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10585 &des, type, attr);
10586 }
10587 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010588 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010589 if (xmlSchemaGetPropNode(node, "block") == NULL) {
10590 /*
10591 * Apply default "block" values.
10592 */
10593 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10594 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10595 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10596 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10597 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010598 /*
10599 * And now for the children...
10600 */
10601 oldcontainer = ctxt->container;
10602 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010603 child = node->children;
10604 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010605 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10606 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010607 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010608 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010609 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010610 /*
10611 * 3.4.3 : 2.2
10612 * Specifying mixed='true' when the <simpleContent>
10613 * alternative is chosen has no effect
10614 */
William M. Bracke7091952004-05-11 15:09:58 +000010615 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10616 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010617 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010618 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010619 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010620 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10621 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010622 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010623 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010624 /*
10625 * SPEC
10626 * "...the third alternative (neither <simpleContent> nor
10627 * <complexContent>) is chosen. This case is understood as shorthand
10628 * for complex content restricting the ·ur-type definition·, and the
10629 * details of the mappings should be modified as necessary.
10630 */
10631 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10632 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010633 /*
10634 * Parse model groups.
10635 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010636 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010637 type->subtypes = (xmlSchemaTypePtr)
10638 xmlSchemaParseModelGroup(ctxt, schema, child,
10639 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010640 child = child->next;
10641 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010642 type->subtypes = (xmlSchemaTypePtr)
10643 xmlSchemaParseModelGroup(ctxt, schema, child,
10644 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010645 child = child->next;
10646 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010647 type->subtypes = (xmlSchemaTypePtr)
10648 xmlSchemaParseModelGroup(ctxt, schema, child,
10649 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010650 child = child->next;
10651 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010652 type->subtypes = (xmlSchemaTypePtr)
10653 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010654 child = child->next;
10655 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010656 /*
10657 * Parse attribute decls/refs.
10658 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010659 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010660 /*
10661 * Parse attribute wildcard.
10662 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010663 if (IS_SCHEMA(child, "anyAttribute")) {
10664 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10665 child = child->next;
10666 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010667 }
10668 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010669 xmlSchemaPContentErr(ctxt,
10670 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10671 &des, type, node, child,
10672 NULL, "(annotation?, (simpleContent | complexContent | "
10673 "((group | all | choice | sequence)?, ((attribute | "
10674 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010675 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010676 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010677 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010678 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010679 return (type);
10680}
10681
Daniel Veillard4255d502002-04-16 15:50:10 +000010682/**
10683 * xmlSchemaParseSchema:
10684 * @ctxt: a schema validation context
10685 * @node: a subtree containing XML Schema informations
10686 *
10687 * parse a XML schema definition from a node set
10688 * *WARNING* this interface is highly subject to change
10689 *
10690 * Returns the internal XML Schema structure built from the resource or
10691 * NULL in case of error
10692 */
10693static xmlSchemaPtr
10694xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10695{
10696 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010697 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010698 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010699 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010700
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010701 /*
10702 * This one is called by xmlSchemaParse only and is used if
10703 * the schema to be parsed was specified via the API; i.e. not
10704 * automatically by the validated instance document.
10705 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010706 if ((ctxt == NULL) || (node == NULL))
10707 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010708 nberrors = ctxt->nberrors;
10709 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010710 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010711 xmlSchemaImportPtr import;
10712
Daniel Veillard4255d502002-04-16 15:50:10 +000010713 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010714 if (schema == NULL)
10715 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010716 /*
10717 * Disable build of list of items.
10718 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010719 attr = xmlSchemaGetPropNode(node, "targetNamespace");
10720 if (attr != NULL) {
10721 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
10722 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10723 /*
10724 * TODO: Should we proceed with an invalid target namespace?
10725 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010726 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
10727 } else {
10728 schema->targetNamespace = NULL;
10729 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010730 /*
10731 * Add the current ns name and location to the import table;
10732 * this is needed to have a consistent mechanism, regardless
10733 * if all schemata are constructed dynamically fired by the
10734 * instance or if the schema to be used was specified via
10735 * the API.
10736 */
10737 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10738 schema->targetNamespace);
10739 if (import == NULL) {
10740 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10741 NULL, NULL, (xmlNodePtr) ctxt->doc,
10742 "Internal error: xmlSchemaParseSchema, "
10743 "failed to add an import entry", NULL);
10744 xmlSchemaFree(schema);
10745 schema = NULL;
10746 return (NULL);
10747 }
10748 import->schemaLocation = ctxt->URL;
10749 /*
10750 * NOTE: We won't set the doc here, otherwise it will be freed
10751 * if the import struct is freed.
10752 * import->doc = ctxt->doc;
10753 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010754 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010755 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10756 } else {
10757 xmlDocPtr doc;
10758
10759 doc = node->doc;
10760
10761 if ((doc != NULL) && (doc->URL != NULL)) {
10762 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10763 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010764 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010765 } else {
10766 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10767 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010768 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010769 }
10770 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010771 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010772 if (ctxt->nberrors != 0) {
10773 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010774 xmlSchemaFree(schema);
10775 schema = NULL;
10776 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010777 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010778 if (schema != NULL)
10779 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010780 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010781#ifdef DEBUG
10782 if (schema == NULL)
10783 xmlGenericError(xmlGenericErrorContext,
10784 "xmlSchemaParse() failed\n");
10785#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010786 return (schema);
10787}
10788
10789/************************************************************************
10790 * *
10791 * Validating using Schemas *
10792 * *
10793 ************************************************************************/
10794
10795/************************************************************************
10796 * *
10797 * Reading/Writing Schemas *
10798 * *
10799 ************************************************************************/
10800
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010801#if 0 /* Will be enabled if it is clear what options are needed. */
10802/**
10803 * xmlSchemaParserCtxtSetOptions:
10804 * @ctxt: a schema parser context
10805 * @options: a combination of xmlSchemaParserOption
10806 *
10807 * Sets the options to be used during the parse.
10808 *
10809 * Returns 0 in case of success, -1 in case of an
10810 * API error.
10811 */
10812static int
10813xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10814 int options)
10815
10816{
10817 int i;
10818
10819 if (ctxt == NULL)
10820 return (-1);
10821 /*
10822 * WARNING: Change the start value if adding to the
10823 * xmlSchemaParseOption.
10824 */
10825 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10826 if (options & 1<<i) {
10827 return (-1);
10828 }
10829 }
10830 ctxt->options = options;
10831 return (0);
10832}
10833
10834/**
10835 * xmlSchemaValidCtxtGetOptions:
10836 * @ctxt: a schema parser context
10837 *
10838 * Returns the option combination of the parser context.
10839 */
10840static int
10841xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
10842
10843{
10844 if (ctxt == NULL)
10845 return (-1);
10846 else
10847 return (ctxt->options);
10848}
10849
10850 void *curItems; /* used for dynamic addition of schemata */
10851 int nbCurItems; /* used for dynamic addition of schemata */
10852 int sizeCurItems; /* used for dynamic addition of schemata */
10853
10854#endif
10855
Daniel Veillard4255d502002-04-16 15:50:10 +000010856/**
10857 * xmlSchemaNewParserCtxt:
10858 * @URL: the location of the schema
10859 *
10860 * Create an XML Schemas parse context for that file/resource expected
10861 * to contain an XML Schemas file.
10862 *
10863 * Returns the parser context or NULL in case of error
10864 */
10865xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010866xmlSchemaNewParserCtxt(const char *URL)
10867{
Daniel Veillard4255d502002-04-16 15:50:10 +000010868 xmlSchemaParserCtxtPtr ret;
10869
10870 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010871 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010872
10873 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10874 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010875 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010876 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010877 return (NULL);
10878 }
10879 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010880 ret->dict = xmlDictCreate();
10881 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010882 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010883 return (ret);
10884}
10885
10886/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010887 * xmlSchemaNewParserCtxtUseDict:
10888 * @URL: the location of the schema
10889 * @dict: the dictionary to be used
10890 *
10891 * Create an XML Schemas parse context for that file/resource expected
10892 * to contain an XML Schemas file.
10893 *
10894 * Returns the parser context or NULL in case of error
10895 */
10896static xmlSchemaParserCtxtPtr
10897xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10898{
10899 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010900 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010901 if (URL == NULL)
10902 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010903 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010904
10905 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10906 if (ret == NULL) {
10907 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10908 NULL);
10909 return (NULL);
10910 }
10911 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10912 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010913 xmlDictReference(dict);
10914 if (URL != NULL)
10915 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010916 ret->includes = 0;
10917 return (ret);
10918}
10919
10920
10921/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010922 * xmlSchemaNewMemParserCtxt:
10923 * @buffer: a pointer to a char array containing the schemas
10924 * @size: the size of the array
10925 *
10926 * Create an XML Schemas parse context for that memory buffer expected
10927 * to contain an XML Schemas file.
10928 *
10929 * Returns the parser context or NULL in case of error
10930 */
10931xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010932xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10933{
Daniel Veillard6045c902002-10-09 21:13:59 +000010934 xmlSchemaParserCtxtPtr ret;
10935
10936 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010937 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010938
10939 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10940 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010941 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010942 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010943 return (NULL);
10944 }
10945 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10946 ret->buffer = buffer;
10947 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010948 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010949 return (ret);
10950}
10951
10952/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010953 * xmlSchemaNewDocParserCtxt:
10954 * @doc: a preparsed document tree
10955 *
10956 * Create an XML Schemas parse context for that document.
10957 * NB. The document may be modified during the parsing process.
10958 *
10959 * Returns the parser context or NULL in case of error
10960 */
10961xmlSchemaParserCtxtPtr
10962xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10963{
10964 xmlSchemaParserCtxtPtr ret;
10965
10966 if (doc == NULL)
10967 return (NULL);
10968
10969 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10970 if (ret == NULL) {
10971 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10972 NULL);
10973 return (NULL);
10974 }
10975 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10976 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010977 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010978 /* The application has responsibility for the document */
10979 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010980
10981 return (ret);
10982}
10983
10984/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010985 * xmlSchemaFreeParserCtxt:
10986 * @ctxt: the schema parser context
10987 *
10988 * Free the resources associated to the schema parser context
10989 */
10990void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010991xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10992{
Daniel Veillard4255d502002-04-16 15:50:10 +000010993 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010994 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010995 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010996 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010997 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010998 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010999 xmlFree(ctxt->assemble);
11000 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011001 if (ctxt->vctxt != NULL) {
11002 xmlSchemaFreeValidCtxt(ctxt->vctxt);
11003 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000011004 if (ctxt->localImports != NULL)
11005 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011006 if (ctxt->substGroups != NULL)
11007 xmlHashFree(ctxt->substGroups,
11008 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011009 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000011010 xmlFree(ctxt);
11011}
11012
11013/************************************************************************
11014 * *
11015 * Building the content models *
11016 * *
11017 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011018
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011019static void
11020xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011021 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011022{
11023 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011024 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011025 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011026 xmlSchemaSubstGroupPtr substGroup;
11027 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011028
11029 elemDecl = (xmlSchemaElementPtr) particle->children;
11030 /*
11031 * Wrap the substitution group with a CHOICE.
11032 */
11033 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011034 end = xmlAutomataNewState(pctxt->am);
11035 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
11036 if (substGroup == NULL) {
11037 xmlSchemaPErr(pctxt, GET_NODE(particle),
11038 XML_SCHEMAP_INTERNAL,
11039 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
11040 "declaration is marked having a subst. group but none "
11041 "available.\n", elemDecl->name, NULL);
11042 return;
11043 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011044 if (particle->maxOccurs == 1) {
11045 /*
11046 * NOTE that we put the declaration in, even if it's abstract,
11047 */
11048 xmlAutomataNewEpsilon(pctxt->am,
11049 xmlAutomataNewTransition2(pctxt->am,
11050 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011051 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
11052 /*
11053 * Add subst. group members.
11054 */
11055 for (i = 0; i < substGroup->members->nbItems; i++) {
11056 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11057 xmlAutomataNewEpsilon(pctxt->am,
11058 xmlAutomataNewTransition2(pctxt->am,
11059 start, NULL,
11060 member->name, member->targetNamespace, member),
11061 end);
11062 }
11063 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011064 int counter;
11065 xmlAutomataStatePtr hop;
11066 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11067 UNBOUNDED : particle->maxOccurs - 1;
11068 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
11069
11070 counter =
11071 xmlAutomataNewCounter(pctxt->am, minOccurs,
11072 maxOccurs);
11073 hop = xmlAutomataNewState(pctxt->am);
11074
11075 xmlAutomataNewEpsilon(pctxt->am,
11076 xmlAutomataNewTransition2(pctxt->am,
11077 start, NULL,
11078 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011079 hop);
11080 /*
11081 * Add subst. group members.
11082 */
11083 for (i = 0; i < substGroup->members->nbItems; i++) {
11084 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11085 xmlAutomataNewEpsilon(pctxt->am,
11086 xmlAutomataNewTransition2(pctxt->am,
11087 start, NULL,
11088 member->name, member->targetNamespace, member),
11089 hop);
11090 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011091 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11092 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11093 }
11094 if (particle->minOccurs == 0)
11095 xmlAutomataNewEpsilon(pctxt->am, start, end);
11096 pctxt->state = end;
11097}
11098
11099static void
11100xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11101 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011102{
11103 if (((xmlSchemaElementPtr) particle->children)->flags &
11104 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011105 /*
11106 * Substitution groups.
11107 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011108 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011109 } else {
11110 xmlSchemaElementPtr elemDecl;
11111 xmlAutomataStatePtr start;
11112
11113 elemDecl = (xmlSchemaElementPtr) particle->children;
11114
11115 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
11116 return;
11117 if (particle->maxOccurs == 1) {
11118 start = ctxt->state;
11119 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11120 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11121 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
11122 /* Special case. */
11123 start = ctxt->state;
11124 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11125 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11126 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
11127 } else {
11128 int counter;
11129 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11130 UNBOUNDED : particle->maxOccurs - 1;
11131 int minOccurs = particle->minOccurs < 1 ?
11132 0 : particle->minOccurs - 1;
11133
11134 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
11135 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11136 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11137 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11138 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11139 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11140 NULL, counter);
11141 }
11142 if (particle->minOccurs == 0)
11143 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11144 }
11145}
11146
Daniel Veillard4255d502002-04-16 15:50:10 +000011147/**
11148 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011149 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011150 * @particle: the particle component
11151 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011152 *
11153 * Generate the automata sequence needed for that type
11154 */
11155static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
11157 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011158 const xmlChar * name)
11159{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011160 if (particle == NULL) {
11161 xmlSchemaPErr(ctxt, NULL,
11162 XML_SCHEMAP_INTERNAL,
11163 "Internal error: xmlSchemaBuildAContentModel, "
11164 "particle is NULL.\n", NULL, NULL);
11165 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011166 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011167 if (particle->children == NULL) {
11168 xmlSchemaPErr(ctxt, GET_NODE(particle),
11169 XML_SCHEMAP_INTERNAL,
11170 "Internal error: xmlSchemaBuildAContentModel, "
11171 "no term on particle.\n", NULL, NULL);
11172 return;
11173 }
11174
11175 switch (particle->children->type) {
11176 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011177 xmlAutomataStatePtr start, end;
11178 xmlSchemaWildcardPtr wild;
11179 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011180
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011181 wild = (xmlSchemaWildcardPtr) particle->children;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011182
11183 start = ctxt->state;
11184 end = xmlAutomataNewState(ctxt->am);
11185
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011186 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011187 if (wild->any == 1) {
11188 /*
11189 * We need to add both transitions:
11190 *
11191 * 1. the {"*", "*"} for elements in a namespace.
11192 */
11193 ctxt->state =
11194 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011195 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011196 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11197 /*
11198 * 2. the {"*"} for elements in no namespace.
11199 */
11200 ctxt->state =
11201 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011202 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011203 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11204
11205 } else if (wild->nsSet != NULL) {
11206 ns = wild->nsSet;
11207 do {
11208 ctxt->state = start;
11209 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011211 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11212 ns = ns->next;
11213 } while (ns != NULL);
11214
11215 } else if (wild->negNsSet != NULL) {
11216 xmlAutomataStatePtr deadEnd;
11217
11218 deadEnd = xmlAutomataNewState(ctxt->am);
11219 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011220 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011221 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011222 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011223 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11224 }
11225 } else {
11226 int counter;
11227 xmlAutomataStatePtr hop;
11228 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011230 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011231 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011232
11233 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11234 hop = xmlAutomataNewState(ctxt->am);
11235 if (wild->any == 1) {
11236 ctxt->state =
11237 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011239 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11240 ctxt->state =
11241 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011242 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011243 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11244 } else if (wild->nsSet != NULL) {
11245 ns = wild->nsSet;
11246 do {
11247 ctxt->state =
11248 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011250 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11251 ns = ns->next;
11252 } while (ns != NULL);
11253
11254 } else if (wild->negNsSet != NULL) {
11255 xmlAutomataStatePtr deadEnd;
11256
11257 deadEnd = xmlAutomataNewState(ctxt->am);
11258 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011260 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011261 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011262 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11263 }
11264 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11265 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11266 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011267 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011268 xmlAutomataNewEpsilon(ctxt->am, start, end);
11269 }
11270 ctxt->state = end;
11271 break;
11272 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011273 case XML_SCHEMA_TYPE_ELEMENT:
11274 xmlSchemaBuildContentModelForElement(ctxt, particle);
11275 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011277 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011278
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011279 /*
11280 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011281 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011282 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011283 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11284 sub = particle->children->children;
11285 while (sub != NULL) {
11286 xmlSchemaBuildAContentModel(ctxt,
11287 (xmlSchemaParticlePtr) sub, name);
11288 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011289 }
11290 } else {
11291 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011292
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 if (particle->maxOccurs >= UNBOUNDED) {
11294 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011295 xmlAutomataStatePtr tmp;
11296 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011297
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011300 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011301
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011302 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011303 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011305 sub = particle->children->children;
11306 while (sub != NULL) {
11307 xmlSchemaBuildAContentModel(ctxt,
11308 (xmlSchemaParticlePtr) sub, name);
11309 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011310 }
11311 tmp = ctxt->state;
11312 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11313 oldstate, counter);
11314 ctxt->state =
11315 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11316 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011317
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011318 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011319 sub = particle->children->children;
11320 while (sub != NULL) {
11321 xmlSchemaBuildAContentModel(ctxt,
11322 (xmlSchemaParticlePtr) sub, name);
11323 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011324 }
11325 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11326 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011327 if (particle->minOccurs == 0) {
11328 xmlAutomataNewEpsilon(ctxt->am,
11329 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011330 }
11331 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 } else if ((particle->maxOccurs > 1)
11333 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011334 xmlAutomataStatePtr tmp;
11335 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011336
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011337 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011338 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011339 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011340
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011341 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 particle->minOccurs - 1,
11343 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011344
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011345 sub = particle->children->children;
11346 while (sub != NULL) {
11347 xmlSchemaBuildAContentModel(ctxt,
11348 (xmlSchemaParticlePtr) sub, name);
11349 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011350 }
11351 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011352 xmlAutomataNewCountedTrans(ctxt->am,
11353 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011354 ctxt->state =
11355 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11356 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011357 if (particle->minOccurs == 0) {
11358 xmlAutomataNewEpsilon(ctxt->am,
11359 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011361 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 sub = particle->children->children;
11363 while (sub != NULL) {
11364 xmlSchemaBuildAContentModel(ctxt,
11365 (xmlSchemaParticlePtr) sub, name);
11366 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011367 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011368 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011369 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11370 ctxt->state);
11371 }
11372 }
11373 }
11374 break;
11375 }
11376 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011377 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011378 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011379
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011380 start = ctxt->state;
11381 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011382
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011383 /*
11384 * iterate over the subtypes and remerge the end with an
11385 * epsilon transition
11386 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011387 if (particle->maxOccurs == 1) {
11388 sub = particle->children->children;
11389 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011390 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011391 xmlSchemaBuildAContentModel(ctxt,
11392 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011393 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011394 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011395 }
11396 } else {
11397 int counter;
11398 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011399 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11400 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011401 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011402 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011403
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011404 /*
11405 * use a counter to keep track of the number of transtions
11406 * which went through the choice.
11407 */
11408 counter =
11409 xmlAutomataNewCounter(ctxt->am, minOccurs,
11410 maxOccurs);
11411 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011412
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011413 sub = particle->children->children;
11414 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011415 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011416 xmlSchemaBuildAContentModel(ctxt,
11417 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011418 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011419 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011420 }
11421 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11422 counter);
11423 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11424 counter);
11425 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011426 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011427 xmlAutomataNewEpsilon(ctxt->am, start, end);
11428 }
11429 ctxt->state = end;
11430 break;
11431 }
11432 case XML_SCHEMA_TYPE_ALL:{
11433 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011434 xmlSchemaParticlePtr sub;
11435 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011436 int lax;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011437
11438 sub = (xmlSchemaParticlePtr) particle->children->children;
11439 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011440 break;
11441 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011442 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011443 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011444
11445 elemDecl = (xmlSchemaElementPtr) sub->children;
11446 if (elemDecl == NULL) {
11447 xmlSchemaPErr(ctxt, NULL,
11448 XML_SCHEMAP_INTERNAL,
11449 "Internal error: xmlSchemaBuildAContentModel, "
11450 "<element> particle a NULL term.\n", NULL, NULL);
11451 return;
11452 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011453 /*
11454 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011455 * {particles} of the group must be 0 or 1; this is
11456 * already ensured during the parse of the content of
11457 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011458 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011459 if ((sub->minOccurs == 1) &&
11460 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011461 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11462 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011463 elemDecl->name,
11464 elemDecl->targetNamespace,
11465 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011466 } else if ((sub->minOccurs == 0) &&
11467 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011468
11469 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11470 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011471 elemDecl->name,
11472 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011473 0,
11474 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011475 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011476 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011477 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011478 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011479 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011480 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011481 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011482 break;
11483 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011484 default:
11485 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011486 "Internal error: xmlSchemaBuildAContentModel, found "
11487 "unexpected term of type %d in content model of complex "
11488 "type '%s'.\n",
11489 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011490 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011491 }
11492}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011493
Daniel Veillard4255d502002-04-16 15:50:10 +000011494/**
11495 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011496 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011497 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011498 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011499 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011500 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011501 */
11502static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011503xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011504 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011505 const xmlChar * name)
11506{
Daniel Veillard4255d502002-04-16 15:50:10 +000011507 xmlAutomataStatePtr start;
11508
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011509 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11510 (type->contModel != NULL) ||
11511 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11512 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011513 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011514
11515#ifdef DEBUG_CONTENT
11516 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011517 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011518#endif
11519
Daniel Veillard4255d502002-04-16 15:50:10 +000011520 ctxt->am = xmlNewAutomata();
11521 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011522 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011523 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011524 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011525 }
11526 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011527 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011528 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011529 type->contModel = xmlAutomataCompile(ctxt->am);
11530 if (type->contModel == NULL) {
11531 xmlSchemaPCustomErr(ctxt,
11532 XML_SCHEMAP_INTERNAL,
11533 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011534 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011535 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011536 xmlSchemaPCustomErr(ctxt,
11537 XML_SCHEMAP_NOT_DETERMINISTIC,
11538 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011539 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011540 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011541 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011542#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011543 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011544 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011545 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011546#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011547 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011548 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011549 xmlFreeAutomata(ctxt->am);
11550 ctxt->am = NULL;
11551}
11552
11553/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011554 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011555 * @elem: the schema element context
11556 * @ctxt: the schema parser context
11557 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011558 * Resolves the references of an element declaration
11559 * or particle, which has an element declaration as it's
11560 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011561 */
11562static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011563xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011564 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011565 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011566 const xmlChar * context ATTRIBUTE_UNUSED,
11567 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011568{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011569 if ((ctxt == NULL) || (elemDecl == NULL) ||
11570 ((elemDecl != NULL) && (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011571 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011572 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011574 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011575 xmlSchemaTypePtr type;
11576
11577 /* (type definition) ... otherwise the type definition ·resolved·
11578 * to by the ·actual value· of the type [attribute] ...
11579 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011580 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
11581 elemDecl->namedTypeNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011582 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011583 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011584 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011585 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
11586 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587 XML_SCHEMA_TYPE_BASIC, "type definition");
11588 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011589 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011591 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011592 xmlSchemaElementPtr substHead;
11593
Daniel Veillardc0826a72004-08-10 14:17:33 +000011594 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011595 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
11596 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011598 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11599 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011600 if (substHead == NULL) {
11601 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011602 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011603 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
11604 "substitutionGroup", elemDecl->substGroup,
11605 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011606 } else {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011607 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011608 /*
11609 * Set the "substitution group affiliation".
11610 * NOTE that now we use the "refDecl" field for this.
11611 */
11612 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011613 /*
11614 * (type definition)...otherwise the {type definition} of the
11615 * element declaration ·resolved· to by the ·actual value· of
11616 * the substitutionGroup [attribute], if present
11617 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011618 if (elemDecl->subtypes == NULL)
11619 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011620 }
11621 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011622 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11623 (elemDecl->substGroup == NULL))
11624 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011625}
11626
11627/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011628 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011629 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011630 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011631 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011632 * Checks and builds the "member type definitions" property of the union
11633 * simple type. This handles part (1), part (2) is done in
11634 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11635 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011636 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011637 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011638static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011639xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11640 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011641{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011642
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011643 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011644 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011645
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011646 /*
11647 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Daniel Veillard01fa6152004-06-29 17:04:39 +000011648 * define the explicit members as the type definitions ·resolved·
11649 * to by the items in the ·actual value· of the memberTypes [attribute],
11650 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011651 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011652 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011653 /*
11654 * Resolve references.
11655 */
11656 link = type->memberTypes;
11657 lastLink = NULL;
11658 while (link != NULL) {
11659 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011660
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011661 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11662 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11663
11664 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11665 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11666 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
11667 NULL, type, type->node, "memberTypes",
11668 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11669 /*
11670 * Remove the member type link.
11671 */
11672 if (lastLink == NULL)
11673 type->memberTypes = link->next;
11674 else
11675 lastLink->next = link->next;
11676 newLink = link;
11677 link = link->next;
11678 xmlFree(newLink);
11679 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011680 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011681 lastLink = link;
11682 link = link->next;
11683 }
11684 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011685 /*
11686 * Add local simple types,
11687 */
11688 memberType = type->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011689 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011690 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11691 if (link == NULL) {
11692 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11693 return (-1);
11694 }
11695 link->type = memberType;
11696 link->next = NULL;
11697 if (lastLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011698 type->memberTypes = link;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 else
11700 lastLink->next = link;
11701 lastLink = link;
11702 memberType = memberType->next;
11703 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011704 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011705}
11706
Daniel Veillard4255d502002-04-16 15:50:10 +000011707/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011708 * xmlSchemaIsDerivedFromBuiltInType:
11709 * @ctxt: the schema parser context
11710 * @type: the type definition
11711 * @valType: the value type
11712 *
11713 *
11714 * Returns 1 if the type has the given value type, or
11715 * is derived from such a type.
11716 */
William M. Brack803812b2004-06-03 02:11:24 +000011717static int
Daniel Veillard3646d642004-06-02 19:19:14 +000011718xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
11719 xmlSchemaTypePtr type, int valType)
11720{
11721 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011722 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011723 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011724 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011725 return(1);
11726 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
11727 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
11728 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
11729 ((xmlSchemaAttributePtr) type)->subtypes, valType));
11730 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
11731 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
11732 if (type->baseType != NULL)
11733 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
11734 valType));
11735 } else if ((type->subtypes != NULL) &&
11736 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
11737 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11738 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
11739 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
11740 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
11741 valType));
11742 }
11743
11744 return (0);
11745}
11746
11747/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011748 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011749 * @type: the simpleType definition
11750 *
11751 * Returns the primitive type of the given type or
11752 * NULL in case of error.
11753 */
11754static xmlSchemaTypePtr
11755xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11756{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011757
Daniel Veillard01fa6152004-06-29 17:04:39 +000011758 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011759 /*
11760 * Note that anySimpleType is actually not a primitive type
11761 * but we need that here.
11762 */
11763 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11764 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011765 return (type);
11766 type = type->baseType;
11767 }
11768
11769 return (NULL);
11770}
11771
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011772#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011773/**
11774 * xmlSchemaGetBuiltInTypeAncestor:
11775 * @type: the simpleType definition
11776 *
11777 * Returns the primitive type of the given type or
11778 * NULL in case of error.
11779 */
11780static xmlSchemaTypePtr
11781xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11782{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011783 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11784 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
11785 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011786 while (type != NULL) {
11787 if (type->type == XML_SCHEMA_TYPE_BASIC)
11788 return (type);
11789 type = type->baseType;
11790 }
11791
11792 return (NULL);
11793}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011794#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011795
Daniel Veillard01fa6152004-06-29 17:04:39 +000011796/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011797 * xmlSchemaBuildAttributeUsesOwned:
11798 * @ctxt: the schema parser context
11799 * @type: the complex type definition
11800 * @cur: the attribute declaration list
11801 * @lastUse: the top of the attribute use list
11802 *
11803 * Builds the attribute uses list on the given complex type.
11804 * This one is supposed to be called by
11805 * xmlSchemaBuildAttributeValidation only.
11806 */
11807static int
11808xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
11809 xmlSchemaAttributePtr cur,
11810 xmlSchemaAttributeLinkPtr *uses,
11811 xmlSchemaAttributeLinkPtr *lastUse)
11812{
11813 xmlSchemaAttributeLinkPtr tmp;
11814 while (cur != NULL) {
11815 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11816 /*
11817 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11818 * to by the ·actual value·s of the ref [attribute] of the
11819 * <attributeGroup> [children], if any."
11820 */
11821 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11822 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
11823 lastUse) == -1) {
11824 return (-1);
11825 }
11826 } else {
11827 /* W3C: "1 The set of attribute uses corresponding to the
11828 * <attribute> [children], if any."
11829 */
11830 tmp = (xmlSchemaAttributeLinkPtr)
11831 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11832 if (tmp == NULL) {
11833 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11834 return (-1);
11835 }
11836 tmp->attr = cur;
11837 tmp->next = NULL;
11838 if (*uses == NULL)
11839 *uses = tmp;
11840 else
11841 (*lastUse)->next = tmp;
11842 *lastUse = tmp;
11843 }
11844 cur = cur->next;
11845 }
11846 return (0);
11847}
11848
Daniel Veillard50355f02004-06-08 17:52:16 +000011849/**
11850 * xmlSchemaCloneWildcardNsConstraints:
11851 * @ctxt: the schema parser context
11852 * @dest: the destination wildcard
11853 * @source: the source wildcard
11854 *
11855 * Clones the namespace constraints of source
11856 * and assignes them to dest.
11857 * Returns -1 on internal error, 0 otherwise.
11858 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011859static int
11860xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11861 xmlSchemaWildcardPtr *dest,
11862 xmlSchemaWildcardPtr source)
11863{
11864 xmlSchemaWildcardNsPtr cur, tmp, last;
11865
11866 if ((source == NULL) || (*dest == NULL))
11867 return(-1);
11868 (*dest)->any = source->any;
11869 cur = source->nsSet;
11870 last = NULL;
11871 while (cur != NULL) {
11872 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11873 if (tmp == NULL)
11874 return(-1);
11875 tmp->value = cur->value;
11876 if (last == NULL)
11877 (*dest)->nsSet = tmp;
11878 else
11879 last->next = tmp;
11880 last = tmp;
11881 cur = cur->next;
11882 }
11883 if ((*dest)->negNsSet != NULL)
11884 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
11885 if (source->negNsSet != NULL) {
11886 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11887 if ((*dest)->negNsSet == NULL)
11888 return(-1);
11889 (*dest)->negNsSet->value = source->negNsSet->value;
11890 } else
11891 (*dest)->negNsSet = NULL;
11892 return(0);
11893}
11894
Daniel Veillard50355f02004-06-08 17:52:16 +000011895/**
11896 * xmlSchemaUnionWildcards:
11897 * @ctxt: the schema parser context
11898 * @completeWild: the first wildcard
11899 * @curWild: the second wildcard
11900 *
11901 * Unions the namespace constraints of the given wildcards.
11902 * @completeWild will hold the resulting union.
11903 * Returns a positive error code on failure, -1 in case of an
11904 * internal error, 0 otherwise.
11905 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011906static int
11907xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11908 xmlSchemaWildcardPtr completeWild,
11909 xmlSchemaWildcardPtr curWild)
11910{
11911 xmlSchemaWildcardNsPtr cur, curB, tmp;
11912
11913 /*
11914 * 1 If O1 and O2 are the same value, then that value must be the
11915 * value.
11916 */
11917 if ((completeWild->any == curWild->any) &&
11918 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11919 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11920
11921 if ((completeWild->negNsSet == NULL) ||
11922 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11923
11924 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011925 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011926
11927 /*
11928 * Check equality of sets.
11929 */
11930 cur = completeWild->nsSet;
11931 while (cur != NULL) {
11932 found = 0;
11933 curB = curWild->nsSet;
11934 while (curB != NULL) {
11935 if (cur->value == curB->value) {
11936 found = 1;
11937 break;
11938 }
11939 curB = curB->next;
11940 }
11941 if (!found)
11942 break;
11943 cur = cur->next;
11944 }
11945 if (found)
11946 return(0);
11947 } else
11948 return(0);
11949 }
11950 }
11951 /*
11952 * 2 If either O1 or O2 is any, then any must be the value
11953 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011954 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011955 if (completeWild->any == 0) {
11956 completeWild->any = 1;
11957 if (completeWild->nsSet != NULL) {
11958 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11959 completeWild->nsSet = NULL;
11960 }
11961 if (completeWild->negNsSet != NULL) {
11962 xmlFree(completeWild->negNsSet);
11963 completeWild->negNsSet = NULL;
11964 }
11965 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011966 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 }
11968 /*
11969 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11970 * then the union of those sets must be the value.
11971 */
11972 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11973 int found;
11974 xmlSchemaWildcardNsPtr start;
11975
11976 cur = curWild->nsSet;
11977 start = completeWild->nsSet;
11978 while (cur != NULL) {
11979 found = 0;
11980 curB = start;
11981 while (curB != NULL) {
11982 if (cur->value == curB->value) {
11983 found = 1;
11984 break;
11985 }
11986 curB = curB->next;
11987 }
11988 if (!found) {
11989 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11990 if (tmp == NULL)
11991 return (-1);
11992 tmp->value = cur->value;
11993 tmp->next = completeWild->nsSet;
11994 completeWild->nsSet = tmp;
11995 }
11996 cur = cur->next;
11997 }
11998
11999 return(0);
12000 }
12001 /*
12002 * 4 If the two are negations of different values (namespace names
12003 * or ·absent·), then a pair of not and ·absent· must be the value.
12004 */
12005 if ((completeWild->negNsSet != NULL) &&
12006 (curWild->negNsSet != NULL) &&
12007 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12008 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012009
12010 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012011 }
12012 /*
12013 * 5.
12014 */
12015 if (((completeWild->negNsSet != NULL) &&
12016 (completeWild->negNsSet->value != NULL) &&
12017 (curWild->nsSet != NULL)) ||
12018 ((curWild->negNsSet != NULL) &&
12019 (curWild->negNsSet->value != NULL) &&
12020 (completeWild->nsSet != NULL))) {
12021
12022 int nsFound, absentFound = 0;
12023
12024 if (completeWild->nsSet != NULL) {
12025 cur = completeWild->nsSet;
12026 curB = curWild->negNsSet;
12027 } else {
12028 cur = curWild->nsSet;
12029 curB = completeWild->negNsSet;
12030 }
12031 nsFound = 0;
12032 while (cur != NULL) {
12033 if (cur->value == NULL)
12034 absentFound = 1;
12035 else if (cur->value == curB->value)
12036 nsFound = 1;
12037 if (nsFound && absentFound)
12038 break;
12039 cur = cur->next;
12040 }
12041
12042 if (nsFound && absentFound) {
12043 /*
12044 * 5.1 If the set S includes both the negated namespace
12045 * name and ·absent·, then any must be the value.
12046 */
12047 completeWild->any = 1;
12048 if (completeWild->nsSet != NULL) {
12049 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12050 completeWild->nsSet = NULL;
12051 }
12052 if (completeWild->negNsSet != NULL) {
12053 xmlFree(completeWild->negNsSet);
12054 completeWild->negNsSet = NULL;
12055 }
12056 } else if (nsFound && (!absentFound)) {
12057 /*
12058 * 5.2 If the set S includes the negated namespace name
12059 * but not ·absent·, then a pair of not and ·absent· must
12060 * be the value.
12061 */
12062 if (completeWild->nsSet != NULL) {
12063 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12064 completeWild->nsSet = NULL;
12065 }
12066 if (completeWild->negNsSet == NULL) {
12067 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12068 if (completeWild->negNsSet == NULL)
12069 return (-1);
12070 }
12071 completeWild->negNsSet->value = NULL;
12072 } else if ((!nsFound) && absentFound) {
12073 /*
12074 * 5.3 If the set S includes ·absent· but not the negated
12075 * namespace name, then the union is not expressible.
12076 */
12077 xmlSchemaPErr(ctxt, completeWild->node,
12078 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012079 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012080 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012081 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012082 } else if ((!nsFound) && (!absentFound)) {
12083 /*
12084 * 5.4 If the set S does not include either the negated namespace
12085 * name or ·absent·, then whichever of O1 or O2 is a pair of not
12086 * and a namespace name must be the value.
12087 */
12088 if (completeWild->negNsSet == NULL) {
12089 if (completeWild->nsSet != NULL) {
12090 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12091 completeWild->nsSet = NULL;
12092 }
12093 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12094 if (completeWild->negNsSet == NULL)
12095 return (-1);
12096 completeWild->negNsSet->value = curWild->negNsSet->value;
12097 }
12098 }
12099 return (0);
12100 }
12101 /*
12102 * 6.
12103 */
12104 if (((completeWild->negNsSet != NULL) &&
12105 (completeWild->negNsSet->value == NULL) &&
12106 (curWild->nsSet != NULL)) ||
12107 ((curWild->negNsSet != NULL) &&
12108 (curWild->negNsSet->value == NULL) &&
12109 (completeWild->nsSet != NULL))) {
12110
12111 if (completeWild->nsSet != NULL) {
12112 cur = completeWild->nsSet;
12113 } else {
12114 cur = curWild->nsSet;
12115 }
12116 while (cur != NULL) {
12117 if (cur->value == NULL) {
12118 /*
12119 * 6.1 If the set S includes ·absent·, then any must be the
12120 * value.
12121 */
12122 completeWild->any = 1;
12123 if (completeWild->nsSet != NULL) {
12124 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12125 completeWild->nsSet = NULL;
12126 }
12127 if (completeWild->negNsSet != NULL) {
12128 xmlFree(completeWild->negNsSet);
12129 completeWild->negNsSet = NULL;
12130 }
12131 return (0);
12132 }
12133 cur = cur->next;
12134 }
12135 if (completeWild->negNsSet == NULL) {
12136 /*
12137 * 6.2 If the set S does not include ·absent·, then a pair of not
12138 * and ·absent· must be the value.
12139 */
12140 if (completeWild->nsSet != NULL) {
12141 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12142 completeWild->nsSet = NULL;
12143 }
12144 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12145 if (completeWild->negNsSet == NULL)
12146 return (-1);
12147 completeWild->negNsSet->value = NULL;
12148 }
12149 return (0);
12150 }
12151 return (0);
12152
12153}
12154
Daniel Veillard50355f02004-06-08 17:52:16 +000012155/**
12156 * xmlSchemaIntersectWildcards:
12157 * @ctxt: the schema parser context
12158 * @completeWild: the first wildcard
12159 * @curWild: the second wildcard
12160 *
12161 * Intersects the namespace constraints of the given wildcards.
12162 * @completeWild will hold the resulting intersection.
12163 * Returns a positive error code on failure, -1 in case of an
12164 * internal error, 0 otherwise.
12165 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012166static int
12167xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
12168 xmlSchemaWildcardPtr completeWild,
12169 xmlSchemaWildcardPtr curWild)
12170{
William M. Brack803812b2004-06-03 02:11:24 +000012171 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012172
12173 /*
12174 * 1 If O1 and O2 are the same value, then that value must be the
12175 * value.
12176 */
12177 if ((completeWild->any == curWild->any) &&
12178 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12179 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
12180
12181 if ((completeWild->negNsSet == NULL) ||
12182 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
12183
12184 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012185 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012186
12187 /*
12188 * Check equality of sets.
12189 */
12190 cur = completeWild->nsSet;
12191 while (cur != NULL) {
12192 found = 0;
12193 curB = curWild->nsSet;
12194 while (curB != NULL) {
12195 if (cur->value == curB->value) {
12196 found = 1;
12197 break;
12198 }
12199 curB = curB->next;
12200 }
12201 if (!found)
12202 break;
12203 cur = cur->next;
12204 }
12205 if (found)
12206 return(0);
12207 } else
12208 return(0);
12209 }
12210 }
12211 /*
12212 * 2 If either O1 or O2 is any, then the other must be the value.
12213 */
12214 if ((completeWild->any != curWild->any) && (completeWild->any)) {
12215 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12216 return(-1);
12217 return(0);
12218 }
12219 /*
12220 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12221 * name or ·absent·) and the other is a set of (namespace names or
12222 * ·absent·), then that set, minus the negated value if it was in
12223 * the set, minus ·absent· if it was in the set, must be the value.
12224 */
12225 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12226 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12227 const xmlChar *neg;
12228
12229 if (completeWild->nsSet == NULL) {
12230 neg = completeWild->negNsSet->value;
12231 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12232 return(-1);
12233 } else
12234 neg = curWild->negNsSet->value;
12235 /*
12236 * Remove absent and negated.
12237 */
12238 prev = NULL;
12239 cur = completeWild->nsSet;
12240 while (cur != NULL) {
12241 if (cur->value == NULL) {
12242 if (prev == NULL)
12243 completeWild->nsSet = cur->next;
12244 else
12245 prev->next = cur->next;
12246 xmlFree(cur);
12247 break;
12248 }
12249 prev = cur;
12250 cur = cur->next;
12251 }
12252 if (neg != NULL) {
12253 prev = NULL;
12254 cur = completeWild->nsSet;
12255 while (cur != NULL) {
12256 if (cur->value == neg) {
12257 if (prev == NULL)
12258 completeWild->nsSet = cur->next;
12259 else
12260 prev->next = cur->next;
12261 xmlFree(cur);
12262 break;
12263 }
12264 prev = cur;
12265 cur = cur->next;
12266 }
12267 }
12268
12269 return(0);
12270 }
12271 /*
12272 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
12273 * then the intersection of those sets must be the value.
12274 */
12275 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
12276 int found;
12277
12278 cur = completeWild->nsSet;
12279 prev = NULL;
12280 while (cur != NULL) {
12281 found = 0;
12282 curB = curWild->nsSet;
12283 while (curB != NULL) {
12284 if (cur->value == curB->value) {
12285 found = 1;
12286 break;
12287 }
12288 curB = curB->next;
12289 }
12290 if (!found) {
12291 if (prev == NULL)
12292 completeWild->nsSet = cur->next;
12293 else
12294 prev->next = cur->next;
12295 tmp = cur->next;
12296 xmlFree(cur);
12297 cur = tmp;
12298 continue;
12299 }
12300 prev = cur;
12301 cur = cur->next;
12302 }
12303
12304 return(0);
12305 }
12306 /* 5 If the two are negations of different namespace names,
12307 * then the intersection is not expressible
12308 */
12309 if ((completeWild->negNsSet != NULL) &&
12310 (curWild->negNsSet != NULL) &&
12311 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12312 (completeWild->negNsSet->value != NULL) &&
12313 (curWild->negNsSet->value != NULL)) {
12314
12315 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012316 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012317 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012318 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012319 }
12320 /*
12321 * 6 If the one is a negation of a namespace name and the other
12322 * is a negation of ·absent·, then the one which is the negation
12323 * of a namespace name must be the value.
12324 */
12325 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12326 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12327 (completeWild->negNsSet->value == NULL)) {
12328 completeWild->negNsSet->value = curWild->negNsSet->value;
12329 }
12330 return(0);
12331}
12332
Daniel Veillard50355f02004-06-08 17:52:16 +000012333/**
12334 * xmlSchemaIsWildcardNsConstraintSubset:
12335 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012336 * @sub: the first wildcard
12337 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012338 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012339 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12340 *
12341 * Returns 0 if the namespace constraint of @sub is an intensional
12342 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012343 */
12344static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012345xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12346 xmlSchemaWildcardPtr super)
12347{
Daniel Veillard50355f02004-06-08 17:52:16 +000012348 /*
12349 * 1 super must be any.
12350 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012351 if (super->any)
12352 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012353 /*
12354 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12355 * 2.2 super must be a pair of not and the same value.
12356 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012357 if ((sub->negNsSet != NULL) &&
12358 (super->negNsSet != NULL) &&
12359 (sub->negNsSet->value == sub->negNsSet->value))
12360 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012361 /*
12362 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
12363 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012364 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012365 /*
12366 * 3.2.1 super must be the same set or a superset thereof.
12367 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012368 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012369 xmlSchemaWildcardNsPtr cur, curB;
12370 int found = 0;
12371
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012372 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012373 while (cur != NULL) {
12374 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012375 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012376 while (curB != NULL) {
12377 if (cur->value == curB->value) {
12378 found = 1;
12379 break;
12380 }
12381 curB = curB->next;
12382 }
12383 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012384 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012385 cur = cur->next;
12386 }
12387 if (found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012388 return (0);
12389 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012390 xmlSchemaWildcardNsPtr cur;
12391 /*
12392 * 3.2.2 super must be a pair of not and a namespace name or
12393 * ·absent· and that value must not be in sub's set.
12394 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012395 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012396 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012397 if (cur->value == super->negNsSet->value)
12398 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012399 cur = cur->next;
12400 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012401 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012402 }
12403 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012404 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012405}
12406
12407/**
12408 * xmlSchemaBuildCompleteAttributeWildcard:
12409 * @ctxt: the schema parser context
12410 * @attrs: the attribute list
12411 * @completeWild: the resulting complete wildcard
12412 *
12413 * Returns -1 in case of an internal error, 0 otherwise.
12414 */
12415static int
12416xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
12417 xmlSchemaAttributePtr attrs,
12418 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000012419{
12420 while (attrs != NULL) {
12421 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12422 xmlSchemaAttributeGroupPtr group;
12423
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012424 group = (xmlSchemaAttributeGroupPtr) attrs;
12425 /*
12426 * Handle attribute group references.
12427 */
12428 if (group->ref != NULL) {
12429 if (group->refItem == NULL) {
12430 /*
12431 * TODO: Should we raise a warning here?
12432 */
12433 /*
12434 * The referenced attribute group definition could not
12435 * be resolved beforehand, so skip.
12436 */
12437 attrs = attrs->next;
12438 continue;
12439 } else
12440 group = group->refItem;
12441 }
12442 /*
12443 * For every attribute group definition, an intersected wildcard
12444 * will be created (assumed that a wildcard exists on the
12445 * particular attr. gr. def. or on any contained attr. gr. def
12446 * at all).
12447 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12448 * that the intersection will be performed only once.
12449 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012450 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12451 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012452 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12453 group->attributes, &group->attributeWildcard) == -1)
12454 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012455 }
12456 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
12457 }
12458 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012459 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012460 /*
12461 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012462 *
12463 * Although the complete wildcard might not correspond to any
12464 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012465 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012466 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12467 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12468 group->attributeWildcard->node);
Daniel Veillard50355f02004-06-08 17:52:16 +000012469 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
12470 completeWild, group->attributeWildcard) == -1)
12471 return (-1);
12472 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012473 (*completeWild)->node = group->attributeWildcard->node;
12474 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012475 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012476 }
12477 }
12478 attrs = attrs->next;
12479 }
12480
Daniel Veillard50355f02004-06-08 17:52:16 +000012481 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012482}
12483
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012484static int
12485xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12486 int *fixed,
12487 const xmlChar **value,
12488 xmlSchemaValPtr *val)
12489{
12490 *fixed = 0;
12491 *value = NULL;
12492 if (val != 0)
12493 *val = NULL;
12494
12495 if (item->defValue == NULL)
12496 item = item->refDecl;
12497
12498 if (item == NULL)
12499 return (0);
12500
12501 if (item->defValue != NULL) {
12502 *value = item->defValue;
12503 if (val != 0)
12504 *val = item->defVal;
12505 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12506 *fixed = 1;
12507 return (1);
12508 }
12509 return (0);
12510}
Daniel Veillard3646d642004-06-02 19:19:14 +000012511/**
12512 * xmlSchemaMatchesWildcardNs:
12513 * @wild: the wildcard
12514 * @ns: the namespace
12515 *
12516 *
12517 * Returns 1 if the given namespace matches the wildcard,
12518 * 0 otherwise.
12519 */
12520static int
12521xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
12522{
12523 if (wild == NULL)
12524 return(0);
12525
12526 if (wild->any)
12527 return(1);
12528 else if (wild->nsSet != NULL) {
12529 xmlSchemaWildcardNsPtr cur;
12530
12531 cur = wild->nsSet;
12532 while (cur != NULL) {
12533 if (xmlStrEqual(cur->value, ns))
12534 return(1);
12535 cur = cur->next;
12536 }
12537 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
12538 (!xmlStrEqual(wild->negNsSet->value, ns)))
12539 return(1);
12540
12541 return(0);
12542}
12543
12544/**
12545 * xmlSchemaBuildAttributeValidation:
12546 * @ctxt: the schema parser context
12547 * @type: the complex type definition
12548 *
12549 *
12550 * Builds the wildcard and the attribute uses on the given complex type.
12551 * Returns -1 if an internal error occurs, 0 otherwise.
12552 */
12553static int
12554xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
12555{
12556 xmlSchemaTypePtr baseType = NULL;
12557 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000012558 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012559 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012560 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000012561 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012562 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012563 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012564
Daniel Veillard01fa6152004-06-29 17:04:39 +000012565 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012566 /*
12567 * Complex Type Definition with complex content Schema Component.
12568 *
12569 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012570 * TODO: Add checks for absent referenced attribute declarations and
12571 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012572 */
12573 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012574 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012575 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000012576 "attribute uses already builded.\n",
12577 NULL, NULL);
12578 return (-1);
12579 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012580 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012581 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012582 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012583 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012584 type->name, NULL);
12585 return (-1);
12586 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012587 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012588 if (baseType == anyType)
12589 baseIsAnyType = 1;
12590 /*
12591 * Inherit the attribute uses of the base type.
12592 */
12593 /*
12594 * NOTE: It is allowed to "extend" the anyType complex type.
12595 */
12596 if (!baseIsAnyType) {
12597 if (baseType != NULL) {
12598 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
12599 tmp = (xmlSchemaAttributeLinkPtr)
12600 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12601 if (tmp == NULL) {
12602 xmlSchemaPErrMemory(ctxt,
12603 "building attribute uses of complexType", NULL);
12604 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012605 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012606 tmp->attr = cur->attr;
12607 tmp->next = NULL;
12608 if (type->attributeUses == NULL) {
12609 type->attributeUses = tmp;
12610 } else
12611 lastBaseUse->next = tmp;
12612 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012613 }
12614 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012615 }
12616 if ((type->subtypes != NULL) &&
12617 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
12618 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012619 /*
12620 * type --> (<simpleContent>|<complexContent>)
12621 * --> (<restriction>|<extension>) --> attributes
12622 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012623 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012624 } else {
12625 /* Short hand form of the complexType. */
12626 attrs = type->attributes;
12627 }
12628 /*
12629 * Handle attribute wildcards.
12630 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012631 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12632 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012633 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012634 * NOTE: During the parse time, the wildcard is created on the complexType
12635 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012636 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012637 if (err == -1) {
12638 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
12639 "Internal error: xmlSchemaBuildAttributeValidation: "
12640 "failed to build an intersected attribute wildcard.\n",
12641 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012642 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012643 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012644
12645 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12646 ((baseIsAnyType) ||
12647 ((baseType != NULL) &&
12648 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12649 (baseType->attributeWildcard != NULL)))) {
12650 if (type->attributeWildcard != NULL) {
12651 /*
12652 * Union the complete wildcard with the base wildcard.
12653 */
12654 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
12655 baseType->attributeWildcard) == -1)
12656 return (-1);
12657 } else {
12658 /*
12659 * Just inherit the wildcard.
12660 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012661 /*
12662 * NOTE: This is the only case where an attribute
12663 * wildcard is shared.
12664 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012665 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012666 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012667 }
12668
12669 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12670 if (type->attributeWildcard != NULL) {
12671 /*
12672 * Derivation Valid (Restriction, Complex)
12673 * 4.1 The {base type definition} must also have one.
12674 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012675 if (baseType->attributeWildcard == NULL) {
12676 xmlSchemaPCustomErr(ctxt,
12677 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
12678 NULL, type, NULL,
12679 "The type has an attribute wildcard, "
12680 "but the base type %s does not have one",
12681 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12682 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012683 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012684 } else if (xmlSchemaCheckCOSNSSubset(
12685 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012686 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012687 xmlSchemaPCustomErr(ctxt,
12688 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
12689 NULL, type, NULL,
12690 "The attribute wildcard is not a valid "
12691 "subset of the wildcard in the base type %s",
12692 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12693 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012694 return (1);
12695 }
12696 /* 4.3 Unless the {base type definition} is the ·ur-type
12697 * definition·, the complex type definition's {attribute
12698 * wildcard}'s {process contents} must be identical to or
12699 * stronger than the {base type definition}'s {attribute
12700 * wildcard}'s {process contents}, where strict is stronger
12701 * than lax is stronger than skip.
12702 */
12703 if ((type->baseType != anyType) &&
12704 (type->attributeWildcard->processContents <
12705 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012706 xmlSchemaPCustomErr(ctxt,
12707 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
12708 NULL, type, NULL,
12709 "The 'process contents' of the attribute wildcard is weaker than "
12710 "the one in the base type %s",
12711 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12712 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012713 return (1);
12714 }
12715 }
12716 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12717 /*
12718 * Derivation Valid (Extension)
12719 * At this point the type and the base have both, either
12720 * no wildcard or a wildcard.
12721 */
12722 if ((baseType->attributeWildcard != NULL) &&
12723 (baseType->attributeWildcard != type->attributeWildcard)) {
12724 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012725 if (xmlSchemaCheckCOSNSSubset(
12726 baseType->attributeWildcard, type->attributeWildcard)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012727 xmlSchemaPCustomErr(ctxt,
12728 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
12729 NULL, type, NULL,
12730 "The attribute wildcard is not a valid "
12731 "superset of the one in the base type %s",
12732 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12733 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012734 return (1);
12735 }
12736 }
12737 }
12738
Daniel Veillard3646d642004-06-02 19:19:14 +000012739 /*
12740 * Gather attribute uses defined by this type.
12741 */
12742 if (attrs != NULL) {
12743 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
12744 &uses, &lastUse) == -1) {
12745 return (-1);
12746 }
12747 }
12748 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
12749 * "Two distinct attribute declarations in the {attribute uses} must
12750 * not have identical {name}s and {target namespace}s."
12751 *
12752 * For "extension" this is done further down.
12753 */
12754 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
12755 cur = uses;
12756 while (cur != NULL) {
12757 tmp = cur->next;
12758 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012759 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12760 xmlSchemaGetAttrName(tmp->attr))) &&
12761 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12762 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12763
12764 xmlSchemaPAttrUseErr(ctxt,
12765 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12766 NULL, type, NULL, cur->attr,
12767 "Duplicate attribute use %s specified",
12768 xmlSchemaFormatNsUriLocal(&str,
12769 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12770 xmlSchemaGetAttrName(tmp->attr))
12771 );
12772 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012773 break;
12774 }
12775 tmp = tmp->next;
12776 }
12777 cur = cur->next;
12778 }
12779 }
12780 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12781 /*
12782 * Derive by restriction.
12783 */
12784 if (baseIsAnyType) {
12785 type->attributeUses = uses;
12786 } else {
12787 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012788 const xmlChar *bEffValue;
12789 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012790
12791 cur = uses;
12792 while (cur != NULL) {
12793 found = 0;
12794 base = type->attributeUses;
12795 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012796 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12797 xmlSchemaGetAttrName(base->attr)) &&
12798 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
12799 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012800
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012801 found = 1;
12802
Daniel Veillard3646d642004-06-02 19:19:14 +000012803 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12804 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12805 /*
12806 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000012807 */
12808 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012809 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012810 NULL, type, NULL, cur->attr,
12811 "The 'optional' use is inconsistent with a matching "
12812 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012813 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12814 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12815 /*
12816 * derivation-ok-restriction 3
12817 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012818 xmlSchemaPCustomErr(ctxt,
12819 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12820 NULL, type, NULL,
12821 "A matching attribute use for the 'required' "
12822 "attribute use %s of the base type is missing",
12823 xmlSchemaFormatNsUriLocal(&str,
12824 xmlSchemaGetAttrTargetNsURI(base->attr),
12825 xmlSchemaGetAttrName(base->attr)));
12826 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012827 } else {
12828 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012829 * 2.1.3 [Definition:] Let the effective value
12830 * constraint of an attribute use be its {value
12831 * constraint}, if present, otherwise its {attribute
12832 * declaration}'s {value constraint} .
12833 */
12834 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12835 &bEffValue, 0);
12836 /*
12837 * 2.1.3 ... one of the following must be true
12838 *
12839 * 2.1.3.1 B's ·effective value constraint· is
12840 * ·absent· or default.
12841 */
12842 if ((bEffValue != NULL) &&
12843 (effFixed == 1)) {
12844 const xmlChar *rEffValue = NULL;
12845
12846 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12847 &rEffValue, 0);
12848 /*
12849 * 2.1.3.2 R's ·effective value constraint· is
12850 * fixed with the same string as B's.
12851 */
12852 if ((effFixed == 0) ||
12853 (! xmlStrEqual(rEffValue, bEffValue))) {
12854 xmlSchemaPAttrUseErr(ctxt,
12855 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12856 NULL, type, NULL, cur->attr,
12857 "The effective value constraint of the "
12858 "attribute use is inconsistent with "
12859 "its correspondent of the base type",
12860 NULL);
12861 }
12862 }
12863 /*
12864 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
12865 */
12866 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012867 * Override the attribute use.
12868 */
12869 base->attr = cur->attr;
12870 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012871
Daniel Veillard3646d642004-06-02 19:19:14 +000012872 break;
12873 }
12874 base = base->next;
12875 }
12876
12877 if (!found) {
12878 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12879 /*
12880 * derivation-ok-restriction 2.2
12881 */
12882 if ((type->attributeWildcard != NULL) &&
12883 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12884 cur->attr->targetNamespace))
12885 found = 1;
12886
12887 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012888 xmlSchemaPAttrUseErr(ctxt,
12889 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12890 NULL, type, NULL, cur->attr,
12891 "Neither a matching attribute use, "
12892 "nor a matching wildcard in the base type does exist",
12893 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012894 } else {
12895 /*
12896 * Add the attribute use.
12897 *
12898 * Note that this may lead to funny derivation error reports, if
12899 * multiple equal attribute uses exist; but this is not
12900 * allowed anyway, and it will be reported beforehand.
12901 */
12902 tmp = cur;
12903 if (prev != NULL)
12904 prev->next = cur->next;
12905 else
12906 uses = cur->next;
12907 cur = cur->next;
12908 if (type->attributeUses == NULL) {
12909 type->attributeUses = tmp;
12910 } else
12911 lastBaseUse->next = tmp;
12912 lastBaseUse = tmp;
12913
12914 continue;
12915 }
12916 }
12917 }
12918 prev = cur;
12919 cur = cur->next;
12920 }
12921 if (uses != NULL)
12922 xmlSchemaFreeAttributeUseList(uses);
12923 }
12924 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12925 /*
12926 * The spec allows only appending, and not other kinds of extensions.
12927 *
12928 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12929 */
12930 if (uses != NULL) {
12931 if (type->attributeUses == NULL) {
12932 type->attributeUses = uses;
12933 } else
12934 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012935 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012936 } else {
12937 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012938 * Derive implicitely from the ur-type.
12939 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012940 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012941 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012942 /*
12943 * 3.4.6 -> Complex Type Definition Properties Correct
12944 */
12945 if (type->attributeUses != NULL) {
12946 cur = type->attributeUses;
12947 prev = NULL;
12948 while (cur != NULL) {
12949 /*
12950 * 4. Two distinct attribute declarations in the {attribute uses} must
12951 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012952 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012953 * Note that this was already done for "restriction" and types derived from
12954 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012955 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012956 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12957 tmp = cur->next;
12958 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012959 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12960 xmlSchemaGetAttrName(tmp->attr))) &&
12961 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12962 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012963
Daniel Veillardc0826a72004-08-10 14:17:33 +000012964 xmlSchemaPAttrUseErr(ctxt,
12965 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12966 NULL, type, NULL, tmp->attr,
12967 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012968 break;
12969 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012970 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012971 }
12972 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012973 /*
12974 * 5. Two distinct attribute declarations in the {attribute uses} must
12975 * not have {type definition}s which are or are derived from ID.
12976 */
12977 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012978 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012979 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012980 xmlSchemaPAttrUseErr(ctxt,
12981 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12982 NULL, type, NULL, cur->attr,
12983 "There must not exist more than one attribute use, "
12984 "declared of type 'ID' or derived from it",
12985 NULL);
12986 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012987 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012988 id = cur;
12989 }
12990 /*
12991 * Remove "prohibited" attribute uses. The reason this is done at this late
12992 * stage is to be able to catch dublicate attribute uses. So we had to keep
12993 * prohibited uses in the list as well.
12994 */
12995 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12996 tmp = cur;
12997 if (prev == NULL)
12998 type->attributeUses = cur->next;
12999 else
13000 prev->next = cur->next;
13001 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013002 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013003 } else {
13004 prev = cur;
13005 cur = cur->next;
13006 }
13007 }
13008 }
13009 /*
13010 * TODO: This check should be removed if we are 100% sure of
13011 * the base type attribute uses already being built.
13012 */
13013 if ((baseType != NULL) && (!baseIsAnyType) &&
13014 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013015 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013016 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013017 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013018 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000013019 baseType->name, NULL);
13020 }
13021 return (0);
13022}
13023
13024/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013025 * xmlSchemaTypeFinalContains:
13026 * @schema: the schema
13027 * @type: the type definition
13028 * @final: the final
13029 *
13030 * Evaluates if a type definition contains the given "final".
13031 * This does take "finalDefault" into account as well.
13032 *
13033 * Returns 1 if the type does containt the given "final",
13034 * 0 otherwise.
13035 */
13036static int
13037xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
13038{
13039 int tfinal = final, tflags = type->flags;
13040
13041 if (type == NULL)
13042 return (0);
13043 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
13044 switch (final) {
13045 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
13046 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
13047 break;
13048 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
13049 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
13050 break;
13051 case XML_SCHEMAS_TYPE_FINAL_LIST:
13052 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
13053 break;
13054 case XML_SCHEMAS_TYPE_FINAL_UNION:
13055 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
13056 break;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013057 default:
13058 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013059 }
13060 tflags = schema->flags;
13061 }
13062 if (tflags & tfinal)
13063 return (1);
13064 else
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013065 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013066}
13067
13068/**
13069 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13070 * @type: the Union Simple Type
13071 *
13072 * Returns a list of member types of @type if existing,
13073 * returns NULL otherwise.
13074 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013075static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013076xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13077{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013078 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013079 if (type->memberTypes != NULL)
13080 return (type->memberTypes);
13081 else
13082 type = type->baseType;
13083 }
13084 return (NULL);
13085}
13086
13087/**
13088 * xmlSchemaGetListSimpleTypeItemType:
13089 * @type: the simple type definition
13090 *
13091 * Returns the item type definition of the list simple type.
13092 */
13093static xmlSchemaTypePtr
13094xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
13095{
13096 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
13097 return (NULL);
13098 /*
13099 * Note: In libxml2, the built-in types do not reflect
13100 * the datatype hierarchy (yet?) - we have to treat them
13101 * in a special way.
13102 */
13103 if (type->type == XML_SCHEMA_TYPE_BASIC)
13104 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013105 return (type->subtypes);
13106}
13107
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013108/**
13109 * xmlSchemaGetParticleTotalRangeMin:
13110 * @particle: the particle
13111 *
13112 * Schema Component Constraint: Effective Total Range
13113 * (all and sequence) + (choice)
13114 *
13115 * Returns the minimun Effective Total Range.
13116 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013117static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013118xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013119{
13120 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013121 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013122 return (0);
13123 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013124 int min = -1, cur;
13125 xmlSchemaParticlePtr part =
13126 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013127
13128 if (part == NULL)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013129 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013130 while (part != NULL) {
13131 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13132 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013133 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013134 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013135 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013136 if (cur == 0)
13137 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013138 if ((min > cur) || (min == -1))
13139 min = cur;
13140 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013141 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013142 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013143 } else {
13144 /* <all> and <sequence> */
13145 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013146 xmlSchemaParticlePtr part =
13147 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013148
13149 if (part == NULL)
13150 return (0);
13151 do {
13152 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13153 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013154 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013155 else
13156 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013157 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013158 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013159 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013160 }
13161}
13162
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013163/**
13164 * xmlSchemaGetParticleTotalRangeMax:
13165 * @particle: the particle
13166 *
13167 * Schema Component Constraint: Effective Total Range
13168 * (all and sequence) + (choice)
13169 *
13170 * Returns the maximum Effective Total Range.
13171 */
13172static int
13173xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13174{
13175 if ((particle->children == NULL) ||
13176 (particle->children->children == NULL))
13177 return (0);
13178 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13179 int max = -1, cur;
13180 xmlSchemaParticlePtr part =
13181 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013183 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13184 if (part->children == NULL)
13185 continue;
13186 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13187 (part->children->type == XML_SCHEMA_TYPE_ANY))
13188 cur = part->maxOccurs;
13189 else
13190 cur = xmlSchemaGetParticleTotalRangeMax(part);
13191 if (cur == UNBOUNDED)
13192 return (UNBOUNDED);
13193 if ((max < cur) || (max == -1))
13194 max = cur;
13195 }
13196 /* TODO: Handle overflows? */
13197 return (particle->maxOccurs * max);
13198 } else {
13199 /* <all> and <sequence> */
13200 int sum = 0, cur;
13201 xmlSchemaParticlePtr part =
13202 (xmlSchemaParticlePtr) particle->children->children;
13203
13204 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13205 if (part->children == NULL)
13206 continue;
13207 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13208 (part->children->type == XML_SCHEMA_TYPE_ANY))
13209 cur = part->maxOccurs;
13210 else
13211 cur = xmlSchemaGetParticleTotalRangeMax(part);
13212 if (cur == UNBOUNDED)
13213 return (UNBOUNDED);
13214 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13215 return (UNBOUNDED);
13216 sum += cur;
13217 }
13218 /* TODO: Handle overflows? */
13219 return (particle->maxOccurs * sum);
13220 }
13221}
13222
13223/**
13224 * xmlSchemaIsParticleEmptiable:
13225 * @particle: the particle
13226 *
13227 * Schema Component Constraint: Particle Emptiable
13228 * Checks whether the given particle is emptiable.
13229 *
13230 * Returns 1 if emptiable, 0 otherwise.
13231 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013232static int
13233xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13234{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013235 /*
13236 * SPEC (1) "Its {min occurs} is 0."
13237 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013238 if ((particle == NULL) || (particle->minOccurs == 0) ||
13239 (particle->children == NULL))
13240 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013241 /*
13242 * SPEC (2) "Its {term} is a group and the minimum part of the
13243 * effective total range of that group, [...] is 0."
13244 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013245 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013246 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013247 return (1);
13248 }
13249 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013250}
13251
13252/**
13253 * xmlSchemaCheckCOSSTDerivedOK:
13254 * @type: the derived simple type definition
13255 * @baseType: the base type definition
13256 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013257 * Schema Component Constraint:
13258 * Type Derivation OK (Simple) (cos-st-derived-OK)
13259 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013260 * Checks wheter @type can be validly
13261 * derived from @baseType.
13262 *
13263 * Returns 0 on success, an positive error code otherwise.
13264 */
13265static int
13266xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
13267 xmlSchemaTypePtr type,
13268 xmlSchemaTypePtr baseType,
13269 int subset)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013270{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013271 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013272 * 1 They are the same type definition.
13273 * TODO: The identy check might have to be more complex than this.
13274 */
13275 if (type == baseType)
13276 return (0);
13277 /*
13278 * 2.1 restriction is not in the subset, or in the {final}
13279 * of its own {base type definition};
13280 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013281 if ((subset & SUBSET_RESTRICTION) ||
Daniel Veillard01fa6152004-06-29 17:04:39 +000013282 (xmlSchemaTypeFinalContains(schema,
13283 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13284 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
13285 }
13286 /* 2.2 */
13287 if (type->baseType == baseType) {
13288 /*
13289 * 2.2.1 D's ·base type definition· is B.
13290 */
13291 return (0);
13292 }
13293 /*
13294 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13295 * and is validly derived from B given the subset, as defined by this
13296 * constraint.
13297 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013298 if ((! IS_ANYTYPE(type->baseType)) &&
13299 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType,
13300 baseType, subset) == 0)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013301 return (0);
13302 }
13303 /*
13304 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
13305 * definition·.
13306 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013307 if (IS_ANY_SIMPLE_TYPE(baseType) &&
13308 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13309 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013310 return (0);
13311 }
13312 /*
13313 * 2.2.4 B's {variety} is union and D is validly derived from a type
13314 * definition in B's {member type definitions} given the subset, as
13315 * defined by this constraint.
13316 *
13317 * NOTE: This seems not to involve built-in types, since there is no
13318 * built-in Union Simple Type.
13319 */
13320 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13321 xmlSchemaTypeLinkPtr cur;
13322
13323 cur = baseType->memberTypes;
13324 while (cur != NULL) {
13325 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
13326 cur->type, subset) == 0)
13327 return (0);
13328 cur = cur->next;
13329 }
13330 }
13331
13332 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13333}
13334
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013335/**
13336 * xmlSchemaCheckTypeDefCircularInternal:
13337 * @pctxt: the schema parser context
13338 * @ctxtType: the type definition
13339 * @ancestor: an ancestor of @ctxtType
13340 *
13341 * Checks st-props-correct (2) + ct-props-correct (3).
13342 * Circular type definitions are not allowed.
13343 *
13344 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13345 * circular, 0 otherwise.
13346 */
13347static int
13348xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13349 xmlSchemaTypePtr ctxtType,
13350 xmlSchemaTypePtr ancestor)
13351{
13352 int ret;
13353
13354 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13355 return (0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013356
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013357 if (ctxtType == ancestor) {
13358 xmlSchemaPCustomErr(pctxt,
13359 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13360 NULL, ctxtType, GET_NODE(ctxtType),
13361 "The definition is circular", NULL);
13362 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13363 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013364 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13365 /*
13366 * Avoid inifinite recursion on circular types not yet checked.
13367 */
13368 return (0);
13369 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013370 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13371 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13372 ancestor->baseType);
13373 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13374 return (ret);
13375}
13376
13377/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013378 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013379 * @item: the complex/simple type definition
13380 * @ctxt: the parser context
13381 * @name: the name
13382 *
13383 * Checks for circular type definitions.
13384 */
13385static void
13386xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
13387 xmlSchemaParserCtxtPtr ctxt,
13388 const xmlChar * name ATTRIBUTE_UNUSED)
13389{
13390 if ((item == NULL) ||
13391 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13392 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13393 return;
13394 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13395
13396}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013397
13398/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013399 * xmlSchemaResolveTypeDefs:
13400 * @item: the complex/simple type definition
13401 * @ctxt: the parser context
13402 * @name: the name
13403 *
13404 * Checks for circular type definitions.
13405 */
13406static void
13407xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
13408 xmlSchemaParserCtxtPtr ctxt,
13409 const xmlChar * name ATTRIBUTE_UNUSED)
13410{
13411 if (typeDef == NULL)
13412 return;
13413
13414 if (IS_SIMPLE_TYPE(typeDef)) {
13415 if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13416 /*
13417 * Resolve the memberTypes.
13418 */
13419 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13420 return;
13421 } else if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13422 /*
13423 * Resolve the itemType.
13424 */
13425 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13426 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13427 typeDef->ref, typeDef->refNs);
13428 if ((typeDef->subtypes == NULL) ||
13429 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13430 typeDef->subtypes = NULL;
13431 xmlSchemaPResCompAttrErr(ctxt,
13432 XML_SCHEMAP_SRC_RESOLVE,
13433 NULL, typeDef, typeDef->node,
13434 "itemType", typeDef->ref, typeDef->refNs,
13435 XML_SCHEMA_TYPE_SIMPLE, NULL);
13436 }
13437 }
13438 return;
13439 }
13440 }
13441 /*
13442 * Resolve the base type.
13443 */
13444 if (typeDef->baseType == NULL) {
13445 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13446 typeDef->base, typeDef->baseNs);
13447 if (typeDef->baseType == NULL) {
13448 xmlSchemaPResCompAttrErr(ctxt,
13449 XML_SCHEMAP_SRC_RESOLVE,
13450 NULL, typeDef, typeDef->node,
13451 "base", typeDef->base, typeDef->baseNs,
13452 XML_SCHEMA_TYPE_SIMPLE, NULL);
13453 return;
13454 }
13455 }
13456}
13457
13458
13459
13460/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013461 * xmlSchemaCheckSTPropsCorrect:
13462 * @ctxt: the schema parser context
13463 * @type: the simple type definition
13464 *
13465 * Checks st-props-correct.
13466 *
13467 * Returns 0 if the properties are correct,
13468 * if not, a positive error code and -1 on internal
13469 * errors.
13470 */
13471static int
13472xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13473 xmlSchemaTypePtr type)
13474{
13475 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13476 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013477 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013478
Daniel Veillardc0826a72004-08-10 14:17:33 +000013479 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 /*
13481 * Schema Component Constraint: Simple Type Definition Properties Correct
13482 *
13483 * NOTE: This is somehow redundant, since we actually built a simple type
13484 * to have all the needed information; this acts as an self test.
13485 */
13486 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13487 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 /* Base type: If the datatype has been ·derived· by ·restriction·
13489 * then the Simple Type Definition component from which it is ·derived·,
13490 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
13491 */
13492 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013493 /*
13494 * TODO: Think about: "modulo the impact of Missing
13495 * Sub-components (§5.3)."
13496 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013497 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013498 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013499 NULL, type, NULL,
13500 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013502
Daniel Veillard01fa6152004-06-29 17:04:39 +000013503 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013504 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013505 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013507 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013508 "The base type '%s' is not a simple type",
13509 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013510 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013511 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13512 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013513 if ((baseType->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
13514 ((type->flags &
13515 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13516 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13517 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013518 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013520 NULL, type, NULL,
13521 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013522 "the simple ur-type definition as base type, not '%s'",
13523 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013524 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13526 }
13527 /*
13528 * Variety: One of {atomic, list, union}.
13529 */
13530 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13531 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
13532 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013533 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013534 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013535 NULL, type, NULL,
13536 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13538 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013539 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013540
13541 /*
13542 * 3 The {final} of the {base type definition} must not contain restriction.
13543 */
13544 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
13545 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13546 xmlSchemaPCustomErr(ctxt,
13547 XML_SCHEMAP_ST_PROPS_CORRECT_3,
13548 NULL, type, NULL,
13549 "The 'final' of its base type '%s' must not contain "
13550 "'restriction'",
13551 xmlSchemaGetComponentQName(&str, baseType));
13552 FREE_AND_NULL(str)
13553 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
13554 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013555
13556 /*
13557 * 2 All simple type definitions must be derived ultimately from the ·simple
13558 * ur-type definition (so· circular definitions are disallowed). That is, it
13559 * must be possible to reach a built-in primitive datatype or the ·simple
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013560 * ur-type definition· by repeatedly following the {base type definition}.
13561 *
13562 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013563 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013564 return (0);
13565}
13566
13567/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013568 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013569 * @ctxt: the schema parser context
13570 * @type: the simple type definition
13571 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013572 * Schema Component Constraint:
13573 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13574
13575 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013576 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 *
13578 * Returns -1 on internal errors, 0 if the type is validly derived,
13579 * a positive error code otherwise.
13580 */
13581static int
13582xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013583 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013584{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013585 xmlChar *str = NULL;
13586
Daniel Veillard01fa6152004-06-29 17:04:39 +000013587 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
13588 xmlSchemaPErr(ctxt, type->node,
13589 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013590 "xmlSchemaCheckCOSSTRestricts: The given "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013591 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013592 type->name, NULL);
13593 return (-1);
13594 }
13595
13596 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13597 xmlSchemaTypePtr primitive;
13598 /*
13599 * 1.1 The {base type definition} must be an atomic simple
13600 * type definition or a built-in primitive datatype.
13601 */
13602 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013603 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013604 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013605 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013606 "The base type '%s' is not an atomic simple type",
13607 xmlSchemaGetComponentQName(&str, type->baseType));
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_1_1);
13610 }
13611 /* 1.2 The {final} of the {base type definition} must not contain
13612 * restriction.
13613 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013614 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013615 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13616 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013617 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013618 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013619 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013620 "The final of its base type '%s' must not contain 'restriction'",
13621 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013622 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13624 }
13625
13626 /*
13627 * 1.3.1 DF must be an allowed constraining facet for the {primitive
13628 * type definition}, as specified in the appropriate subsection of 3.2
13629 * Primitive datatypes.
13630 */
13631 if (type->facets != NULL) {
13632 xmlSchemaFacetPtr facet;
13633 int ok = 1;
13634
13635 primitive = xmlSchemaGetPrimitiveType(type);
13636 if (primitive == NULL) {
13637 xmlSchemaPErr(ctxt, type->node,
13638 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013639 "xmlSchemaCheckCOSSTRestricts: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013640 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013641 type->name, NULL);
13642 return (-1);
13643 }
13644 facet = type->facets;
13645 do {
13646 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013647 ok = 0;
13648 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013649 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013650 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013651 }
13652 facet = facet->next;
13653 } while (facet != NULL);
13654 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013655 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013656 }
13657 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013658 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13659 * of the {base type definition} (call this BF),then the DF's {value}
13660 * must be a valid restriction of BF's {value} as defined in
13661 * [XML Schemas: Datatypes]."
13662 *
13663 * NOTE (1.3.2) Facet derivation constraints are currently handled in
13664 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 */
13666 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13667 xmlSchemaTypePtr itemType = NULL;
13668
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013669 itemType = type->subtypes;
13670 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 xmlSchemaPErr(ctxt, type->node,
13672 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013673 "Internal error: xmlSchemaCheckCOSSTRestricts: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013674 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013675 type->name, NULL);
13676 return (-1);
13677 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013678 if (IS_NOT_TYPEFIXED(itemType))
13679 xmlSchemaTypeFixup(itemType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013680 /*
13681 * 2.1 The {item type definition} must have a {variety} of atomic or
13682 * union (in which case all the {member type definitions}
13683 * must be atomic).
13684 */
13685 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13686 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013687 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013688 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013689 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013690 "The item type '%s' does not have a variety of atomic or union",
13691 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013692 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013693 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13694 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13695 xmlSchemaTypeLinkPtr member;
13696
13697 member = itemType->memberTypes;
13698 while (member != NULL) {
13699 if ((member->type->flags &
13700 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013701 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013702 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013703 NULL, type, NULL,
13704 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013705 "member type '%s' of this item type is not atomic",
13706 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013707 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013708 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13709 }
13710 member = member->next;
13711 }
13712 }
13713
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013714 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 xmlSchemaFacetPtr facet;
13716 /*
13717 * This is the case if we have: <simpleType><list ..
13718 */
13719 /*
13720 * 2.3.1
13721 * 2.3.1.1 The {final} of the {item type definition} must not
13722 * contain list.
13723 */
13724 if (xmlSchemaTypeFinalContains(ctxt->schema,
13725 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013726 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013728 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013729 "The final of its item type '%s' must not contain 'list'",
13730 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013731 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13733 }
13734 /*
13735 * 2.3.1.2 The {facets} must only contain the whiteSpace
13736 * facet component.
13737 */
13738 if (type->facets != NULL) {
13739 facet = type->facets;
13740 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013741 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13742 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013744 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013745 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13746 }
13747 facet = facet->next;
13748 } while (facet != NULL);
13749 }
13750 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013751 * MABY TODO: (Hmm, not really) Datatypes states:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13753 * whose ·lexical space· allows space (such as string or anyURI)or
13754 * a ·union· datatype any of whose {member type definitions}'s
13755 * ·lexical space· allows space.
13756 */
13757 } else {
13758 /*
13759 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013760 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013761 */
13762 /*
13763 * 2.3.2
13764 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13765 */
13766 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013767 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013769 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013770 "The base type '%s' must be a list type",
13771 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013772 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13774 }
13775 /*
13776 * 2.3.2.2 The {final} of the {base type definition} must not
13777 * contain restriction.
13778 */
13779 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13780 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013781 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013782 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013783 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013784 "The 'final' of the base type '%s' must not contain 'restriction'",
13785 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013786 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13788 }
13789 /*
13790 * 2.3.2.3 The {item type definition} must be validly derived
13791 * from the {base type definition}'s {item type definition} given
13792 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13793 */
13794 {
13795 xmlSchemaTypePtr baseItemType;
13796
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013797 baseItemType = type->baseType->subtypes;
13798 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013799 xmlSchemaPErr(ctxt, type->node,
13800 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013801 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013802 "List simple type '%s': Failed to "
13803 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 type->name, type->baseType->name);
13805 return (-1);
13806 }
13807 if ((itemType != baseItemType) &&
13808 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
13809 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 xmlChar *strBIT = NULL, *strBT = NULL;
13811 xmlSchemaPCustomErrExt(ctxt,
13812 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
13813 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013814 "The item type '%s' is not validly derived from the "
13815 "item type '%s' of the base type '%s'",
13816 xmlSchemaGetComponentQName(&str, itemType),
13817 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13818 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013819
13820 FREE_AND_NULL(str)
13821 FREE_AND_NULL(strBIT)
13822 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013823 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13824 }
13825 }
13826
13827 if (type->facets != NULL) {
13828 xmlSchemaFacetPtr facet;
13829 int ok = 1;
13830 /*
13831 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
13832 * and enumeration facet components are allowed among the {facets}.
13833 */
13834 facet = type->facets;
13835 do {
13836 switch (facet->type) {
13837 case XML_SCHEMA_FACET_LENGTH:
13838 case XML_SCHEMA_FACET_MINLENGTH:
13839 case XML_SCHEMA_FACET_MAXLENGTH:
13840 case XML_SCHEMA_FACET_WHITESPACE:
13841 /*
13842 * TODO: 2.5.1.2 List datatypes
13843 * The value of ·whiteSpace· is fixed to the value collapse.
13844 */
13845 case XML_SCHEMA_FACET_PATTERN:
13846 case XML_SCHEMA_FACET_ENUMERATION:
13847 break;
13848 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013849 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013850 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013851 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013852 /*
13853 * We could return, but it's nicer to report all
13854 * invalid facets.
13855 */
13856 ok = 0;
13857 }
13858 }
13859 facet = facet->next;
13860 } while (facet != NULL);
13861 if (ok == 0)
13862 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13863 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013864 * SPEC (2.3.2.5) (same as 1.3.2)
13865 *
13866 * NOTE (2.3.2.5) This is currently done in
13867 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 */
13869 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 }
13871 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13872 /*
13873 * 3.1 The {member type definitions} must all have {variety} of
13874 * atomic or list.
13875 */
13876 xmlSchemaTypeLinkPtr member;
13877
13878 member = type->memberTypes;
13879 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013880 if (IS_NOT_TYPEFIXED(member->type))
13881 xmlSchemaTypeFixup(member->type, ctxt, NULL);
13882
Daniel Veillard01fa6152004-06-29 17:04:39 +000013883 if (((member->type->flags &
13884 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13885 ((member->type->flags &
13886 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013887 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013888 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013889 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013890 "The member type '%s' is neither an atomic, nor a list type",
13891 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013892 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013893 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13894 }
13895 member = member->next;
13896 }
13897 /*
13898 * 3.3.1 If the {base type definition} is the ·simple ur-type
13899 * definition·
13900 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013901 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 /*
13903 * 3.3.1.1 All of the {member type definitions} must have a
13904 * {final} which does not contain union.
13905 */
13906 member = type->memberTypes;
13907 while (member != NULL) {
13908 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
13909 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013910 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013911 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013912 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013913 "The 'final' of member type '%s' contains 'union'",
13914 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013915 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13917 }
13918 member = member->next;
13919 }
13920 /*
13921 * 3.3.1.2 The {facets} must be empty.
13922 */
13923 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013924 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013925 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013926 NULL, type, NULL,
13927 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013928 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13929 }
13930 } else {
13931 /*
13932 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013933 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013934 */
13935 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013936 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013937 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013938 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013939 "The base type '%s' is not a union type",
13940 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013941 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013942 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13943 }
13944 /*
13945 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13946 */
13947 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13948 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013949 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013950 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013951 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013952 "The 'final' of its base type '%s' must not contain 'restriction'",
13953 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013954 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013955 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13956 }
13957 /*
13958 * 3.3.2.3 The {member type definitions}, in order, must be validly
13959 * derived from the corresponding type definitions in the {base
13960 * type definition}'s {member type definitions} given the empty set,
13961 * as defined in Type Derivation OK (Simple) (§3.14.6).
13962 */
13963 {
13964 xmlSchemaTypeLinkPtr baseMember;
13965
13966 /*
13967 * OPTIMIZE: if the type is restricting, it has no local defined
13968 * member types and inherits the member types of the base type;
13969 * thus a check for equality can be skipped.
13970 */
13971 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013972 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 * union simple type can have other member types as the member
13974 * types of it's base type. This check seems not necessary with
13975 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013976 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013977 */
13978 if (type->memberTypes != NULL) {
13979 member = type->memberTypes;
13980 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
13981 if ((member == NULL) && (baseMember != NULL)) {
13982 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013983 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013984 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013985 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013986 "of member types in the base type\n",
13987 type->name, NULL);
13988 }
13989 while (member != NULL) {
13990 if (baseMember == NULL) {
13991 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013992 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013993 "Internal error: "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013994 "xmlSchemaCheckCOSSTRestricts "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013995 "(3.3.2.3), union simple type '%s', unequal number "
13996 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013997 type->name, NULL);
13998 }
13999 if ((member->type != baseMember->type) &&
14000 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
14001 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014002 xmlChar *strBMT = NULL, *strBT = NULL;
14003
14004 xmlSchemaPCustomErrExt(ctxt,
14005 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
14006 NULL, type, NULL,
14007 "The member type %s is not validly derived from its "
14008 "corresponding member type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014009 xmlSchemaGetComponentQName(&str, member->type),
14010 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
14011 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014012 FREE_AND_NULL(str)
14013 FREE_AND_NULL(strBMT)
14014 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
14016 }
14017 member = member->next;
14018 baseMember = baseMember->next;
14019 }
14020 }
14021 }
14022 /*
14023 * 3.3.2.4 Only pattern and enumeration facet components are
14024 * allowed among the {facets}.
14025 */
14026 if (type->facets != NULL) {
14027 xmlSchemaFacetPtr facet;
14028 int ok = 1;
14029
14030 facet = type->facets;
14031 do {
14032 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
14033 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014034 xmlSchemaPIllegalFacetListUnionErr(ctxt,
14035 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
14036 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014037 ok = 0;
14038 }
14039 facet = facet->next;
14040 } while (facet != NULL);
14041 if (ok == 0)
14042 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
14043
14044 }
14045 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014046 * SPEC (3.3.2.5) (same as 1.3.2)
14047 *
14048 * NOTE (3.3.2.5) This is currently done in
14049 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014050 */
14051 }
14052 }
14053
14054 return (0);
14055}
14056
14057/**
14058 * xmlSchemaCheckSRCSimpleType:
14059 * @ctxt: the schema parser context
14060 * @type: the simple type definition
14061 *
14062 * Checks crc-simple-type constraints.
14063 *
14064 * Returns 0 if the constraints are satisfied,
14065 * if not a positive error code and -1 on internal
14066 * errors.
14067 */
14068static int
14069xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14070 xmlSchemaTypePtr type)
14071{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014072 /*
14073 * src-simple-type.1 The corresponding simple type definition, if any,
14074 * must satisfy the conditions set out in Constraints on Simple Type
14075 * Definition Schema Components (§3.14.6).
14076 */
14077 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
14078 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14079 /*
14080 * TODO: Removed this, since it got annoying to get an
14081 * extra error report, if anything failed until now.
14082 * Enable this if needed.
14083 */
14084 /*
14085 xmlSchemaPErr(ctxt, type->node,
14086 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014087 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014088 "on simple type definitions.\n",
14089 type->name, NULL);
14090 */
14091 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14092 }
14093
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014094 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014095 /*
14096 * src-simple-type.2 If the <restriction> alternative is chosen,
14097 * either it must have a base [attribute] or a <simpleType> among its
14098 * [children], but not both.
14099 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014100 /*
14101 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014102 * NOTE: This is checked in the parse function of <restriction>.
William M. Brack2f2a6632004-08-20 23:09:47 +000014103 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014104 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014105 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14106 * an itemType [attribute] or a <simpleType> among its [children],
14107 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014108 *
14109 * REMOVED: This is checked in the parse function of <list>.
14110 */
14111 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014112 xmlSchemaTypeLinkPtr member;
14113 xmlSchemaTypePtr ancestor, anySimpleType;
14114
14115 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14116
14117 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14118 * the <union> alternative is chosen, there must not be any entries
14119 * in the memberTypes [attribute] at any depth which resolve to the
14120 * component corresponding to the <simpleType>.
14121 */
14122 member = type->memberTypes;
14123 while (member != NULL) {
14124 ancestor = member->type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014125 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
14126 if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014127 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014128 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014129 NULL, type, NULL,
14130 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014131 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014132 }
14133 if (IS_NOT_TYPEFIXED(ancestor))
14134 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
14135 if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014136 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014137 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000014138 * type as item type, which in turn has a list ST as member
14139 * type, we will assume this here as well, since this check
14140 * was not yet performed.
14141 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014142 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014143
Daniel Veillard01fa6152004-06-29 17:04:39 +000014144 ancestor = ancestor->baseType;
14145 }
14146 member = member->next;
14147 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014148 }
14149
14150 return (0);
14151}
14152
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014153#if 0 /* Not yet used code for ST schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000014154static int
14155xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
14156 const xmlChar * value,
14157 xmlSchemaTypePtr type,
14158 int fireErrors)
14159{
14160 int ret;
14161 /*
14162 * 3.14.4 Simple Type Definition Validation Rules
14163 * Validation Rule: String Valid
14164 */
14165 /*
14166 * 1 It is schema-valid with respect to that definition as defined
14167 * by Datatype Valid in [XML Schemas: Datatypes].
14168 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014169 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14170 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000014171 return (ret);
14172 /*
14173 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
14174 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
14175 * the string must be a ·declared entity name·.
14176 */
14177 /*
14178 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
14179 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
14180 * then every whitespace-delimited substring of the string must be a ·declared
14181 * entity name·.
14182 */
14183 /*
14184 * 2.3 otherwise no further condition applies.
14185 */
14186
14187 return (0);
14188}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014189#endif
14190
William M. Brack2f2a6632004-08-20 23:09:47 +000014191
14192static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014193xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
14194{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000014195 if (vctxt->pctxt == NULL) {
14196 if (vctxt->schema != NULL)
14197 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
14198 else
14199 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014200 if (vctxt->pctxt == NULL) {
14201 xmlSchemaVErr(vctxt, NULL,
14202 XML_SCHEMAV_INTERNAL,
14203 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14204 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000014205 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014206 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014207 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014208 /* TODO: Pass user data. */
14209 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
14210 }
14211 return (0);
14212}
14213
14214static int
14215xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14216{
14217 if (ctxt->vctxt == NULL) {
14218 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14219 if (ctxt->vctxt == NULL) {
14220 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014221 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014222 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14223 "failed to create a temp. validation context.\n",
14224 NULL, NULL);
14225 return (-1);
14226 }
14227 /* TODO: Pass user data. */
14228 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
14229 }
14230 return (0);
14231}
14232
14233/**
14234 * xmlSchemaCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014235 * @pctxt: the schema parser context
14236 * @vctxt: the temporary schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014237 * @type: the simple type definition
14238 * @value: the default value
14239 * @node: an optional node (the holder of the value)
14240 *
14241 * Checks the "cos-valid-default" constraints.
14242 *
14243 * Returns 0 if the constraints are satisfied,
14244 * if not, a positive error code and -1 on internal
14245 * errors.
14246 */
14247static int
14248xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14249 xmlSchemaValidCtxtPtr vctxt,
14250 xmlSchemaTypePtr type,
14251 const xmlChar *value,
14252 xmlNodePtr node)
14253{
14254 int ret = 0;
14255
14256 /*
14257 * cos-valid-default:
14258 * Schema Component Constraint: Element Default Valid (Immediate)
14259 * For a string to be a valid default with respect to a type
14260 * definition the appropriate case among the following must be true:
14261 */
14262 /*
14263 * NOTE: This has to work without a given node (the holder of the
14264 * value), since it should work on the component, i.e. an underlying
14265 * DOM must not be mandatory.
14266 */
14267 if ((pctxt == NULL) || (vctxt == NULL)) {
14268 xmlSchemaPErr(pctxt, node,
14269 XML_SCHEMAP_INTERNAL,
14270 "Internal error: xmlSchemaCheckCOSValidDefault, "
14271 "bad arguments: the parser and/or validation context is "
14272 "missing.\n",
14273 NULL, NULL);
14274 return (-1);
14275 }
14276 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014277 /*
14278 * Complex type.
14279 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014280 * SPEC (2.1) "its {content type} must be a simple type definition
14281 * or mixed."
14282 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
14283 * type}'s particle must be ·emptiable· as defined by
14284 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014285 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014286 if ((! HAS_SIMPLE_CONTENT(type)) &&
14287 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14288 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014289 xmlSchemaPSimpleTypeErr(pctxt,
14290 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
14291 NULL, NULL, node,
14292 type, NULL, NULL,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014293 "For a string to be a valid default, the type definition "
14294 "must be a simple type or a complex type with mixed content "
14295 "and a particle emptiable",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014296 NULL, NULL);
14297 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14298 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014299 }
14300 /*
14301 * 1 If the type definition is a simple type definition, then the string
14302 * must be ·valid· with respect to that definition as defined by String
14303 * Valid (§3.14.4).
14304 *
14305 * AND
14306 *
14307 * 2.2.1 If the {content type} is a simple type definition, then the
14308 * string must be ·valid· with respect to that simple type definition
14309 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014310 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014311 vctxt->node = node;
14312 vctxt->cur = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014313 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014314 if (IS_SIMPLE_TYPE(type))
14315 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value,
14316 1, 1, 1, 0);
14317 else if (HAS_SIMPLE_CONTENT(type))
14318 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type->contentTypeDef,
14319 value, 1, 1, 1, 0);
14320 else
14321 return (ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014322 if (ret != 0) {
14323 pctxt->err = vctxt->err;
14324 pctxt->nberrors++;
14325 }
14326
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014327 if (ret < 0) {
14328 xmlSchemaPErr(pctxt, node,
14329 /* NOTNICE: error code: This function will be used during
14330 * schema construction and xsi:type validation.
14331 */
14332 XML_SCHEMAP_INTERNAL,
14333 "Internal error: xmlSchemaCheckCOSValidDefault, "
14334 "while validating a value constaint value.\n",
14335 NULL, NULL);
14336
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014337 }
14338
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014339 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014340}
14341
14342/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014343 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014344 * @ctxt: the schema parser context
14345 * @type: the complex type definition
14346 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014347 *.(4.6) Constraints on Complex Type Definition Schema Components
14348 * Schema Component Constraint:
14349 * Complex Type Definition Properties Correct (ct-props-correct)
14350 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014351 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014352 * Returns 0 if the constraints are satisfied, a positive
14353 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014355static int
14356xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14357 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014358{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014359 /*
14360 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14361 *
14362 * SPEC (1) "The values of the properties of a complex type definition must
14363 * be as described in the property tableau in The Complex Type Definition
14364 * Schema Component (§3.4.1), modulo the impact of Missing
14365 * Sub-components (§5.3)."
14366 */
14367 if ((type->baseType != NULL) &&
14368 (IS_SIMPLE_TYPE(type->baseType)) &&
14369 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14370 /*
14371 * SPEC (2) "If the {base type definition} is a simple type definition,
14372 * the {derivation method} must be extension."
14373 */
14374 xmlSchemaPCustomErr(pctxt,
14375 XML_SCHEMAP_SRC_CT_1,
14376 NULL, type, NULL,
14377 "If the base type is a simple type, the derivation method must be "
14378 "'extension'", NULL);
14379 return (XML_SCHEMAP_SRC_CT_1);
14380 }
14381 /*
14382 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14383 * definition·. That is, it must be possible to reach the ·ur-type
14384 * definition by repeatedly following the {base type definition}."
14385 *
14386 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14387 *
14388 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
14389 * must not have identical {name}s and {target namespace}s."
14390 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14391 * must not have {type definition}s which are or are derived from ID."
14392 *
14393 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14394 */
14395 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014396}
14397
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014398static int
14399xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14400 xmlSchemaTypePtr typeB)
14401{
14402 /*
14403 * TODO: This should implement component-identity
14404 * in the future.
14405 */
14406 if ((typeA == NULL) || (typeB == NULL))
14407 return (0);
14408 return (typeA == typeB);
14409}
14410
14411/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014412 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014413 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014414 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014415 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014416 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014417 *
14418 * Schema Component Constraint:
14419 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14420 *
14421 * STATUS: completed
14422 *
14423 * Returns 0 if the constraints are satisfied, or 1
14424 * if not.
14425 */
14426static int
14427xmlSchemaCheckCOSCTDerivedOK(xmlSchemaPtr schema,
14428 xmlSchemaTypePtr type,
14429 xmlSchemaTypePtr baseType,
14430 int set)
14431{
14432 int equal = xmlSchemaAreEqualTypes(type, baseType);
14433 /* TODO: Error codes. */
14434 /*
14435 * SPEC "For a complex type definition (call it D, for derived)
14436 * to be validly derived from a type definition (call this
14437 * B, for base) given a subset of {extension, restriction}
14438 * all of the following must be true:"
14439 */
14440 if (! equal) {
14441 /*
14442 * SPEC (1) "If B and D are not the same type definition, then the
14443 * {derivation method} of D must not be in the subset."
14444 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014445 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014446 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014447 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014448 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014449 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014450 } else {
14451 /*
14452 * SPEC (2.1) "B and D must be the same type definition."
14453 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014454 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014455 }
14456 /*
14457 * SPEC (2.2) "B must be D's {base type definition}."
14458 */
14459 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014460 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014461 /*
14462 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14463 * definition·."
14464 */
14465 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014466 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014467
14468 if (IS_COMPLEX_TYPE(type->baseType)) {
14469 /*
14470 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14471 * must be validly derived from B given the subset as defined by this
14472 * constraint."
14473 */
14474 return (xmlSchemaCheckCOSCTDerivedOK(schema, type->baseType,
14475 baseType, set));
14476 } else {
14477 /*
14478 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14479 * must be validly derived from B given the subset as defined in Type
14480 * Derivation OK (Simple) (§3.14.6).
14481 */
14482 return (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType,
14483 set));
14484 }
14485}
14486
14487/**
14488 * xmlSchemaCheckCOSDerivedOK:
14489 * @type: the derived simple type definition
14490 * @baseType: the base type definition
14491 *
14492 * Calls:
14493 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
14494 *
14495 * Checks wheter @type can be validly derived from @baseType.
14496 *
14497 * Returns 0 on success, an positive error code otherwise.
14498 */
14499static int
14500xmlSchemaCheckCOSDerivedOK(xmlSchemaPtr schema,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014501 xmlSchemaTypePtr type,
14502 xmlSchemaTypePtr baseType,
14503 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014504{
14505 if (IS_SIMPLE_TYPE(type))
14506 return (xmlSchemaCheckCOSSTDerivedOK(schema, type, baseType, set));
14507 else
14508 return (xmlSchemaCheckCOSCTDerivedOK(schema, type, baseType, set));
14509}
14510
William M. Brack2f2a6632004-08-20 23:09:47 +000014511/**
14512 * xmlSchemaCheckCOSCTExtends:
14513 * @ctxt: the schema parser context
14514 * @type: the complex type definition
14515 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014516 * (3.4.6) Constraints on Complex Type Definition Schema Components
14517 * Schema Component Constraint:
14518 * Derivation Valid (Extension) (cos-ct-extends)
14519 *
14520 * STATUS:
14521 * missing:
14522 * (1.5)
14523 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014524 *
14525 * Returns 0 if the constraints are satisfied, a positive
14526 * error code if not and -1 if an internal error occured.
14527 */
14528static int
14529xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14530 xmlSchemaTypePtr type)
14531{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014532 xmlSchemaTypePtr base = type->baseType;
14533 /*
14534 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14535 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014536 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014537 /*
14538 * SPEC (1) "If the {base type definition} is a complex type definition,
14539 * then all of the following must be true:"
14540 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014541 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14542 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014543 * SPEC (1.1) "The {final} of the {base type definition} must not
14544 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014545 */
14546 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14547 xmlSchemaPCustomErr(ctxt,
14548 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14549 NULL, type, NULL,
14550 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014551 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014552 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14553 }
14554 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014555 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
14556 * uses}
William M. Brack2f2a6632004-08-20 23:09:47 +000014557 * of the complex type definition itself, that is, for every attribute
14558 * use in the {attribute uses} of the {base type definition}, there
14559 * must be an attribute use in the {attribute uses} of the complex
14560 * type definition itself whose {attribute declaration} has the same
14561 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014562 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014563 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014564 * NOTE (1.2): This will be already satisfied by the way the attribute
14565 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14566 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014567 */
14568
14569 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014570 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14571 * definition must also have one, and the base type definition's
14572 * {attribute wildcard}'s {namespace constraint} must be a subset
14573 * of the complex type definition's {attribute wildcard}'s {namespace
14574 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014575 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014576 * NOTE (1.3) This is already checked in
14577 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014578 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014579 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014581 if ((type->contentTypeDef != NULL) &&
14582 (type->contentTypeDef == base->contentTypeDef)) {
14583 /*
14584 * SPEC (1.4.1) "The {content type} of the {base type definition}
14585 * and the {content type} of the complex type definition itself
14586 * must be the same simple type definition"
14587 * PASS
14588 */
14589 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14590 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14591 /*
14592 * SPEC (1.4.2) "The {content type} of both the {base type
14593 * definition} and the complex type definition itself must
14594 * be empty."
14595 * PASS
14596 */
14597 } else {
14598 /*
14599 * SPEC (1.4.3) "All of the following must be true:"
14600 */
14601 if (type->subtypes == NULL) {
14602 /*
14603 * SPEC 1.4.3.1 The {content type} of the complex type
14604 * definition itself must specify a particle.
14605 */
14606 xmlSchemaPCustomErr(ctxt,
14607 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14608 NULL, type, NULL,
14609 "The content type must specify a particle", NULL);
14610 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14611 }
14612 /*
14613 * SPEC (1.4.3.2) "One of the following must be true:"
14614 */
14615 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14616 /*
14617 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14618 * definition} must be empty.
14619 * PASS
14620 */
14621 } else {
14622 /*
14623 * SPEC (1.4.3.2.2) "All of the following must be true:"
14624 */
14625 if ((type->contentType != base->contentType) ||
14626 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14627 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14628 /*
14629 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14630 * or both must be element-only."
14631 */
14632 xmlSchemaPCustomErr(ctxt,
14633 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14634 NULL, type, NULL,
14635 "The content type of both, the type and its base "
14636 "type, must either 'mixed' or 'element-only'", NULL);
14637 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14638 }
14639 /*
14640 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14641 * complex type definition must be a ·valid extension·
14642 * of the {base type definition}'s particle, as defined
14643 * in Particle Valid (Extension) (§3.9.6)."
14644 *
14645 * NOTE that we won't check "Particle Valid (Extension)",
14646 * since it is ensured by the derivation process in
14647 * xmlSchemaTypeFixup(). We need to implement this when heading
14648 * for a construction API
14649 */
14650 }
14651 /*
14652 * TODO (1.5)
14653 */
14654 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014655 } else {
14656 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014657 * SPEC (2) "If the {base type definition} is a simple type definition,
14658 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014659 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014660 if (type->contentTypeDef != base) {
14661 /*
14662 * SPEC (2.1) "The {content type} must be the same simple type
14663 * definition."
14664 */
14665 xmlSchemaPCustomErr(ctxt,
14666 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14667 NULL, type, NULL,
14668 "The content type must be the simple base type", NULL);
14669 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14670 }
14671 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14672 /*
14673 * SPEC (2.2) "The {final} of the {base type definition} must not
14674 * contain extension"
14675 * NOTE that this is the same as (1.1).
14676 */
14677 xmlSchemaPCustomErr(ctxt,
14678 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14679 NULL, type, NULL,
14680 "The 'final' of the base type definition "
14681 "contains 'extension'", NULL);
14682 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14683 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014684 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014685 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014686}
14687
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014688/**
14689 * xmlSchemaCheckDerivationOKRestriction:
14690 * @ctxt: the schema parser context
14691 * @type: the complex type definition
14692 *
14693 * (3.4.6) Constraints on Complex Type Definition Schema Components
14694 * Schema Component Constraint:
14695 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14696 *
14697 * STATUS:
14698 * missing:
14699 * (5.4.2), (5.2.2.1)
14700 *
14701 * Returns 0 if the constraints are satisfied, a positive
14702 * error code if not and -1 if an internal error occured.
14703 */
14704static int
14705xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14706 xmlSchemaTypePtr type)
14707{
14708 xmlSchemaTypePtr base;
14709
14710 /*
14711 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14712 * temporarily only.
14713 */
14714 base = type->baseType;
14715 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14716 /*
14717 * SPEC (1) "The {base type definition} must be a complex type
14718 * definition whose {final} does not contain restriction."
14719 */
14720 xmlSchemaPCustomErr(ctxt,
14721 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14722 NULL, type, NULL,
14723 "The 'final' of the base type definition "
14724 "contains 'restriction'", NULL);
14725 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14726 }
14727 /*
14728 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14729 *
14730 * SPEC (5) "One of the following must be true:"
14731 */
14732 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14733 /*
14734 * SPEC (5.1) "The {base type definition} must be the
14735 * ·ur-type definition·."
14736 * PASS
14737 */
14738 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14739 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14740 /*
14741 * SPEC (5.2.1) "The {content type} of the complex type definition
14742 * must be a simple type definition"
14743 *
14744 * SPEC (5.2.2) "One of the following must be true:"
14745 */
14746 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14747 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14748 /*
14749 * SPEC (5.2.2.1) "The {content type} of the {base type
14750 * definition} must be a simple type definition from which
14751 * the {content type} is validly derived given the empty
14752 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14753 * URGENT TODO
14754 */
14755 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14756 (xmlSchemaIsParticleEmptiable(
14757 (xmlSchemaParticlePtr) base->subtypes))) {
14758 /*
14759 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14760 * and have a particle which is ·emptiable· as defined in
14761 * Particle Emptiable (§3.9.6)."
14762 * PASS
14763 */
14764 } else {
14765 xmlSchemaPCustomErr(ctxt,
14766 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14767 NULL, type, NULL,
14768 "The content type of the base type must be either "
14769 "a simple type or 'mixed' and an emptiable particle", NULL);
14770 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14771 }
14772 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14773 /*
14774 * SPEC (5.3.1) "The {content type} of the complex type itself must
14775 * be empty"
14776 */
14777 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14778 /*
14779 * SPEC (5.3.2.1) "The {content type} of the {base type
14780 * definition} must also be empty."
14781 * PASS
14782 */
14783 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14784 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14785 xmlSchemaIsParticleEmptiable(
14786 (xmlSchemaParticlePtr) base->subtypes)) {
14787 /*
14788 * SPEC (5.3.2.2) "The {content type} of the {base type
14789 * definition} must be elementOnly or mixed and have a particle
14790 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14791 * PASS
14792 */
14793 } else {
14794 xmlSchemaPCustomErr(ctxt,
14795 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14796 NULL, type, NULL,
14797 "The content type of the base type must be either "
14798 "empty or 'mixed' (or 'elements-only') and an emptiable "
14799 "particle", NULL);
14800 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14801 }
14802 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14803 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14804 (base->contentType == XML_SCHEMA_CONTENT_MIXED))) {
14805 /*
14806 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14807 * itself must be element-only"
14808 * SPEC (5.4.1.2) "The {content type} of the complex type definition
14809 * itself and of the {base type definition} must be mixed"
14810 */
14811 /*
14812 * SPEC (5.4.2) "The particle of the complex type definition itself
14813 * must be a ·valid restriction· of the particle of the {content
14814 * type} of the {base type definition} as defined in Particle Valid
14815 * (Restriction) (§3.9.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014816 * URGENT TODO: (5.4.2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014817 */
14818 } else {
14819 xmlSchemaPCustomErr(ctxt,
14820 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14821 NULL, type, NULL,
14822 "The type is not a valid restriction of its base type", NULL);
14823 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14824 }
14825 return (0);
14826}
14827
14828/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014829 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014830 * @ctxt: the schema parser context
14831 * @type: the complex type definition
14832 *
14833 * (3.4.6) Constraints on Complex Type Definition Schema Components
14834 *
14835 * Returns 0 if the constraints are satisfied, a positive
14836 * error code if not and -1 if an internal error occured.
14837 */
14838static int
14839xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14840 xmlSchemaTypePtr type)
14841{
14842 int ret;
14843 /*
14844 * Complex Type Definition Properties Correct
14845 */
14846 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14847 if (ret != 0)
14848 return (ret);
14849 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14850 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14851 else
14852 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14853 return (ret);
14854}
14855
14856/**
14857 * xmlSchemaCheckSRCCT:
14858 * @ctxt: the schema parser context
14859 * @type: the complex type definition
14860 *
14861 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
14862 * Schema Representation Constraint:
14863 * Complex Type Definition Representation OK (src-ct)
14864 *
14865 * Returns 0 if the constraints are satisfied, a positive
14866 * error code if not and -1 if an internal error occured.
14867 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014868static int
14869xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
14870 xmlSchemaTypePtr type)
14871{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014872 xmlSchemaTypePtr base;
14873 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014874
14875 /*
14876 * TODO: Adjust the error codes here, as I used
14877 * XML_SCHEMAP_SRC_CT_1 only yet.
14878 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014879 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014880 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014881 /*
14882 * 1 If the <complexContent> alternative is chosen, the type definition
14883 * ·resolved· to by the ·actual value· of the base [attribute]
14884 * must be a complex type definition;
14885 */
14886 if (! IS_COMPLEX_TYPE(base)) {
14887 xmlChar *str = NULL;
14888 xmlSchemaPCustomErr(ctxt,
14889 XML_SCHEMAP_SRC_CT_1,
14890 NULL, type, type->node,
14891 "If using <complexContent>, the base type is expected to be "
14892 "a complex type. The base type '%s' is a simple type",
14893 xmlSchemaFormatQName(&str, base->targetNamespace,
14894 base->name));
14895 FREE_AND_NULL(str)
14896 return (XML_SCHEMAP_SRC_CT_1);
14897 }
14898 } else {
14899 /*
14900 * SPEC
14901 * 2 If the <simpleContent> alternative is chosen, all of the
14902 * following must be true:
14903 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14904 * base [attribute] must be one of the following:
14905 */
14906 if (IS_SIMPLE_TYPE(base)) {
14907 if ((type->flags &
14908 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14909 xmlChar *str = NULL;
14910 /*
14911 * 2.1.3 only if the <extension> alternative is also
14912 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014913 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014914 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014915 xmlSchemaPCustomErr(ctxt,
14916 XML_SCHEMAP_SRC_CT_1,
14917 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014918 "If using <simpleContent> and <restriction>, the base "
14919 "type must be a complex type. The base type '%s' is "
14920 "a simple type",
14921 xmlSchemaFormatQName(&str, base->targetNamespace,
14922 base->name));
14923 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014924 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014925 }
14926 } else {
14927 /* Base type is a complex type. */
14928 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14929 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14930 /*
14931 * 2.1.1 a complex type definition whose {content type} is a
14932 * simple type definition;
14933 * PASS
14934 */
14935 if (base->contentTypeDef == NULL) {
14936 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014937 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014938 "Internal error: xmlSchemaCheckSRCCT, "
14939 "'%s', base type has no content type",
14940 type->name);
14941 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014942 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014943 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14944 (type->flags &
14945 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014946
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014947 /*
14948 * 2.1.2 only if the <restriction> alternative is also
14949 * chosen, a complex type definition whose {content type}
14950 * is mixed and a particle emptiable.
14951 */
14952 if (! xmlSchemaIsParticleEmptiable(
14953 (xmlSchemaParticlePtr) base->subtypes)) {
14954 ret = XML_SCHEMAP_SRC_CT_1;
14955 } else if ((type->contentTypeDef == NULL) ||
14956 (type->contentTypeDef->baseType == NULL)) {
14957 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014958 /*
14959 * 2.2 If clause 2.1.2 above is satisfied, then there
14960 * must be a <simpleType> among the [children] of
14961 * <restriction>.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014962 */
14963 /* TODO: Change error code to ..._SRC_CT_2_2. */
14964 xmlSchemaPCustomErr(ctxt,
14965 XML_SCHEMAP_SRC_CT_1,
14966 NULL, type, NULL,
14967 "A <simpleType> is expected among the children "
14968 "of <restriction>, if <simpleContent> is used and "
14969 "the base type '%s' is a complex type",
14970 xmlSchemaFormatQName(&str, base->targetNamespace,
14971 base->name));
14972 FREE_AND_NULL(str)
14973 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014974 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014975 } else {
14976 ret = XML_SCHEMAP_SRC_CT_1;
14977 }
14978 }
14979 if (ret > 0) {
14980 xmlChar *str = NULL;
14981 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
14982 xmlSchemaPCustomErr(ctxt,
14983 XML_SCHEMAP_SRC_CT_1,
14984 NULL, type, NULL,
14985 "If <simpleContent> and <restriction> is used, the "
14986 "base type must be a simple type or a complex type with "
14987 "mixed content and particle emptiable. The base type "
14988 "'%s' is none of those",
14989 xmlSchemaFormatQName(&str, base->targetNamespace,
14990 base->name));
14991 } else {
14992 xmlSchemaPCustomErr(ctxt,
14993 XML_SCHEMAP_SRC_CT_1,
14994 NULL, type, NULL,
14995 "If <simpleContent> and <extension> is used, the "
14996 "base type must be a simple type. The base type '%s' "
14997 "is a complex type",
14998 xmlSchemaFormatQName(&str, base->targetNamespace,
14999 base->name));
15000 }
15001 FREE_AND_NULL(str)
15002 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015003 }
15004 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015005 * SPEC (3) "The corresponding complex type definition component must
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015006 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015007 * Definition Schema Components (§3.4.6);"
15008 * NOTE (3) will be done in xmlSchemaTypeFixup().
15009 */
15010 /*
15011 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015012 * above for {attribute wildcard} is satisfied, the intensional
15013 * intersection must be expressible, as defined in Attribute Wildcard
15014 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015015 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015016 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015017 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015018}
William M. Brack2f2a6632004-08-20 23:09:47 +000015019
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015020#ifdef ENABLE_PARTICLE_RESTRICTION
15021/**
15022 * xmlSchemaCheckParticleRangeOK:
15023 * @ctxt: the schema parser context
15024 * @type: the complex type definition
15025 *
15026 * (3.9.6) Constraints on Particle Schema Components
15027 * Schema Component Constraint:
15028 * Occurrence Range OK (range-ok)
15029 *
15030 * STATUS: complete
15031 *
15032 * Returns 0 if the constraints are satisfied, a positive
15033 * error code if not and -1 if an internal error occured.
15034 */
15035static int
15036xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
15037 int bmin, int bmax)
15038{
15039 if (rmin < bmin)
15040 return (1);
15041 if ((bmax != UNBOUNDED) &&
15042 (rmax > bmax))
15043 return (1);
15044 return (0);
15045}
15046
15047/**
15048 * xmlSchemaCheckRCaseNameAndTypeOK:
15049 * @ctxt: the schema parser context
15050 * @r: the restricting element declaration particle
15051 * @b: the base element declaration particle
15052 *
15053 * (3.9.6) Constraints on Particle Schema Components
15054 * Schema Component Constraint:
15055 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
15056 * (rcase-NameAndTypeOK)
15057 *
15058 * STATUS:
15059 * MISSING (3.2.3)
15060 * CLARIFY: (3.2.2)
15061 *
15062 * Returns 0 if the constraints are satisfied, a positive
15063 * error code if not and -1 if an internal error occured.
15064 */
15065static int
15066xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
15067 xmlSchemaParticlePtr r,
15068 xmlSchemaParticlePtr b)
15069{
15070 xmlSchemaElementPtr elemR, elemB;
15071
15072 /* TODO: Error codes (rcase-NameAndTypeOK). */
15073 elemR = (xmlSchemaElementPtr) r->children;
15074 elemB = (xmlSchemaElementPtr) b->children;
15075 /*
15076 * SPEC (1) "The declarations' {name}s and {target namespace}s are
15077 * the same."
15078 */
15079 if ((elemR != elemB) &&
15080 ((! xmlStrEqual(elemR->name, elemB->name)) ||
15081 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
15082 return (1);
15083 /*
15084 * SPEC (2) "R's occurrence range is a valid restriction of B's
15085 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15086 */
15087 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15088 b->minOccurs, b->maxOccurs) != 0)
15089 return (1);
15090 /*
15091 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
15092 * {scope} are global."
15093 */
15094 if (elemR == elemB)
15095 return (0);
15096 /*
15097 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
15098 */
15099 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
15100 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
15101 return (1);
15102 /*
15103 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
15104 * or is not fixed, or R's declaration's {value constraint} is fixed
15105 * with the same value."
15106 */
15107 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
15108 ((elemR->value == NULL) ||
15109 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
15110 /* TODO: Equality of the initial value or normalized or canonical? */
15111 (! xmlStrEqual(elemR->value, elemB->value))))
15112 return (1);
15113 /*
15114 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
15115 * definitions} is a subset of B's declaration's {identity-constraint
15116 * definitions}, if any."
15117 */
15118 if (elemB->idcs != NULL) {
15119 /* TODO */
15120 }
15121 /*
15122 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
15123 * superset of B's declaration's {disallowed substitutions}."
15124 */
15125 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
15126 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
15127 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
15128 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
15129 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
15130 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
15131 return (1);
15132 /*
15133 * SPEC (3.2.5) "R's {type definition} is validly derived given
15134 * {extension, list, union} from B's {type definition}"
15135 *
15136 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15137 * set, if the corresponding constraints handle "restriction" and
15138 * "extension" only?
15139 *
15140 */
15141 {
15142 int set = 0;
15143
15144 set |= SUBSET_EXTENSION;
15145 set |= SUBSET_LIST;
15146 set |= SUBSET_UNION;
15147 if (xmlSchemaCheckCOSDerivedOK(ctxt->schema, elemR->subtypes,
15148 elemB->subtypes, set) != 0)
15149 return (1);
15150 }
15151 return (0);
15152}
15153
15154/**
15155 * xmlSchemaCheckRCaseNSCompat:
15156 * @ctxt: the schema parser context
15157 * @r: the restricting element declaration particle
15158 * @b: the base wildcard particle
15159 *
15160 * (3.9.6) Constraints on Particle Schema Components
15161 * Schema Component Constraint:
15162 * Particle Derivation OK (Elt:Any -- NSCompat)
15163 * (rcase-NSCompat)
15164 *
15165 * STATUS: complete
15166 *
15167 * Returns 0 if the constraints are satisfied, a positive
15168 * error code if not and -1 if an internal error occured.
15169 */
15170static int
15171xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15172 xmlSchemaParticlePtr r,
15173 xmlSchemaParticlePtr b)
15174{
15175 /* TODO:Error codes (rcase-NSCompat). */
15176 /*
15177 * SPEC "For an element declaration particle to be a ·valid restriction·
15178 * of a wildcard particle all of the following must be true:"
15179 *
15180 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15181 * with respect to the wildcard's {namespace constraint} as defined by
15182 * Wildcard allows Namespace Name (§3.10.4)."
15183 */
15184 if (xmlSchemaMatchesWildcardNs((xmlSchemaWildcardPtr) b->children,
15185 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15186 return (1);
15187 /*
15188 * SPEC (2) "R's occurrence range is a valid restriction of B's
15189 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15190 */
15191 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15192 b->minOccurs, b->maxOccurs) != 0)
15193 return (1);
15194
15195 return (0);
15196}
15197
15198/**
15199 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15200 * @ctxt: the schema parser context
15201 * @r: the restricting element declaration particle
15202 * @b: the base model group particle
15203 *
15204 * (3.9.6) Constraints on Particle Schema Components
15205 * Schema Component Constraint:
15206 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15207 * (rcase-RecurseAsIfGroup)
15208 *
15209 * STATUS: TODO
15210 *
15211 * Returns 0 if the constraints are satisfied, a positive
15212 * error code if not and -1 if an internal error occured.
15213 */
15214static int
15215xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15216 xmlSchemaParticlePtr r,
15217 xmlSchemaParticlePtr b)
15218{
15219 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15220 TODO
15221 return (0);
15222}
15223
15224/**
15225 * xmlSchemaCheckRCaseNSSubset:
15226 * @ctxt: the schema parser context
15227 * @r: the restricting wildcard particle
15228 * @b: the base wildcard particle
15229 *
15230 * (3.9.6) Constraints on Particle Schema Components
15231 * Schema Component Constraint:
15232 * Particle Derivation OK (Any:Any -- NSSubset)
15233 * (rcase-NSSubset)
15234 *
15235 * STATUS: complete
15236 *
15237 * Returns 0 if the constraints are satisfied, a positive
15238 * error code if not and -1 if an internal error occured.
15239 */
15240static int
15241xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15242 xmlSchemaParticlePtr r,
15243 xmlSchemaParticlePtr b,
15244 int isAnyTypeBase)
15245{
15246 /* TODO: Error codes (rcase-NSSubset). */
15247 /*
15248 * SPEC (1) "R's occurrence range is a valid restriction of B's
15249 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15250 */
15251 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15252 b->minOccurs, b->maxOccurs))
15253 return (1);
15254 /*
15255 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15256 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15257 */
15258 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15259 (xmlSchemaWildcardPtr) b->children))
15260 return (1);
15261 /*
15262 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15263 * definition·, R's {process contents} must be identical to or stronger
15264 * than B's {process contents}, where strict is stronger than lax is
15265 * stronger than skip."
15266 */
15267 if (! isAnyTypeBase) {
15268 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15269 ((xmlSchemaWildcardPtr) b->children)->processContents)
15270 return (1);
15271 }
15272
15273 return (0);
15274}
15275
15276/**
15277 * xmlSchemaCheckCOSParticleRestrict:
15278 * @ctxt: the schema parser context
15279 * @type: the complex type definition
15280 *
15281 * (3.9.6) Constraints on Particle Schema Components
15282 * Schema Component Constraint:
15283 * Particle Valid (Restriction) (cos-particle-restrict)
15284 *
15285 * STATUS: TODO
15286 *
15287 * Returns 0 if the constraints are satisfied, a positive
15288 * error code if not and -1 if an internal error occured.
15289 */
15290static int
15291xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15292 xmlSchemaParticlePtr r,
15293 xmlSchemaParticlePtr b)
15294{
15295 int ret = 0;
15296
15297 /*part = GET_PARTICLE(type);
15298 basePart = GET_PARTICLE(base);
15299 */
15300
15301 TODO
15302
15303 /*
15304 * SPEC (1) "They are the same particle."
15305 */
15306 if (r == b)
15307 return (0);
15308
15309
15310 return (0);
15311}
15312
15313/**
15314 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15315 * @ctxt: the schema parser context
15316 * @r: the model group particle
15317 * @b: the base wildcard particle
15318 *
15319 * (3.9.6) Constraints on Particle Schema Components
15320 * Schema Component Constraint:
15321 * Particle Derivation OK (All/Choice/Sequence:Any --
15322 * NSRecurseCheckCardinality)
15323 * (rcase-NSRecurseCheckCardinality)
15324 *
15325 * STATUS: TODO: subst-groups
15326 *
15327 * Returns 0 if the constraints are satisfied, a positive
15328 * error code if not and -1 if an internal error occured.
15329 */
15330static int
15331xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15332 xmlSchemaParticlePtr r,
15333 xmlSchemaParticlePtr b)
15334{
15335 xmlSchemaParticlePtr part;
15336 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15337 if ((r->children == NULL) || (r->children->children == NULL))
15338 return (-1);
15339 /*
15340 * SPEC "For a group particle to be a ·valid restriction· of a
15341 * wildcard particle..."
15342 *
15343 * SPEC (1) "Every member of the {particles} of the group is a ·valid
15344 * restriction· of the wildcard as defined by
15345 * Particle Valid (Restriction) (§3.9.6)."
15346 */
15347 part = (xmlSchemaParticlePtr) r->children->children;
15348 do {
15349 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15350 return (1);
15351 part = (xmlSchemaParticlePtr) part->next;
15352 } while (part != NULL);
15353 /*
15354 * SPEC (2) "The effective total range of the group [...] is a
15355 * valid restriction of B's occurrence range as defined by
15356 * Occurrence Range OK (§3.9.6)."
15357 */
15358 if (xmlSchemaCheckParticleRangeOK(
15359 xmlSchemaGetParticleTotalRangeMin(r),
15360 xmlSchemaGetParticleTotalRangeMax(r),
15361 b->minOccurs, b->maxOccurs) != 0)
15362 return (1);
15363 return (0);
15364}
15365
15366/**
15367 * xmlSchemaCheckRCaseRecurse:
15368 * @ctxt: the schema parser context
15369 * @r: the <all> or <sequence> model group particle
15370 * @b: the base <all> or <sequence> model group particle
15371 *
15372 * (3.9.6) Constraints on Particle Schema Components
15373 * Schema Component Constraint:
15374 * Particle Derivation OK (All:All,Sequence:Sequence --
15375 Recurse)
15376 * (rcase-Recurse)
15377 *
15378 * STATUS: ?
15379 * TODO: subst-groups
15380 *
15381 * Returns 0 if the constraints are satisfied, a positive
15382 * error code if not and -1 if an internal error occured.
15383 */
15384static int
15385xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15386 xmlSchemaParticlePtr r,
15387 xmlSchemaParticlePtr b)
15388{
15389 /* xmlSchemaParticlePtr part; */
15390 /* TODO: Error codes (rcase-Recurse). */
15391 if ((r->children == NULL) || (b->children == NULL) ||
15392 (r->children->type != b->children->type))
15393 return (-1);
15394 /*
15395 * SPEC "For an all or sequence group particle to be a ·valid
15396 * restriction· of another group particle with the same {compositor}..."
15397 *
15398 * SPEC (1) "R's occurrence range is a valid restriction of B's
15399 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15400 */
15401 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15402 b->minOccurs, b->maxOccurs))
15403 return (1);
15404
15405
15406 return (0);
15407}
15408
15409#endif
15410
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015411#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15412 xmlSchemaPCustomErrExt(pctxt, \
15413 XML_SCHEMAP_INVALID_FACET_VALUE, \
15414 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15415 "It is an error for both '%s' and '%s' to be specified on the "\
15416 "same type definition", \
15417 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15418 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15419
15420#define FACET_RESTR_ERR(fac1, msg) \
15421 xmlSchemaPCustomErr(pctxt, \
15422 XML_SCHEMAP_INVALID_FACET_VALUE, \
15423 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15424 msg, NULL);
15425
15426#define FACET_RESTR_FIXED_ERR(fac) \
15427 xmlSchemaPCustomErr(pctxt, \
15428 XML_SCHEMAP_INVALID_FACET_VALUE, \
15429 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15430 "The base type's facet is 'fixed', thus the value must not " \
15431 "differ", NULL);
15432
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015433static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015434xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15435 xmlSchemaFacetPtr facet1,
15436 xmlSchemaFacetPtr facet2,
15437 int lessGreater,
15438 int orEqual,
15439 int ofBase)
15440{
15441 xmlChar *msg = NULL;
15442
15443 msg = xmlStrdup(BAD_CAST "'");
15444 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15445 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15446 if (lessGreater == 0)
15447 msg = xmlStrcat(msg, BAD_CAST " equal to");
15448 if (lessGreater == 1)
15449 msg = xmlStrcat(msg, BAD_CAST " greater than");
15450 else
15451 msg = xmlStrcat(msg, BAD_CAST " less than");
15452
15453 if (orEqual)
15454 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15455 msg = xmlStrcat(msg, BAD_CAST " '");
15456 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15457 if (ofBase)
15458 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15459 else
15460 msg = xmlStrcat(msg, BAD_CAST "'");
15461
15462 xmlSchemaPCustomErr(pctxt,
15463 XML_SCHEMAP_INVALID_FACET_VALUE,
15464 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
15465 (const char *) msg, NULL);
15466
15467 if (msg != NULL)
15468 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015469}
15470
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015471static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015472xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15473 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015474{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015475 xmlSchemaTypePtr base = type->baseType;
15476 xmlSchemaFacetLinkPtr link, cur, last = NULL;
15477 xmlSchemaFacetPtr facet, bfacet,
15478 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15479 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15480 fmininc = NULL, fmaxinc = NULL,
15481 fminexc = NULL, fmaxexc = NULL,
15482 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15483 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15484 bfmininc = NULL, bfmaxinc = NULL,
15485 bfminexc = NULL, bfmaxexc = NULL;
15486 int res, err = 0, fixedErr;
15487 /*
15488 * 3 The {facets} of R are the union of S and the {facets}
15489 * of B, eliminating duplicates. To eliminate duplicates,
15490 * when a facet of the same kind occurs in both S and the
15491 * {facets} of B, the one in the {facets} of B is not
15492 * included, with the exception of enumeration and pattern
15493 * facets, for which multiple occurrences with distinct values
15494 * are allowed.
15495 */
15496 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15497 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015498
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015499 last = type->facetSet;
15500 if (last != NULL)
15501 while (last->next != NULL)
15502 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015503
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015504 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15505 facet = cur->facet;
15506 switch (facet->type) {
15507 case XML_SCHEMA_FACET_LENGTH:
15508 flength = facet; break;
15509 case XML_SCHEMA_FACET_MINLENGTH:
15510 fminlen = facet; break;
15511 case XML_SCHEMA_FACET_MININCLUSIVE:
15512 fmininc = facet; break;
15513 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15514 fminexc = facet; break;
15515 case XML_SCHEMA_FACET_MAXLENGTH:
15516 fmaxlen = facet; break;
15517 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15518 fmaxinc = facet; break;
15519 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15520 fmaxexc = facet; break;
15521 case XML_SCHEMA_FACET_TOTALDIGITS:
15522 ftotdig = facet; break;
15523 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15524 ffracdig = facet; break;
15525 default:
15526 break;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015527 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015528 }
15529 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15530 facet = cur->facet;
15531 switch (facet->type) {
15532 case XML_SCHEMA_FACET_LENGTH:
15533 bflength = facet; break;
15534 case XML_SCHEMA_FACET_MINLENGTH:
15535 bfminlen = facet; break;
15536 case XML_SCHEMA_FACET_MININCLUSIVE:
15537 bfmininc = facet; break;
15538 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15539 bfminexc = facet; break;
15540 case XML_SCHEMA_FACET_MAXLENGTH:
15541 bfmaxlen = facet; break;
15542 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15543 bfmaxinc = facet; break;
15544 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15545 bfmaxexc = facet; break;
15546 case XML_SCHEMA_FACET_TOTALDIGITS:
15547 bftotdig = facet; break;
15548 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15549 bffracdig = facet; break;
15550 default:
15551 break;
15552 }
15553 }
15554 err = 0;
15555 /*
15556 * length and minLength or maxLength (2.2) + (3.2)
15557 */
15558 if (flength && (fminlen || fmaxlen)) {
15559 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15560 "either of 'minLength' or 'maxLength' to be specified on "
15561 "the same type definition")
15562 }
15563 /*
15564 * Mutual exclusions in the same derivation step.
15565 */
15566 if ((fmaxinc) && (fmaxexc)) {
15567 /*
15568 * SCC "maxInclusive and maxExclusive"
15569 */
15570 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15571 }
15572 if ((fmininc) && (fminexc)) {
15573 /*
15574 * SCC "minInclusive and minExclusive"
15575 */
15576 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015577 }
15578
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015579 if (flength && bflength) {
15580 /*
15581 * SCC "length valid restriction"
15582 * The values have to be equal.
15583 */
15584 res = xmlSchemaCompareValues(flength->val, bflength->val);
15585 if (res == -2)
15586 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015587 if (res != 0)
15588 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15589 if ((res != 0) && (bflength->fixed)) {
15590 FACET_RESTR_FIXED_ERR(flength)
15591 }
15592
15593 }
15594 if (fminlen && bfminlen) {
15595 /*
15596 * SCC "minLength valid restriction"
15597 * minLength >= BASE minLength
15598 */
15599 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15600 if (res == -2)
15601 goto internal_error;
15602 if (res == -1)
15603 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15604 if ((res != 0) && (bfminlen->fixed)) {
15605 FACET_RESTR_FIXED_ERR(fminlen)
15606 }
15607 }
15608 if (fmaxlen && bfmaxlen) {
15609 /*
15610 * SCC "maxLength valid restriction"
15611 * maxLength <= BASE minLength
15612 */
15613 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15614 if (res == -2)
15615 goto internal_error;
15616 if (res == 1)
15617 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15618 if ((res != 0) && (bfmaxlen->fixed)) {
15619 FACET_RESTR_FIXED_ERR(fmaxlen)
15620 }
15621 }
15622 /*
15623 * SCC "length and minLength or maxLength"
15624 */
15625 if (! flength)
15626 flength = bflength;
15627 if (flength) {
15628 if (! fminlen)
15629 flength = bflength;
15630 if (fminlen) {
15631 /* (1.1) length >= minLength */
15632 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15633 if (res == -2)
15634 goto internal_error;
15635 if (res == -1)
15636 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15637 }
15638 if (! fmaxlen)
15639 fmaxlen = bfmaxlen;
15640 if (fmaxlen) {
15641 /* (2.1) length <= maxLength */
15642 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15643 if (res == -2)
15644 goto internal_error;
15645 if (res == 1)
15646 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15647 }
15648 }
15649 if (fmaxinc) {
15650 /*
15651 * "maxInclusive"
15652 */
15653 if (fmininc) {
15654 /* SCC "maxInclusive >= minInclusive" */
15655 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15656 if (res == -2)
15657 goto internal_error;
15658 if (res == -1) {
15659 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15660 }
15661 }
15662 /*
15663 * SCC "maxInclusive valid restriction"
15664 */
15665 if (bfmaxinc) {
15666 /* maxInclusive <= BASE maxInclusive */
15667 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15668 if (res == -2)
15669 goto internal_error;
15670 if (res == 1)
15671 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15672 if ((res != 0) && (bfmaxinc->fixed)) {
15673 FACET_RESTR_FIXED_ERR(fmaxinc)
15674 }
15675 }
15676 if (bfmaxexc) {
15677 /* maxInclusive < BASE maxExclusive */
15678 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15679 if (res == -2)
15680 goto internal_error;
15681 if (res != -1) {
15682 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15683 }
15684 }
15685 if (bfmininc) {
15686 /* maxInclusive >= BASE minInclusive */
15687 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15688 if (res == -2)
15689 goto internal_error;
15690 if (res == -1) {
15691 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15692 }
15693 }
15694 if (bfminexc) {
15695 /* maxInclusive > BASE minExclusive */
15696 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15697 if (res == -2)
15698 goto internal_error;
15699 if (res != 1) {
15700 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15701 }
15702 }
15703 }
15704 if (fmaxexc) {
15705 /*
15706 * "maxExclusive >= minExclusive"
15707 */
15708 if (fminexc) {
15709 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15710 if (res == -2)
15711 goto internal_error;
15712 if (res == -1) {
15713 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15714 }
15715 }
15716 /*
15717 * "maxExclusive valid restriction"
15718 */
15719 if (bfmaxexc) {
15720 /* maxExclusive <= BASE maxExclusive */
15721 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15722 if (res == -2)
15723 goto internal_error;
15724 if (res == 1) {
15725 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15726 }
15727 if ((res != 0) && (bfmaxexc->fixed)) {
15728 FACET_RESTR_FIXED_ERR(fmaxexc)
15729 }
15730 }
15731 if (bfmaxinc) {
15732 /* maxExclusive <= BASE maxInclusive */
15733 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15734 if (res == -2)
15735 goto internal_error;
15736 if (res == 1) {
15737 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15738 }
15739 }
15740 if (bfmininc) {
15741 /* maxExclusive > BASE minInclusive */
15742 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15743 if (res == -2)
15744 goto internal_error;
15745 if (res != 1) {
15746 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15747 }
15748 }
15749 if (bfminexc) {
15750 /* maxExclusive > BASE minExclusive */
15751 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15752 if (res == -2)
15753 goto internal_error;
15754 if (res != 1) {
15755 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15756 }
15757 }
15758 }
15759 if (fminexc) {
15760 /*
15761 * "minExclusive < maxInclusive"
15762 */
15763 if (fmaxinc) {
15764 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15765 if (res == -2)
15766 goto internal_error;
15767 if (res != -1) {
15768 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15769 }
15770 }
15771 /*
15772 * "minExclusive valid restriction"
15773 */
15774 if (bfminexc) {
15775 /* minExclusive >= BASE minExclusive */
15776 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15777 if (res == -2)
15778 goto internal_error;
15779 if (res == -1) {
15780 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15781 }
15782 if ((res != 0) && (bfminexc->fixed)) {
15783 FACET_RESTR_FIXED_ERR(fminexc)
15784 }
15785 }
15786 if (bfmaxinc) {
15787 /* minExclusive <= BASE maxInclusive */
15788 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15789 if (res == -2)
15790 goto internal_error;
15791 if (res == 1) {
15792 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15793 }
15794 }
15795 if (bfmininc) {
15796 /* minExclusive >= BASE minInclusive */
15797 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15798 if (res == -2)
15799 goto internal_error;
15800 if (res == -1) {
15801 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15802 }
15803 }
15804 if (bfmaxexc) {
15805 /* minExclusive < BASE maxExclusive */
15806 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15807 if (res == -2)
15808 goto internal_error;
15809 if (res != -1) {
15810 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15811 }
15812 }
15813 }
15814 if (fmininc) {
15815 /*
15816 * "minInclusive < maxExclusive"
15817 */
15818 if (fmaxexc) {
15819 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15820 if (res == -2)
15821 goto internal_error;
15822 if (res != -1) {
15823 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15824 }
15825 }
15826 /*
15827 * "minExclusive valid restriction"
15828 */
15829 if (bfmininc) {
15830 /* minInclusive >= BASE minInclusive */
15831 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15832 if (res == -2)
15833 goto internal_error;
15834 if (res == -1) {
15835 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15836 }
15837 if ((res != 0) && (bfmininc->fixed)) {
15838 FACET_RESTR_FIXED_ERR(fmininc)
15839 }
15840 }
15841 if (bfmaxinc) {
15842 /* minInclusive <= BASE maxInclusive */
15843 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15844 if (res == -2)
15845 goto internal_error;
15846 if (res == -1) {
15847 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15848 }
15849 }
15850 if (bfminexc) {
15851 /* minInclusive > BASE minExclusive */
15852 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15853 if (res == -2)
15854 goto internal_error;
15855 if (res != 1)
15856 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15857 }
15858 if (bfmaxexc) {
15859 /* minInclusive < BASE maxExclusive */
15860 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15861 if (res == -2)
15862 goto internal_error;
15863 if (res != -1)
15864 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15865 }
15866 }
15867 if (ftotdig && bftotdig) {
15868 /*
15869 * SCC " totalDigits valid restriction"
15870 * totalDigits <= BASE totalDigits
15871 */
15872 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15873 if (res == -2)
15874 goto internal_error;
15875 if (res == 1)
15876 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15877 -1, 1, 1);
15878 if ((res != 0) && (bftotdig->fixed)) {
15879 FACET_RESTR_FIXED_ERR(ftotdig)
15880 }
15881 }
15882 if (ffracdig && bffracdig) {
15883 /*
15884 * SCC "fractionDigits valid restriction"
15885 * fractionDigits <= BASE fractionDigits
15886 */
15887 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15888 if (res == -2)
15889 goto internal_error;
15890 if (res == 1)
15891 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15892 -1, 1, 1);
15893 if ((res != 0) && (bffracdig->fixed)) {
15894 FACET_RESTR_FIXED_ERR(ffracdig)
15895 }
15896 }
15897 /*
15898 * SCC "fractionDigits less than or equal to totalDigits"
15899 */
15900 if (! ftotdig)
15901 ftotdig = bftotdig;
15902 if (! ffracdig)
15903 ffracdig = bffracdig;
15904 if (ftotdig && ffracdig) {
15905 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15906 if (res == -2)
15907 goto internal_error;
15908 if (res == 1)
15909 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15910 -1, 1, 0);
15911 }
15912 /*
15913 * *Enumerations* won' be added here, since only the first set
15914 * of enumerations in the ancestor-or-self axis is used
15915 * for validation, plus we need to use the base type of those
15916 * enumerations for whitespace.
15917 *
15918 * *Patterns*: won't be add here, since they are ORed at
15919 * type level and ANDed at ancestor level. This will
15920 * happed during validation by walking the base axis
15921 * of the type.
15922 */
15923 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15924 bfacet = cur->facet;
15925 /*
15926 * Special handling of enumerations and patterns.
15927 * TODO: hmm, they should not appear in the set, so remove this.
15928 */
15929 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
15930 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
15931 continue;
15932 /*
15933 * Search for a duplicate facet in the current type.
15934 */
15935 link = type->facetSet;
15936 err = 0;
15937 fixedErr = 0;
15938 while (link != NULL) {
15939 facet = link->facet;
15940 if (facet->type == bfacet->type) {
15941 switch (facet->type) {
15942 case XML_SCHEMA_FACET_WHITESPACE:
15943 /*
15944 * The whitespace must be stronger.
15945 */
15946 if (facet->whitespace < bfacet->whitespace) {
15947 FACET_RESTR_ERR(flength,
15948 "The 'whitespace' value has to be equal to "
15949 "or stronger than the 'whitespace' value of "
15950 "the base type")
15951 }
15952 if ((bfacet->fixed) &&
15953 (facet->whitespace != bfacet->whitespace)) {
15954 FACET_RESTR_FIXED_ERR(facet)
15955 }
15956 break;
15957 default:
15958 break;
15959 }
15960 /* Duplicate found. */
15961 break;
15962 }
15963 link = link->next;
15964 }
15965 /*
15966 * If no duplicate was found: add the base types's facet
15967 * to the set.
15968 */
15969 if (link == NULL) {
15970 link = (xmlSchemaFacetLinkPtr)
15971 xmlMalloc(sizeof(xmlSchemaFacetLink));
15972 if (link == NULL) {
15973 xmlSchemaPErrMemory(pctxt,
15974 "deriving facets, creating a facet link", NULL);
15975 return (-1);
15976 }
15977 link->facet = cur->facet;
15978 link->next = NULL;
15979 if (last == NULL)
15980 type->facetSet = link;
15981 else
15982 last->next = link;
15983 last = link;
15984 }
15985
15986 }
15987
15988 return (0);
15989internal_error:
15990 xmlSchemaPCustomErr(pctxt,
15991 XML_SCHEMAP_INVALID_FACET_VALUE,
15992 NULL, type, NULL,
15993 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15994 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015995}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015996
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015997static int
15998xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15999 xmlSchemaTypePtr type)
16000{
16001 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
16002 /*
16003 * The actual value is then formed by replacing any union type
16004 * definition in the ·explicit members· with the members of their
16005 * {member type definitions}, in order.
16006 */
16007 link = type->memberTypes;
16008 while (link != NULL) {
16009
16010 if (IS_NOT_TYPEFIXED(link->type))
16011 xmlSchemaTypeFixup(link->type, pctxt, NULL);
16012
16013 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16014 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
16015 if (subLink != NULL) {
16016 link->type = subLink->type;
16017 if (subLink->next != NULL) {
16018 lastLink = link->next;
16019 subLink = subLink->next;
16020 prevLink = link;
16021 while (subLink != NULL) {
16022 newLink = (xmlSchemaTypeLinkPtr)
16023 xmlMalloc(sizeof(xmlSchemaTypeLink));
16024 if (newLink == NULL) {
16025 xmlSchemaPErrMemory(pctxt, "allocating a type link",
16026 NULL);
16027 return (-1);
16028 }
16029 newLink->type = subLink->type;
16030 prevLink->next = newLink;
16031 prevLink = newLink;
16032 newLink->next = lastLink;
16033
16034 subLink = subLink->next;
16035 }
16036 }
16037 }
16038 }
16039 link = link->next;
16040 }
16041 return (0);
16042}
16043
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016044/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016045 * xmlSchemaTypeFixup:
16046 * @typeDecl: the schema type definition
16047 * @ctxt: the schema parser context
16048 *
16049 * Fixes the content model of the type.
16050 */
16051static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016052xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016053 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016054{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016055 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016056 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016057 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16058 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016059 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016060 if (! IS_NOT_TYPEFIXED(type))
16061 return;
16062 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016063 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016064 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016065
16066 if (type->baseType == NULL) {
16067 xmlSchemaPCustomErr(ctxt,
16068 XML_SCHEMAP_INTERNAL,
16069 NULL, type, NULL,
16070 "Internal error: xmlSchemaTypeFixup, "
16071 "baseType is missing on '%s'", type->name);
16072 return;
16073 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016074
16075 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016076 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016077
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016078 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016079 * Type-fix the base type.
16080 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016081 if (IS_NOT_TYPEFIXED(baseType))
16082 xmlSchemaTypeFixup(baseType, ctxt, NULL);
16083 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16084 /*
16085 * Skip fixup if the base type is invalid.
16086 * TODO: Generate a warning!
16087 */
16088 return;
16089 }
16090 /*
16091 * This basically checks if the base type can be derived.
16092 */
16093 if (xmlSchemaCheckSRCCT(ctxt, type) != 0) {
16094 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16095 return;
16096 }
16097 /*
16098 * Fixup the content type.
16099 */
16100 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16101 /*
16102 * Corresponds to <complexType><simpleContent>...
16103 */
16104 if ((IS_COMPLEX_TYPE(baseType)) &&
16105 (baseType->contentTypeDef != NULL) &&
16106 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16107 /*
16108 * SPEC (1) If <restriction> + base type is <complexType>,
16109 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016110 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016111 * NOTE (1.1) is handled during parsing of <restriction>.
16112 *
16113 * (1.2) "...otherwise (<restriction> has no <simpleType> among
16114 * its [children]), the simple type definition which is the
16115 * {content type} of the ... base type."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016116 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016117 if (type->contentTypeDef->baseType == NULL) {
16118 /*
16119 * <simpleContent><restriction> has *no* <simpleType>
16120 * child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016121 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016122 type->contentTypeDef->baseType =
16123 baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016124 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016125 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16126 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16127 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16128 /*
16129 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16130 * an emptiable particle, then a simple type definition which
16131 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016132 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016133 if ((type->contentTypeDef == NULL) ||
16134 (type->contentTypeDef->baseType == NULL)) {
16135 /*
16136 * TODO: Check if this ever happens.
16137 */
16138 xmlSchemaPCustomErr(ctxt,
16139 XML_SCHEMAP_INTERNAL,
16140 NULL, type, NULL,
16141 "Internal error: xmlSchemaTypeFixup, "
16142 "complex type '%s': the <simpleContent><restriction> "
16143 "is missing a <simpleType> child, but was not catched "
16144 "by xmlSchemaCheckSRCCT()", type->name);
16145 }
16146 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16147 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16148 /*
16149 * SPEC (3) If <extension> + base is <complexType> with
16150 * <simpleType> content, "...then the {content type} of that
16151 * complex type definition"
16152 */
16153 if (baseType->contentTypeDef == NULL) {
16154 /*
16155 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16156 * should have catched this already.
16157 */
16158 xmlSchemaPCustomErr(ctxt,
16159 XML_SCHEMAP_INTERNAL,
16160 NULL, type, NULL,
16161 "Internal error: xmlSchemaTypeFixup, "
16162 "complex type '%s': the <extension>ed base type is "
16163 "a complex type with no simple content type",
16164 type->name);
16165 }
16166 type->contentTypeDef = baseType->contentTypeDef;
16167 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16168 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16169 /*
16170 * SPEC (4) <extension> + base is <simpleType>
16171 * "... then that simple type definition"
16172 */
16173 type->contentTypeDef = baseType;
16174 } else {
16175 /*
16176 * TODO: Check if this ever happens.
16177 */
16178 xmlSchemaPCustomErr(ctxt,
16179 XML_SCHEMAP_INTERNAL,
16180 NULL, type, NULL,
16181 "Internal error: xmlSchemaTypeFixup, "
16182 "complex type '%s' with <simpleContent>: unhandled "
16183 "derivation case", type->name);
16184 }
16185 } else {
16186 int dummySequence = 0;
16187 xmlSchemaParticlePtr particle =
16188 (xmlSchemaParticlePtr) type->subtypes;
16189 /*
16190 * Corresponds to <complexType><complexContent>...
16191 *
16192 * NOTE that the effective mixed was already set during parsing of
16193 * <complexType> and <complexContent>; its flag value is
16194 * XML_SCHEMAS_TYPE_MIXED.
16195 *
16196 * Compute the "effective content":
16197 * (2.1.1) + (2.1.2) + (2.1.3)
16198 */
16199 if ((particle == NULL) ||
16200 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16201 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16202 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16203 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16204 (particle->minOccurs == 0))) &&
16205 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
16206 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
16207 /*
16208 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16209 * a particle whose properties are as follows:..."
16210 *
16211 * Empty sequence model group with
16212 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16213 * NOTE that we sill assign it the <complexType> node to
16214 * somehow anchor it in the doc.
16215 */
16216 if ((particle == NULL) ||
16217 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016218 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016219 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016220 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016221 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
16222 type->node, 1, 1);
16223 if (particle == NULL)
16224 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016225 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016227 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 particle->children = (xmlSchemaTreeItemPtr)
16229 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
16230 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16231 if (particle->children == NULL)
16232 return;
16233
16234 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016236 dummySequence = 1;
16237 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16238 } else {
16239 /*
16240 * SPEC (2.1.5) "otherwise empty"
16241 */
16242 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
16243 }
16244 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016245 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016246 * SPEC (2.2) "otherwise the particle corresponding to the
16247 * <all>, <choice>, <group> or <sequence> among the
16248 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016249 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016250 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16251 }
16252 /*
16253 * Compute the "content type".
16254 */
16255 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016256 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016257 * SPEC (3.1) "If <restriction>..."
16258 * (3.1.1) + (3.1.2) */
16259 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16260 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16261 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16262 }
16263 } else {
16264 /*
16265 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016266 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016267 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16268 /*
16269 * SPEC (3.2.1)
16270 */
16271 type->contentType = baseType->contentType;
16272 type->subtypes = baseType->subtypes;
16273 /*
16274 * NOTE that the effective mixed is ignored here.
16275 */
16276 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16277 /*
16278 * SPEC (3.2.2)
16279 */
16280 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16281 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16282 } else {
16283 /*
16284 * SPEC (3.2.3)
16285 */
16286 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16287 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16288 /*
16289 * "A model group whose {compositor} is sequence and whose
16290 * {particles} are..."
16291 */
16292 if (! dummySequence) {
16293 xmlSchemaTreeItemPtr effectiveContent =
16294 (xmlSchemaTreeItemPtr) type->subtypes;
16295 /*
16296 * Create the particle.
16297 */
16298 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
16299 type->node, 1, 1);
16300 if (particle == NULL)
16301 return;
16302 /*
16303 * Create the "sequence" model group.
16304 */
16305 particle->children = (xmlSchemaTreeItemPtr)
16306 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
16307 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16308 if (particle->children == NULL)
16309 return;
16310 type->subtypes = (xmlSchemaTypePtr) particle;
16311 /*
16312 * SPEC "the particle of the {content type} of
16313 * the ... base ..."
16314 * Create a duplicate of the base type's particle
16315 * and assign its "term" to it.
16316 */
16317 particle->children->children =
16318 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(ctxt,
16319 ctxt->schema, type->node,
16320 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
16321 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
16322 if (particle->children->children == NULL)
16323 return;
16324 particle = (xmlSchemaParticlePtr)
16325 particle->children->children;
16326 particle->children =
16327 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16328 /*
16329 * SPEC "followed by the ·effective content·."
16330 */
16331 particle->next = effectiveContent;
16332 } else {
16333 /*
16334 * This is the case when there is already an empty
16335 * <sequence> with minOccurs==maxOccurs==1.
16336 * Just add the base types's content type.
16337 * NOTE that, although we miss to add an intermediate
16338 * <sequence>, this should produce no difference to
16339 * neither the regex compilation of the content model,
16340 * nor to the complex type contraints.
16341 */
16342 particle->children->children =
16343 (xmlSchemaTreeItemPtr) baseType->subtypes;
16344 }
16345 }
16346 }
16347 }
16348 /*
16349 * Apply the complex type component constraints; this will not
16350 * check attributes, since this is done in
16351 * xmlSchemaBuildAttributeValidation().
16352 */
16353 if (xmlSchemaCheckCTComponent(ctxt, type) != 0)
16354 return;
16355 /*
16356 * Inherit & check constraints for attributes.
16357 */
16358 xmlSchemaBuildAttributeValidation(ctxt, type);
16359 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
16360 /*
16361 * Simple Type Definition Schema Component
16362 */
16363 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16364 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16365 /*
16366 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016367 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016368 if (type->subtypes == NULL) {
16369 /*
16370 * This one is really needed, so get out.
16371 */
16372 return;
16373 }
16374 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016375 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16377 /*
16378 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016379 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 if (type->memberTypes == NULL) {
16381 /*
16382 * This one is really needed, so get out.
16383 */
16384 return;
16385 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016386 if (xmlSchemaFinishMemberTypeDefinitionsProperty(ctxt, type) == -1)
16387 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016388 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016389 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 /*
16391 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016393 if (IS_NOT_TYPEFIXED(baseType))
16394 xmlSchemaTypeFixup(baseType, ctxt, NULL);
16395 /*
16396 * Variety
16397 * If the <restriction> alternative is chosen, then the
16398 * {variety} of the {base type definition}.
16399 */
16400 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
16401 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
16402 else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16403 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16404 /*
16405 * Inherit the itemType.
16406 */
16407 type->subtypes = baseType->subtypes;
16408 } else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16409 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16410 /*
16411 * NOTE that we won't assign the memberTypes of the base,
16412 * since this will make trouble when freeing them; we will
16413 * use a lookup function to access them instead.
16414 */
16415 }
16416
16417 /*
16418 * Some optimization for validation:
16419 * If there are no facets beside the "whitespace" facet,
16420 * then a value needs not to checked against against a
16421 * facet, thus no computed value is needed.
16422 */
16423#if 0
16424 if (baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
16425 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16426 else {
16427 for (cur = type->facetSet; cur != NULL;
16428 cur = cur->next) {
16429 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
16430 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16431 break;
16432 }
16433 }
16434 }
16435#endif
16436 }
16437 /*
16438 * Check constraints.
16439 *
16440 * TODO: Split this somehow, we need to know first if we can derive
16441 * from the base type at all!
16442 */
16443 if (type->baseType != NULL) {
16444 /*
16445 * Schema Component Constraint: Simple Type Restriction
16446 * (Facets)
16447 * NOTE: Satisfaction of 1 and 2 arise from the fixup
16448 * applied beforehand.
16449 */
16450 xmlSchemaCheckSRCSimpleType(ctxt, type);
16451 xmlSchemaCheckFacetValues(type, ctxt);
16452 xmlSchemaDeriveAndValidateFacets(ctxt, type);
16453 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016454 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016455
Daniel Veillard8651f532002-04-17 09:06:27 +000016456#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016457 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016458 xmlGenericError(xmlGenericErrorContext,
16459 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016460 type->node->doc->URL,
16461 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016462 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016463 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016464 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016465 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16466 switch (type->contentType) {
16467 case XML_SCHEMA_CONTENT_SIMPLE:
16468 xmlGenericError(xmlGenericErrorContext, "simple\n");
16469 break;
16470 case XML_SCHEMA_CONTENT_ELEMENTS:
16471 xmlGenericError(xmlGenericErrorContext, "elements\n");
16472 break;
16473 case XML_SCHEMA_CONTENT_UNKNOWN:
16474 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16475 break;
16476 case XML_SCHEMA_CONTENT_EMPTY:
16477 xmlGenericError(xmlGenericErrorContext, "empty\n");
16478 break;
16479 case XML_SCHEMA_CONTENT_MIXED:
16480 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
16481 type->subtypes))
16482 xmlGenericError(xmlGenericErrorContext,
16483 "mixed as emptiable particle\n");
16484 else
16485 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16486 break;
16487 /* Removed, since not used. */
16488 /*
16489 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16490 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16491 break;
16492 */
16493 case XML_SCHEMA_CONTENT_BASIC:
16494 xmlGenericError(xmlGenericErrorContext, "basic\n");
16495 break;
16496 default:
16497 xmlGenericError(xmlGenericErrorContext,
16498 "not registered !!!\n");
16499 break;
16500 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016501 }
16502#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016503}
16504
16505/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016506 * xmlSchemaCheckFacet:
16507 * @facet: the facet
16508 * @typeDecl: the schema type definition
16509 * @ctxt: the schema parser context or NULL
16510 * @name: name of the type
16511 *
16512 * Checks the default values types, especially for facets
16513 *
16514 * Returns 0 if okay or -1 in cae of error
16515 */
16516int
16517xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016518 xmlSchemaTypePtr typeDecl,
16519 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016520{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016521 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016522 int ret = 0, reuseValCtxt = 0;
16523
Daniel Veillardce682bc2004-11-05 17:22:25 +000016524 if ((facet == NULL) || (typeDecl == NULL))
16525 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016526 /*
16527 * TODO: will the parser context be given if used from
16528 * the relaxNG module?
16529 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016530
16531 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016532 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000016533 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016534 }
16535 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016536 case XML_SCHEMA_FACET_MININCLUSIVE:
16537 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16538 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016539 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16540 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016541 /*
16542 * Okay we need to validate the value
16543 * at that point.
16544 */
16545 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016546 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016547
16548 /* 4.3.5.5 Constraints on enumeration Schema Components
16549 * Schema Component Constraint: enumeration valid restriction
16550 * It is an ·error· if any member of {value} is not in the
16551 * ·value space· of {base type definition}.
16552 *
16553 * minInclusive, maxInclusive, minExclusive, maxExclusive:
16554 * The value ·must· be in the
16555 * ·value space· of the ·base type·.
16556 */
16557 /*
16558 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016559 * on the facet. In this implementation of XML Schemata the
16560 * type holding a facet, won't be a built-in type.
16561 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016562 * calls (relaxng) do work, if the given type is a built-in
16563 * type, we will assume that the given built-in type *is
16564 * already* the base type.
16565 */
16566 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16567 base = typeDecl->baseType;
16568 if (base == NULL) {
16569 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016570 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016571 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016572 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016573 typeDecl->name, NULL);
16574 return (-1);
16575 }
16576 } else
16577 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016578 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016579 * This avoids perseverative creation of the
16580 * validation context if a parser context is
16581 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016582 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016583 if (ctxt != NULL) {
16584 reuseValCtxt = 1;
16585 if (ctxt->vctxt == NULL) {
16586 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16587 return (-1);
16588 }
16589 vctxt = ctxt->vctxt;
16590 } else {
16591 vctxt = xmlSchemaNewValidCtxt(NULL);
16592 if (vctxt == NULL) {
16593 xmlSchemaPErr(ctxt, typeDecl->node,
16594 XML_SCHEMAP_INTERNAL,
16595 "Internal error: xmlSchemaCheckFacet, "
16596 "creating a new validation context.\n",
16597 NULL, NULL);
16598 return (-1);
16599 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016600 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016601
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016602 vctxt->node = facet->node;
16603 vctxt->cur = NULL;
16604 /*
16605 * NOTE: This call does not check the content nodes,
16606 * since they are not available:
16607 * facet->node is just the node holding the facet
16608 * definition, *not* the attribute holding the *value*
16609 * of the facet.
16610 */
16611 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016612 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016613 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016614 /* error code */
16615 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016616 xmlChar *str = NULL;
16617
16618 xmlSchemaPCustomErrExt(ctxt,
16619 XML_SCHEMAP_INVALID_FACET_VALUE,
16620 NULL, (xmlSchemaTypePtr) facet, facet->node,
16621 "The value '%s' of the facet does not validate "
16622 "against the base type '%s'",
16623 facet->value,
16624 xmlSchemaFormatQName(&str,
16625 base->targetNamespace, base->name), NULL);
16626 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016627 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016628 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016629 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016630 } else if (ret < 0) {
16631 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016632 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016633 NULL, NULL, NULL,
16634 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016635 "failed to validate the value '%s' name of the "
16636 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016637 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016638 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016639 base->name, NULL, NULL);
16640 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016641 } else {
16642 if (vctxt->value != NULL) {
16643 facet->val = vctxt->value;
16644 vctxt->value = NULL;
16645 } else {
16646 xmlChar *str;
16647 /*
16648 * Ensure computed values even for type string.
16649 * TODO OPTIMIZE MEMORY: The value will be hold twice,
16650 * by the facet->value and by the computed value.
16651 */
16652 str = xmlStrdup(facet->value);
16653 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
16654 BAD_CAST str, &(facet->val)) == -1) {
16655 FREE_AND_NULL(str)
16656 xmlSchemaPErr(ctxt, typeDecl->node,
16657 XML_SCHEMAP_INTERNAL,
16658 "Internal error: xmlSchemaCheckFacet, "
16659 "post-creating a computed value.\n",
16660 NULL, NULL);
16661 /* Note that we don't return a failure yet.*/
16662 }
16663 }
16664 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016665 if (reuseValCtxt == 0)
16666 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016667 break;
16668 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016669 case XML_SCHEMA_FACET_PATTERN:
16670 facet->regexp = xmlRegexpCompile(facet->value);
16671 if (facet->regexp == NULL) {
16672 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016673 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016674 "Type definition '%s': The value '%s' of the "
16675 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016676 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016677 ret = -1;
16678 }
16679 break;
16680 case XML_SCHEMA_FACET_TOTALDIGITS:
16681 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16682 case XML_SCHEMA_FACET_LENGTH:
16683 case XML_SCHEMA_FACET_MAXLENGTH:
16684 case XML_SCHEMA_FACET_MINLENGTH:{
16685 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016686
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016687 tmp =
16688 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
16689 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016690 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016691 if (tmp != 0) {
16692 /* error code */
16693 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016694 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016695 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016696 NULL, (xmlSchemaTypePtr) facet, facet->node,
16697 "The value '%s' of the facet is not a valid "
16698 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016699 }
16700 ret = -1;
16701 }
16702 break;
16703 }
16704 case XML_SCHEMA_FACET_WHITESPACE:{
16705 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16706 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16707 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16708 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16709 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16710 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16711 } else {
16712 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016713 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
16714 xmlSchemaPCustomErr(ctxt,
16715 XML_SCHEMAP_INVALID_FACET_VALUE,
16716 NULL, (xmlSchemaTypePtr) facet, facet->node,
16717 "The value '%s' of the facet is not a valid",
16718 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016719 }
16720 ret = -1;
16721 }
16722 }
16723 default:
16724 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016725 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016726 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016727}
16728
16729/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016730 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016731 * @typeDecl: the schema type definition
16732 * @ctxt: the schema parser context
16733 *
16734 * Checks the default values types, especially for facets
16735 */
16736static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016737xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16738 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016739{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016740 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016741 /*
16742 * NOTE: It is intended to use the facets list, instead
16743 * of facetSet.
16744 */
16745 if (typeDecl->facets != NULL) {
16746 xmlSchemaFacetPtr facet = typeDecl->facets;
16747
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016748 /*
16749 * Temporarily assign the "schema" to the validation context
16750 * of the parser context. This is needed for NOTATION validation.
16751 */
16752 if (ctxt->vctxt == NULL) {
16753 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16754 return;
16755 }
16756 ctxt->vctxt->schema = ctxt->schema;
16757
Daniel Veillard01fa6152004-06-29 17:04:39 +000016758 while (facet != NULL) {
16759 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16760 facet = facet->next;
16761 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016762
16763 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016764 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016765}
16766
16767/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016768 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016769 * @ctxtMGroup: the searched model group
16770 * @selfMGroup: the second searched model group
16771 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016772 *
16773 * This one is intended to be used by
16774 * xmlSchemaCheckGroupDefCircular only.
16775 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016776 * Returns the particle with the circular model group definition reference,
16777 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016778 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016779static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016780xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016781 xmlSchemaTreeItemPtr particle)
16782{
16783 xmlSchemaTreeItemPtr circ = NULL;
16784 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016785 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016786
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016787 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016788 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016789 if (term == NULL)
16790 continue;
16791 switch (term->type) {
16792 case XML_SCHEMA_TYPE_GROUP:
16793 gdef = (xmlSchemaModelGroupDefPtr) term;
16794 if (gdef == groupDef)
16795 return (particle);
16796 /*
16797 * Mark this model group definition to avoid infinite
16798 * recursion on circular references not yet examined.
16799 */
16800 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16801 continue;
16802 if (gdef->children != NULL) {
16803 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16804 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16805 gdef->children->children);
16806 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16807 if (circ != NULL)
16808 return (circ);
16809 }
16810 break;
16811 case XML_SCHEMA_TYPE_SEQUENCE:
16812 case XML_SCHEMA_TYPE_CHOICE:
16813 case XML_SCHEMA_TYPE_ALL:
16814 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16815 if (circ != NULL)
16816 return (circ);
16817 break;
16818 default:
16819 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016820 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016821 }
16822 return (NULL);
16823}
16824
16825/**
16826 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016827 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016828 * @ctxt: the parser context
16829 * @name: the name
16830 *
16831 * Checks for circular references to model group definitions.
16832 */
16833static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016834xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016835 xmlSchemaParserCtxtPtr ctxt,
16836 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016837{
16838 /*
16839 * Schema Component Constraint: Model Group Correct
16840 * 2 Circular groups are disallowed. That is, within the {particles}
16841 * of a group there must not be at any depth a particle whose {term}
16842 * is the group itself.
16843 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016844 if ((item == NULL) ||
16845 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16846 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016847 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016848 {
16849 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016850
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016851 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016852 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016853 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016854 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016855 * TODO: The error report is not adequate: this constraint
16856 * is defined for model groups but not definitions, but since
16857 * there cannot be any circular model groups without a model group
16858 * definition (if not using a construction API), we check those
16859 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016860 */
16861 xmlSchemaPCustomErr(ctxt,
16862 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016863 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016864 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016865 "defined", xmlSchemaFormatQName(&str,
16866 item->targetNamespace, item->name));
16867 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016868 /*
16869 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016870 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016871 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016872 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016873 }
16874 }
16875}
16876
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016877/**
16878 * xmlSchemaGroupDefTermFixup:
16879 * @item: the particle with a model group definition as term
16880 * @ctxt: the parser context
16881 * @name: the name
16882 *
16883 * Checks for circular references to model group definitions.
16884 * Additionally it
16885 */
16886static void
16887xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
16888 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
16889 const xmlChar * name ATTRIBUTE_UNUSED)
16890{
16891 if ((item == NULL) ||
16892 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16893 (item->children == NULL) ||
16894 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16895 (item->children->children == NULL))
16896 return;
16897 item->children = item->children->children;
16898}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016899
16900/**
16901 * xmlSchemaGetCircAttrGrRef:
16902 * @ctxtGr: the searched attribute group
16903 * @attr: the current attribute list to be processed
16904 *
16905 * This one is intended to be used by
16906 * xmlSchemaCheckSRCAttributeGroupCircular only.
16907 *
16908 * Returns the circular attribute grou reference, otherwise NULL.
16909 */
16910static xmlSchemaAttributeGroupPtr
16911xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16912 xmlSchemaAttributePtr attr)
16913{
16914 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16915 int marked;
16916 /*
16917 * We will search for an attribute group reference which
16918 * references the context attribute group.
16919 */
16920 while (attr != NULL) {
16921 marked = 0;
16922 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16923 gr = (xmlSchemaAttributeGroupPtr) attr;
16924 if (gr->refItem != NULL) {
16925 if (gr->refItem == ctxtGr)
16926 return (gr);
16927 else if (gr->refItem->flags &
16928 XML_SCHEMAS_ATTRGROUP_MARKED) {
16929 attr = attr->next;
16930 continue;
16931 } else {
16932 /*
16933 * Mark as visited to avoid infinite recursion on
16934 * circular references not yet examined.
16935 */
16936 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16937 marked = 1;
16938 }
16939 }
16940 if (gr->attributes != NULL)
16941 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16942 /*
16943 * Unmark the visited group's attributes.
16944 */
16945 if (marked)
16946 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16947 if (circ != NULL)
16948 return (circ);
16949 }
16950 attr = attr->next;
16951 }
16952 return (NULL);
16953}
16954
16955/**
16956 * xmlSchemaCheckSRCAttributeGroupCircular:
16957 * attrGr: the attribute group definition
16958 * @ctxt: the parser context
16959 * @name: the name
16960 *
16961 * Checks for circular references of attribute groups.
16962 */
16963static void
16964xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
16965 xmlSchemaParserCtxtPtr ctxt,
16966 const xmlChar * name ATTRIBUTE_UNUSED)
16967{
16968 /*
16969 * Schema Representation Constraint:
16970 * Attribute Group Definition Representation OK
16971 * 3 Circular group reference is disallowed outside <redefine>.
16972 * That is, unless this element information item's parent is
16973 * <redefine>, then among the [children], if any, there must
16974 * not be an <attributeGroup> with ref [attribute] which resolves
16975 * to the component corresponding to this <attributeGroup>. Indirect
16976 * circularity is also ruled out. That is, when QName resolution
16977 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16978 * any <attributeGroup>s with a ref [attribute] among the [children],
16979 * it must not be the case that a ·QName· is encountered at any depth
16980 * which resolves to the component corresponding to this <attributeGroup>.
16981 */
16982 /*
16983 * Only global components can be referenced.
16984 */
16985 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
16986 (attrGr->attributes == NULL))
16987 return;
16988 else {
16989 xmlSchemaAttributeGroupPtr circ;
16990
16991 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16992 if (circ != NULL) {
16993 /*
16994 * TODO: Report the referenced attr group as QName.
16995 */
16996 xmlSchemaPCustomErr(ctxt,
16997 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16998 NULL, NULL, circ->node,
16999 "Circular reference to the attribute group '%s' "
17000 "defined", attrGr->name);
17001 /*
17002 * NOTE: We will cut the reference to avoid further
17003 * confusion of the processor.
17004 * BADSPEC: The spec should define how to process in this case.
17005 */
17006 circ->attributes = NULL;
17007 circ->refItem = NULL;
17008 }
17009 }
17010}
17011
17012/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017013 * xmlSchemaAttrGrpFixup:
17014 * @attrgrpDecl: the schema attribute definition
17015 * @ctxt: the schema parser context
17016 * @name: the attribute name
17017 *
17018 * Fixes finish doing the computations on the attributes definitions
17019 */
17020static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017021xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017022 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017023{
17024 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017025 name = attrgrp->name;
17026 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017027 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017028 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017029 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017030
Daniel Veillardc0826a72004-08-10 14:17:33 +000017031 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
17032 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017033 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017034 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017035 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017036 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17037 "ref", attrgrp->ref, attrgrp->refNs,
17038 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017039 return;
17040 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017041 attrgrp->refItem = ref;
17042 /*
17043 * Check for self reference!
17044 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017045 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017046 attrgrp->attributes = ref->attributes;
17047 attrgrp->attributeWildcard = ref->attributeWildcard;
17048 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017049}
17050
17051/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017052 * xmlSchemaAttrCheckValConstr:
17053 * @item: an schema attribute declaration/use
17054 * @ctxt: a schema parser context
17055 * @name: the name of the attribute
17056 *
17057 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017058 *
17059 * Fixes finish doing the computations on the attributes definitions
17060 */
17061static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017062xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
17063 xmlSchemaParserCtxtPtr ctxt,
17064 const xmlChar * name ATTRIBUTE_UNUSED)
17065{
17066
17067 /*
17068 * a-props-correct
17069 * Schema Component Constraint: Attribute Declaration Properties Correct
17070 *
17071 * 2 if there is a {value constraint}, the canonical lexical
17072 * representation of its value must be ·valid· with respect
17073 * to the {type definition} as defined in String Valid (§3.14.4).
17074 */
17075
17076 if (item->defValue != NULL) {
17077 int ret;
17078 xmlNodePtr node;
17079 xmlSchemaTypePtr type;
17080
17081 if (item->subtypes == NULL) {
17082 xmlSchemaPErr(ctxt, item->node,
17083 XML_SCHEMAP_INTERNAL,
17084 "Internal error: xmlSchemaCheckAttrValConstr, "
17085 "type is missing... skipping validation of "
17086 "value constraint", NULL, NULL);
17087 return;
17088 }
17089
17090 /*
17091 * TODO: Try to avoid creating a new context.
17092 * TODO: This all is not very performant.
17093 */
17094 type = item->subtypes;
17095 /*
17096 * Ensure there's validation context.
17097 */
17098 if (ctxt->vctxt == NULL) {
17099 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
17100 xmlSchemaPErr(ctxt, item->node,
17101 XML_SCHEMAP_INTERNAL,
17102 "Internal error: xmlSchemaCheckAttrValConstr, "
17103 "creating a new validation context.\n",
17104 NULL, NULL);
17105 return;
17106 }
17107 }
17108
17109 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
17110 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
17111 else
17112 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
17113 ctxt->vctxt->node = node;
17114 ctxt->vctxt->cur = NULL;
17115 /*
17116 * NOTE: This call does not check the content nodes,
17117 * since they are not available:
17118 * facet->node is just the node holding the facet
17119 * definition, *not* the attribute holding the *value*
17120 * of the facet.
17121 */
17122 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
17123 item->defValue, 0, 1, 1, 0);
17124 if (ret == 0) {
17125 /*
17126 * Store the computed value.
17127 */
17128 item->defVal = ctxt->vctxt->value;
17129 ctxt->vctxt->value = NULL;
17130 } else if (ret > 0) {
17131 if (ctxt != NULL) {
17132 xmlSchemaPSimpleTypeErr(ctxt,
17133 XML_SCHEMAP_A_PROPS_CORRECT_2,
17134 NULL, NULL, node,
17135 type, NULL, item->defValue,
17136 NULL, NULL, NULL);
17137 }
17138 } else if (ret < 0) {
17139 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
17140 NULL, NULL, node,
17141 "Internal error: xmlSchemaAttrCheckValConstr, "
17142 "failed to validate the value constraint of the "
17143 "attribute decl/use against the type '%s'",
17144 type->name);
17145 }
17146 }
17147}
17148
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017149static xmlSchemaElementPtr
17150xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17151 xmlSchemaElementPtr ancestor)
17152{
17153 xmlSchemaElementPtr ret;
17154
17155 if (SUBST_GROUP_AFF(ancestor) == NULL)
17156 return (NULL);
17157 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17158 return (ancestor);
17159
17160 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17161 return (NULL);
17162 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17163 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17164 SUBST_GROUP_AFF(ancestor));
17165 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17166
17167 return (ret);
17168}
17169
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017170/**
17171 * xmlSchemaCheckElemPropsCorrect:
17172 * @ctxt: a schema parser context
17173 * @decl: the element declaration
17174 * @name: the name of the attribute
17175 *
17176 * Schema Component Constraint:
17177 * Element Declaration Properties Correct (e-props-correct)
17178 *
17179 * STATUS:
17180 * missing: (6)
17181 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017182static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017183xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17184 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017185{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017186 int ret = 0;
17187 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017188 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017189 * SPEC (1) "The values of the properties of an element declaration
17190 * must be as described in the property tableau in The Element
17191 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17192 * Sub-components (§5.3)."
17193 */
17194 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017195 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017196 /*
17197 * SPEC (3) "If there is a non-·absent· {substitution group
17198 * affiliation}, then {scope} must be global."
17199 */
17200 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17201 xmlSchemaPCustomErr(pctxt,
17202 XML_SCHEMAP_E_PROPS_CORRECT_3,
17203 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17204 "Only global element declarations can have a "
17205 "substitution group affiliation", NULL);
17206 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017207 }
17208 /*
17209 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17210 * That is, it must not be possible to return to an element declaration
17211 * by repeatedly following the {substitution group affiliation}
17212 * property."
17213 */
17214 if (head == elemDecl)
17215 circ = head;
17216 else if (SUBST_GROUP_AFF(head) != NULL)
17217 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17218 else
17219 circ = NULL;
17220 if (circ != NULL) {
17221 xmlChar *strA = NULL, *strB = NULL;
17222
17223 xmlSchemaPCustomErrExt(pctxt,
17224 XML_SCHEMAP_E_PROPS_CORRECT_6,
17225 NULL, (xmlSchemaTypePtr) circ, circ->node,
17226 "The element declaration '%s' defines a circular "
17227 "substitution group to element declaration '%s'",
17228 xmlSchemaGetComponentQName(&strA, circ),
17229 xmlSchemaGetComponentQName(&strB, head),
17230 NULL);
17231 FREE_AND_NULL(strA)
17232 FREE_AND_NULL(strB)
17233 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17234 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017235 /*
17236 * SPEC (4) "If there is a {substitution group affiliation},
17237 * the {type definition}
17238 * of the element declaration must be validly derived from the {type
17239 * definition} of the {substitution group affiliation}, given the value
17240 * of the {substitution group exclusions} of the {substitution group
17241 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17242 * (if the {type definition} is complex) or as defined in
17243 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
17244 * simple)."
17245 *
17246 * NOTE: {substitution group exclusions} means the values of the
17247 * attribute "final".
17248 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017249
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017250 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
17251 int set = 0;
17252
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017253 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017254 set |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017255 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017256 set |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
17257
17258 if (xmlSchemaCheckCOSDerivedOK(pctxt->schema, typeDef,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017259 ELEM_TYPE(head), set) != 0) {
17260 xmlChar *strA = NULL, *strB = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017261
17262 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
17263 xmlSchemaPCustomErrExt(pctxt,
17264 XML_SCHEMAP_E_PROPS_CORRECT_4,
17265 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017266 "The type definition of element declaration '%s' is not "
17267 "validly derived from the type definition of its "
17268 "substitution group affiliation '%s'",
17269 xmlSchemaGetComponentQName(&strA, elemDecl),
17270 xmlSchemaGetComponentQName(&strB, head),
17271 NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017272 FREE_AND_NULL(strA)
17273 FREE_AND_NULL(strB)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017274 }
17275 }
17276 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017277 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017278 * SPEC (5) "If the {type definition} or {type definition}'s
17279 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017280 * is or is derived from ID then there must not be a {value constraint}.
17281 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017282 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017283 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017284 if ((elemDecl->value != NULL) &&
17285 ((IS_SIMPLE_TYPE(typeDef) &&
17286 xmlSchemaIsDerivedFromBuiltInType(pctxt,
17287 ELEM_TYPE(elemDecl), XML_SCHEMAS_ID)) ||
17288 (IS_COMPLEX_TYPE(typeDef) &&
17289 HAS_SIMPLE_CONTENT(typeDef) &&
17290 xmlSchemaIsDerivedFromBuiltInType(pctxt,
17291 typeDef->contentTypeDef, XML_SCHEMAS_ID)))) {
17292
17293 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17294 xmlSchemaPCustomErr(pctxt,
17295 XML_SCHEMAP_E_PROPS_CORRECT_5,
17296 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17297 "The type definition (or type definition's content type) is or "
17298 "is derived from ID; value constraints are not allowed in "
17299 "conjunction with such a type definition", NULL);
17300 } else if (elemDecl->value != NULL) {
17301 int vcret;
17302 xmlNodePtr node = NULL;
17303
17304 /*
17305 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17306 * representation of its value must be ·valid· with respect to the
17307 * {type definition} as defined in Element Default Valid (Immediate)
17308 * (§3.3.6)."
17309 */
17310 if (typeDef == NULL) {
17311 xmlSchemaPErr(pctxt, elemDecl->node,
17312 XML_SCHEMAP_INTERNAL,
17313 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17314 "type is missing... skipping validation of "
17315 "the value constraint", NULL, NULL);
17316 return (-1);
17317 }
17318 /*
17319 * Ensure there's a validation context.
17320 */
17321 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
17322 return (-1);
17323 if (elemDecl->node != NULL) {
17324 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17325 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17326 BAD_CAST "fixed");
17327 else
17328 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17329 BAD_CAST "default");
17330 }
17331 pctxt->vctxt->node = node;
17332 pctxt->vctxt->cur = NULL;
17333 vcret = xmlSchemaCheckCOSValidDefault(pctxt, pctxt->vctxt, typeDef,
17334 elemDecl->value, node);
17335 if (vcret == 0) {
17336 /*
17337 * Consume the computed value.
17338 */
17339 elemDecl->defVal = pctxt->vctxt->value;
17340 pctxt->vctxt->value = NULL;
17341 } else if (vcret < 0) {
17342 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_INTERNAL,
17343 NULL, NULL, node,
17344 "Internal error: xmlSchemaElemCheckValConstr, "
17345 "failed to validate the value constraint of the "
17346 "element declaration '%s'",
17347 elemDecl->name);
17348 ret = vcret;
17349 } else
17350 ret = vcret;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017351 }
17352
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017353 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017354}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017355
17356/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017357 * xmlSchemaCheckElemSubstGroup:
17358 * @ctxt: a schema parser context
17359 * @decl: the element declaration
17360 * @name: the name of the attribute
17361 *
17362 * Schema Component Constraint:
17363 * Substitution Group (cos-equiv-class)
17364 *
17365 * In Libxml2 the subst. groups will be precomputed, in terms of that
17366 * a list will be built for each subst. group head, holding all direct
17367 * referents to this head.
17368 * NOTE that this function needs:
17369 * 1. circular subst. groups to be checked beforehand
17370 * 2. the declaration's type to be derived from the head's type
17371 *
17372 * STATUS:
17373 *
17374 */
17375static void
17376xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17377 xmlSchemaElementPtr elemDecl)
17378{
17379 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17380 /* SPEC (1) "Its {abstract} is false." */
17381 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17382 return;
17383 {
17384 xmlSchemaElementPtr head;
17385 xmlSchemaTypePtr headType, type;
17386 int set, methSet;
17387 /*
17388 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17389 * {disallowed substitutions} as the blocking constraint, as defined in
17390 * Substitution Group OK (Transitive) (§3.3.6)."
17391 */
17392 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17393 head = SUBST_GROUP_AFF(head)) {
17394 set = 0;
17395 methSet = 0;
17396 /*
17397 * The blocking constraints.
17398 */
17399 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17400 continue;
17401 headType = head->subtypes;
17402 type = elemDecl->subtypes;
17403 if (headType == type)
17404 goto add_member;
17405 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17406 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17407 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17408 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17409 /*
17410 * SPEC: Substitution Group OK (Transitive) (2.3)
17411 * "The set of all {derivation method}s involved in the
17412 * derivation of D's {type definition} from C's {type definition}
17413 * does not intersect with the union of the blocking constraint,
17414 * C's {prohibited substitutions} (if C is complex, otherwise the
17415 * empty set) and the {prohibited substitutions} (respectively the
17416 * empty set) of any intermediate {type definition}s in the
17417 * derivation of D's {type definition} from C's {type definition}."
17418 */
17419 /*
17420 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17421 * subst.head axis, the methSet does not need to be computed for
17422 * the full depth over and over.
17423 */
17424 /*
17425 * The set of all {derivation method}s involved in the derivation
17426 */
17427 while ((type != NULL) && (type != headType)) {
17428 if ((type->flags &
17429 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17430 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17431 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17432
17433 if ((type->flags &
17434 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17435 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17436 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17437
17438 type = type->baseType;
17439 }
17440 /*
17441 * The {prohibited substitutions} of all intermediate types +
17442 * the head's type.
17443 */
17444 type = elemDecl->subtypes->baseType;
17445 while (type != NULL) {
17446 if (IS_COMPLEX_TYPE(type)) {
17447 if ((type->flags &
17448 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17449 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17450 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17451 if ((type->flags &
17452 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17453 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17454 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17455 } else
17456 break;
17457 if (type == headType)
17458 break;
17459 type = type->baseType;
17460 }
17461 if ((set != 0) &&
17462 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17463 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17464 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17465 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17466 continue;
17467 }
17468add_member:
17469 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17470 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17471 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17472 }
17473 }
17474}
17475
17476/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017477 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017478 * @item: an schema element declaration/particle
17479 * @ctxt: a schema parser context
17480 * @name: the name of the attribute
17481 *
17482 * Validates the value constraints of an element declaration.
17483 *
17484 * Fixes finish doing the computations on the element declarations.
17485 */
17486static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017487xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
17488 xmlSchemaParserCtxtPtr ctxt,
17489 const xmlChar * name ATTRIBUTE_UNUSED)
17490{
17491 if (elemDecl == NULL)
17492 return;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017493 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17494 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017495}
17496
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017497/**
17498 * xmlSchemaMiscRefFixup:
17499 * @item: an schema component
17500 * @ctxt: a schema parser context
17501 * @name: the internal name of the component
17502 *
17503 * Resolves references of misc. schema components.
17504 */
17505static void
17506xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
17507 xmlSchemaParserCtxtPtr ctxt,
17508 const xmlChar * name ATTRIBUTE_UNUSED)
17509{
17510 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
17511 if ((item->children != NULL) &&
17512 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17513 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17514 xmlSchemaTreeItemPtr refItem;
17515 /*
17516 * Resolve the reference.
17517 */
17518 item->children = NULL;
17519 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17520 ref->itemType, ref->name, ref->targetNamespace);
17521 if (refItem == NULL) {
17522 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
17523 NULL, NULL, GET_NODE(item), "ref", ref->name,
17524 ref->targetNamespace, ref->itemType, NULL);
17525 } else {
17526 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17527 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017528 * NOTE that we will assign the model group definition
17529 * itself to the "term" of the particle. This will ease
17530 * the check for circular model group definitions. After
17531 * that the "term" will be assigned the model group of the
17532 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017533 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017534 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017535 } else
17536 item->children = refItem;
17537 }
17538 }
17539 }
17540}
17541
17542
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017543/**
17544 * xmlSchemaAttrFixup:
17545 * @item: an schema attribute declaration/use.
17546 * @ctxt: a schema parser context
17547 * @name: the name of the attribute
17548 *
17549 * Fixes finish doing the computations on attribute declarations/uses.
17550 */
17551static void
17552xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
17553 xmlSchemaParserCtxtPtr ctxt,
17554 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017555{
Daniel Veillardc0826a72004-08-10 14:17:33 +000017556 /*
17557 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017558 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017559 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017560 /*
17561 * The simple type definition corresponding to the <simpleType> element
17562 * information item in the [children], if present, otherwise the simple
17563 * type definition ·resolved· to by the ·actual value· of the type
17564 * [attribute], if present, otherwise the ·simple ur-type definition·.
17565 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017566 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017567 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017568 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17569 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017570 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017571 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017572 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017573
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017574 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17575 item->typeNs);
17576 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017577 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017578 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017579 NULL, (xmlSchemaTypePtr) item, item->node,
17580 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017581 XML_SCHEMA_TYPE_SIMPLE, NULL);
17582 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017583 item->subtypes = type;
17584
17585 } else if (item->ref != NULL) {
17586 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017587
Daniel Veillardc0826a72004-08-10 14:17:33 +000017588 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017589 * We have an attribute use here; assign the referenced
17590 * attribute declaration.
17591 */
17592 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017593 * TODO: Evaluate, what errors could occur if the declaration is not
17594 * found. It might be possible that the "typefixup" might crash if
17595 * no ref declaration was found.
17596 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017597 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
17598 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017599 xmlSchemaPResCompAttrErr(ctxt,
17600 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017601 NULL, (xmlSchemaTypePtr) item, item->node,
17602 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017603 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017604 return;
17605 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017606 item->refDecl = decl;
17607 xmlSchemaAttrFixup(decl, ctxt, NULL);
17608
17609 item->subtypes = decl->subtypes;
17610 /*
17611 * Attribute Use Correct
17612 * au-props-correct.2: If the {attribute declaration} has a fixed
17613 * {value constraint}, then if the attribute use itself has a
17614 * {value constraint}, it must also be fixed and its value must match
17615 * that of the {attribute declaration}'s {value constraint}.
17616 */
17617 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
17618 (item->defValue != NULL)) {
17619 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
17620 (!xmlStrEqual(item->defValue, decl->defValue))) {
17621 xmlSchemaPCustomErr(ctxt,
17622 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17623 NULL, NULL, item->node,
17624 "The value constraint must be fixed "
17625 "and match the referenced attribute "
17626 "declarations's value constraint '%s'",
17627 decl->defValue);
17628 }
17629 /*
17630 * FUTURE: One should change the values of the attr. use
17631 * if ever validation should be attempted even if the
17632 * schema itself was not fully valid.
17633 */
17634 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017635 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017636 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17637 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017638}
17639
17640/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017641 * xmlSchemaResolveIDCKeyRef:
17642 * @idc: the identity-constraint definition
17643 * @ctxt: the schema parser context
17644 * @name: the attribute name
17645 *
17646 * Resolve keyRef references to key/unique IDCs.
17647 */
17648static void
17649xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
17650 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017651 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017652{
17653 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17654 return;
17655 if (idc->ref->name != NULL) {
17656 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
17657 ctxt->schema->idcDef,
17658 idc->ref->name,
17659 idc->ref->targetNamespace);
17660 if (idc->ref->item == NULL) {
17661 /*
17662 * TODO: It is actually not an error to fail to resolve.
17663 */
17664 xmlSchemaPResCompAttrErr(ctxt,
17665 XML_SCHEMAP_SRC_RESOLVE,
17666 NULL, (xmlSchemaTypePtr) idc, idc->node,
17667 "refer", idc->ref->name,
17668 idc->ref->targetNamespace,
17669 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17670 return;
17671 }
17672 }
17673}
17674
17675/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017676 * xmlSchemaParse:
17677 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017678 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017679 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017680 * XML Shema struture which can be used to validate instances.
17681 * *WARNING* this interface is highly subject to change
17682 *
17683 * Returns the internal XML Schema structure built from the resource or
17684 * NULL in case of error
17685 */
17686xmlSchemaPtr
17687xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17688{
17689 xmlSchemaPtr ret = NULL;
17690 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017691 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017692 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017693
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017694 /*
17695 * This one is used if the schema to be parsed was specified via
17696 * the API; i.e. not automatically by the validated instance document.
17697 */
17698
Daniel Veillard4255d502002-04-16 15:50:10 +000017699 xmlSchemaInitTypes();
17700
Daniel Veillard6045c902002-10-09 21:13:59 +000017701 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017702 return (NULL);
17703
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017704 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017705 ctxt->counter = 0;
17706 ctxt->container = NULL;
17707
17708 /*
17709 * First step is to parse the input document into an DOM/Infoset
17710 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017711 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017712 doc = xmlReadFile((const char *) ctxt->URL, NULL,
17713 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017714 if (doc == NULL) {
17715 xmlSchemaPErr(ctxt, NULL,
17716 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017717 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017718 ctxt->URL, NULL);
17719 return (NULL);
17720 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017721 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017722 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17723 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017724 if (doc == NULL) {
17725 xmlSchemaPErr(ctxt, NULL,
17726 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017727 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017728 NULL, NULL);
17729 return (NULL);
17730 }
17731 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017732 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017733 } else if (ctxt->doc != NULL) {
17734 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017735 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017736 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017737 xmlSchemaPErr(ctxt, NULL,
17738 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017739 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017740 NULL, NULL);
17741 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017742 }
17743
17744 /*
17745 * Then extract the root and Schema parse it
17746 */
17747 root = xmlDocGetRootElement(doc);
17748 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017749 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17750 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017751 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017752 if (!preserve) {
17753 xmlFreeDoc(doc);
17754 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017755 return (NULL);
17756 }
17757
17758 /*
17759 * Remove all the blank text nodes
17760 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017761 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017762
17763 /*
17764 * Then do the parsing for good
17765 */
17766 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017767 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017768 if (!preserve) {
17769 xmlFreeDoc(doc);
17770 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017771 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017772 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017773 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017774 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017775 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017776 ctxt->ctxtType = NULL;
17777 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017778
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017779 /*
17780 * Resolve base types of simple/complex types.
17781 */
17782 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
17783
17784 if (ctxt->nberrors != 0)
17785 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017786
17787 if (ret->volatiles != NULL) {
17788 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17789 int i;
17790 xmlSchemaTreeItemPtr item;
17791
17792 for (i = 0; i < list->nbItems; i++) {
17793 item = (xmlSchemaTreeItemPtr) list->items[i];
17794 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17795 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017796 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017797 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017798 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017799 * Then fixup all attributes declarations
17800 */
17801 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017802 /*
17803 * Then fixup all attributes group declarations
17804 */
17805 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17806 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017807 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017808 * Resolve identity-constraint keyRefs.
17809 */
17810 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017811 /*
17812 * Check type defnitions for circular references.
17813 */
17814 xmlHashScan(ret->typeDecl, (xmlHashScanner)
17815 xmlSchemaCheckTypeDefCircular, ctxt);
17816 /*
17817 * Check model groups defnitions for circular references.
17818 */
17819 xmlHashScan(ret->groupDecl, (xmlHashScanner)
17820 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017821 /*
17822 * Set the "term" of particles pointing to model group definitions
17823 * to the contained model group.
17824 */
17825 if (ret->volatiles != NULL) {
17826 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17827 int i;
17828 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017829
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017830 for (i = 0; i < list->nbItems; i++) {
17831 item = (xmlSchemaParticlePtr) list->items[i];
17832 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17833 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17834 }
17835 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017836 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017837 * Check attribute groups for circular references.
17838 */
17839 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017840 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017841 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017842 * Then fix references of element declaration; apply constraints.
17843 */
17844 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017845 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017846 /*
17847 * We will stop here if the schema was not valid to avoid internal errors
17848 * on missing sub-components. This is not conforming to the spec, since it
17849 * allows missing components, but it might make further processing crash.
17850 * So see it as a very strict handling, which might be made more lax in the
17851 * future.
17852 */
17853 if (ctxt->nberrors != 0)
17854 goto exit;
17855 /*
17856 * Then fixup all types properties
17857 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017858 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017859 /*
17860 * Validate the value constraint of attribute declarations/uses.
17861 */
17862 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017863 /*
17864 * Validate the value constraint of element declarations.
17865 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017866 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017867 /*
17868 * Then build the content model for all complex types
17869 */
17870 xmlHashScan(ret->typeDecl,
17871 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017872
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017873exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017874 if (ctxt->nberrors != 0) {
17875 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017876 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017877 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017878 return (ret);
17879}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017880
Daniel Veillard4255d502002-04-16 15:50:10 +000017881/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017882 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017883 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017884 * @err: the error callback
17885 * @warn: the warning callback
17886 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017887 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017888 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017889 */
17890void
17891xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017892 xmlSchemaValidityErrorFunc err,
17893 xmlSchemaValidityWarningFunc warn, void *ctx)
17894{
Daniel Veillard4255d502002-04-16 15:50:10 +000017895 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017896 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017897 ctxt->error = err;
17898 ctxt->warning = warn;
17899 ctxt->userData = ctx;
17900}
17901
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017902/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017903 * xmlSchemaGetParserErrors:
17904 * @ctxt: a XMl-Schema parser context
17905 * @err: the error callback result
17906 * @warn: the warning callback result
17907 * @ctx: contextual data for the callbacks result
17908 *
17909 * Get the callback information used to handle errors for a parser context
17910 *
17911 * Returns -1 in case of failure, 0 otherwise
17912 */
17913int
17914xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17915 xmlSchemaValidityErrorFunc * err,
17916 xmlSchemaValidityWarningFunc * warn, void **ctx)
17917{
17918 if (ctxt == NULL)
17919 return(-1);
17920 if (err != NULL)
17921 *err = ctxt->error;
17922 if (warn != NULL)
17923 *warn = ctxt->warning;
17924 if (ctx != NULL)
17925 *ctx = ctxt->userData;
17926 return(0);
17927}
17928
17929/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017930 * xmlSchemaFacetTypeToString:
17931 * @type: the facet type
17932 *
17933 * Convert the xmlSchemaTypeType to a char string.
17934 *
17935 * Returns the char string representation of the facet type if the
17936 * type is a facet and an "Internal Error" string otherwise.
17937 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017938static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017939xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17940{
17941 switch (type) {
17942 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017943 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017944 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017945 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017946 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017947 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017948 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017949 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017950 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017951 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017952 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017953 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017954 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017955 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017956 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017957 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017958 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017959 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017960 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017961 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017962 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017963 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017964 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017965 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017966 default:
17967 break;
17968 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017969 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017970}
17971
Daniel Veillardc0826a72004-08-10 14:17:33 +000017972static int
17973xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17974{
17975 xmlSchemaTypePtr anc;
17976
17977 /*
17978 * The normalization type can be changed only for types which are derived
17979 * from xsd:string.
17980 */
17981 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017982 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017983 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017984 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017985 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017986 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
17987 /*
17988 * Note that we assume a whitespace of preserve for anySimpleType.
17989 */
17990 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017991 else {
17992 /*
17993 * For all ·atomic· datatypes other than string (and types ·derived·
17994 * by ·restriction· from it) the value of whiteSpace is fixed to
17995 * collapse
17996 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017997 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017998 }
17999 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18000 /*
18001 * For list types the facet "whiteSpace" is fixed to "collapse".
18002 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018003 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018004 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018005 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018006 } else if (type->facetSet != NULL) {
18007 xmlSchemaTypePtr anyST;
18008 xmlSchemaFacetLinkPtr lin;
18009
18010 /*
18011 * Atomic types.
18012 */
18013 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
18014 anc = type->baseType;
18015 do {
18016 /*
18017 * For all ·atomic· datatypes other than string (and types ·derived·
18018 * by ·restriction· from it) the value of whiteSpace is fixed to
18019 * collapse
18020 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018021 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18022 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018023
18024 lin = type->facetSet;
18025 do {
18026 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018027 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018028 }
18029 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018030 } while (lin != NULL);
18031 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
18032 return (XML_SCHEMAS_FACET_REPLACE);
18033 else
18034 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018035 }
18036 anc = anc->baseType;
18037 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018038 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018039 }
18040 return (-1);
18041}
18042
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018043/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000018044 * xmlSchemaValidateFacetsInternal:
18045 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000018046 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000018047 * @facets: the list of facets to check
18048 * @value: the lexical repr of the value to validate
18049 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000018050 * @fireErrors: if 0, only internal errors will be fired;
18051 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000018052 *
18053 * Check a value against all facet conditions
18054 *
18055 * Returns 0 if the element is schemas valid, a positive error code
18056 * number otherwise and -1 in case of internal or API error.
18057 */
18058static int
18059xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018060 xmlSchemaTypePtr type,
18061 const xmlChar * value,
18062 unsigned long length,
18063 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000018064{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018065 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018066 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018067 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018068 xmlSchemaTypePtr tmpType;
18069 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000018070 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018071 xmlSchemaFacetPtr facet;
18072 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018073 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018074
18075 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018076
Daniel Veillardc0826a72004-08-10 14:17:33 +000018077#ifdef DEBUG_UNION_VALIDATION
18078 printf("Facets of type: '%s'\n", (const char *) type->name);
18079 printf(" fireErrors: %d\n", fireErrors);
18080#endif
18081
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018082 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018083 /*
18084 * NOTE: Do not jump away, if the facetSet of the given type is
18085 * empty: until now, "pattern" facets of the *base types* need to
18086 * be checked as well.
18087 */
18088 biType = type->baseType;
18089 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
18090 biType = biType->baseType;
18091 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018092 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018093 "Internal error: xmlSchemaValidateFacetsInternal, "
18094 "the base type axis of the given type '%s' does not resolve to "
18095 "a built-in type.\n",
18096 type->name, NULL);
18097 return (-1);
18098 }
18099
18100 if (type->facetSet != NULL) {
18101 facetLink = type->facetSet;
18102 while (facetLink != NULL) {
18103 facet = facetLink->facet;
18104 /*
18105 * Skip the pattern "whiteSpace": it is used to
18106 * format the character content beforehand.
18107 */
18108 switch (facet->type) {
18109 case XML_SCHEMA_FACET_WHITESPACE:
18110 case XML_SCHEMA_FACET_PATTERN:
18111 case XML_SCHEMA_FACET_ENUMERATION:
18112 break;
18113 case XML_SCHEMA_FACET_LENGTH:
18114 case XML_SCHEMA_FACET_MINLENGTH:
18115 case XML_SCHEMA_FACET_MAXLENGTH:
18116 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18117 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018118 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018119 len = length;
18120 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018121 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
18122 (xmlSchemaValType) biType->builtInType,
18123 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018124 break;
18125 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018126 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
18127 biType->builtInType, value, ctxt->value, ws);
18128 /*
18129 * ret = xmlSchemaValidateFacet(biType, facet, value,
18130 * ctxt->value);
18131 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018132 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018133 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018135 "Internal error: xmlSchemaValidateFacetsInternal, "
18136 "validating facet of type '%s'.\n",
18137 type->name, NULL);
18138 break;
18139 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018140 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018141 type, facet, NULL, NULL, NULL, NULL);
18142 }
18143
18144 facetLink = facetLink->next;
18145 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018146
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018147 }
18148
Daniel Veillardc0826a72004-08-10 14:17:33 +000018149 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018150 xmlSchemaWhitespaceValueType fws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018151 int found = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018152 /*
18153 * Process enumerations. Facet values are in the value space
18154 * of the defining type's base type. This seems to be a bug in the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018155 * XML Schema 1.0 spec. Use the whitespace type of the base type.
18156 * Only the first set of enumerations in the ancestor-or-self axis
18157 * is used for validation.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018158 */
18159 tmpType = type;
18160 do {
18161 /*
18162 * Use the whitespace type of the base type.
18163 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018164 fws = (xmlSchemaWhitespaceValueType)
18165 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018166 retFacet = 0;
18167 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
18168 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018169 continue;
18170 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018171 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
18172 biType->builtInType, value, ctxt->value, ws);
18173 if (retFacet == 0)
18174 break;
18175 else if (retFacet < 0) {
18176 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
18177 "Internal error: xmlSchemaValidateFacetsInternal, "
18178 "validating enumeration facet '%s' of type '%s'.\n",
18179 facet->value, tmpType->name);
18180 ret = -1;
18181 break;
18182 }
18183 }
18184 if (retFacet <= 0)
18185 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018186 tmpType = tmpType->baseType;
18187 } while ((! found) && (tmpType != NULL) &&
18188 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018189 if (retFacet > 0) {
Kasimier T. Buchcik53b5e052005-03-24 11:05:13 +000018190 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018191 if (fireErrors) {
18192 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
18193 NULL, NULL, NULL, NULL);
18194 }
18195 }
18196 }
18197
18198 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018199 /*
18200 * Process patters. Pattern facets are ORed at type level
18201 * and ANDed if derived. Walk the base type axis.
18202 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018203 tmpType = type;
18204 facet = NULL;
18205 do {
18206 retFacet = 0;
18207 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018208 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018209 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
18210 continue;
18211 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
18212 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018213 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018214 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018215 else if (retFacet < 0) {
18216 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
18217 "Internal error: xmlSchemaValidateFacetsInternal, "
18218 "validating 'pattern' facet '%s' of type '%s'.\n",
18219 facetLink->facet->value, tmpType->name);
18220 ret = -1;
18221 break;
18222 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000018223 /* Save the last non-validating facet. */
18224 facet = facetLink->facet;
18225 }
18226 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018227 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018228 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018229 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018230 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018231 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
18232 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018233 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018234 NULL, NULL, NULL, NULL);
18235 }
18236 }
18237 }
18238
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018239 return (ret);
18240}
18241
Daniel Veillard4255d502002-04-16 15:50:10 +000018242/************************************************************************
18243 * *
18244 * Simple type validation *
18245 * *
18246 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018247
Daniel Veillard4255d502002-04-16 15:50:10 +000018248
18249/************************************************************************
18250 * *
18251 * DOM Validation code *
18252 * *
18253 ************************************************************************/
18254
Daniel Veillard4255d502002-04-16 15:50:10 +000018255static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018256 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000018257 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018258static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018259 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018260 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018261 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000018262
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018263static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018264static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018265
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018266/**
18267 * xmlSchemaGetFreshElemInfo:
18268 * @vctxt: the schema validation context
18269 *
18270 * Creates/reuses and initializes the element info item for
18271 * the currect tree depth.
18272 *
18273 * Returns the element info item or NULL on API or internal errors.
18274 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018275static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018276xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
18277 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018278{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018279 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018280
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018281 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018282 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018283 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018284 "an inconsistent depth encountered.\n",
18285 NULL, NULL);
18286 return (NULL);
18287 }
18288 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018289 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
18290 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018291 if (vctxt->elemInfos == NULL) {
18292 xmlSchemaVErrMemory(vctxt,
18293 "allocating the element info array", NULL);
18294 return (NULL);
18295 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018296 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018297 vctxt->sizeElemInfos = 10;
18298 } else if (vctxt->sizeElemInfos == vctxt->depth) {
18299 int i = vctxt->sizeElemInfos;
18300
18301 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018302 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018303 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018304 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018305 if (vctxt->elemInfos == NULL) {
18306 xmlSchemaVErrMemory(vctxt,
18307 "re-allocating the element info array", NULL);
18308 return (NULL);
18309 }
18310 /*
18311 * We need the new memory to be NULLed.
18312 * TODO: Use memset instead?
18313 */
18314 for (; i < vctxt->sizeElemInfos; i++)
18315 vctxt->elemInfos[i] = NULL;
18316 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018317 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018318
18319 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018320 info = (xmlSchemaNodeInfoPtr)
18321 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018322 if (info == NULL) {
18323 xmlSchemaVErrMemory(vctxt,
18324 "allocating an element info", NULL);
18325 return (NULL);
18326 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018327 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018328 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018329 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018330 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018331
18332 return (info);
18333}
Daniel Veillard3646d642004-06-02 19:19:14 +000018334
18335/**
18336 * xmlSchemaFreeAttrStates:
18337 * @state: a list of attribute states
18338 *
18339 * Free the given list of attribute states
18340 *
18341 */
18342static void
18343xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
18344{
18345 xmlSchemaAttrStatePtr tmp;
18346 while (state != NULL) {
18347 tmp = state;
18348 state = state->next;
18349 xmlFree(tmp);
18350 }
18351}
18352
Daniel Veillard4255d502002-04-16 15:50:10 +000018353/**
18354 * xmlSchemaRegisterAttributes:
18355 * @ctxt: a schema validation context
18356 * @attrs: a list of attributes
18357 *
18358 * Register the list of attributes as the set to be validated on that element
18359 *
18360 * Returns -1 in case of error, 0 otherwise
18361 */
18362static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018363xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
18364{
Daniel Veillard3646d642004-06-02 19:19:14 +000018365 xmlSchemaAttrStatePtr tmp;
18366
18367 ctxt->attr = NULL;
18368 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000018369 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018370 if ((attrs->ns != NULL) &&
18371 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
18372 attrs = attrs->next;
18373 continue;
18374 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018375 tmp = (xmlSchemaAttrStatePtr)
18376 xmlMalloc(sizeof(xmlSchemaAttrState));
18377 if (tmp == NULL) {
18378 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
18379 return (-1);
18380 }
Daniel Veillard3646d642004-06-02 19:19:14 +000018381 tmp->attr = attrs;
18382 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
18383 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018384 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018385 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018386 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000018387 else
18388 ctxt->attrTop->next = tmp;
18389 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018390 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000018391 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018392 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018393}
18394
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018395#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000018396/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018397 * xmlSchemaValidateCheckNodeList
18398 * @nodelist: the list of nodes
18399 *
18400 * Check the node list is only made of text nodes and entities pointing
18401 * to text nodes
18402 *
18403 * Returns 1 if true, 0 if false and -1 in case of error
18404 */
18405static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018406xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
18407{
Daniel Veillard4255d502002-04-16 15:50:10 +000018408 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018409 if (nodelist->type == XML_ENTITY_REF_NODE) {
18410 TODO /* implement recursion in the entity content */
18411 }
18412 if ((nodelist->type != XML_TEXT_NODE) &&
18413 (nodelist->type != XML_COMMENT_NODE) &&
18414 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000018415 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018416 return (0);
18417 }
18418 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000018419 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018420 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018421}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018422#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000018423
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018424static void
18425xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18426{
18427 int i, nbItems;
18428 xmlSchemaTypePtr item, *items;
18429
18430
18431 /*
18432 * During the Assemble of the schema ctxt->curItems has
18433 * been filled with the relevant new items. Fix those up.
18434 */
18435 nbItems = ctxt->assemble->nbItems;
18436 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
18437
18438 for (i = 0; i < nbItems; i++) {
18439 item = items[i];
18440 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018441 case XML_SCHEMA_TYPE_COMPLEX:
18442 case XML_SCHEMA_TYPE_SIMPLE:
18443 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18444 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018445 case XML_SCHEMA_TYPE_ATTRIBUTE:
18446 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18447 break;
18448 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018449 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018450 NULL, NULL, NULL);
18451 break;
18452 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18453 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
18454 ctxt, NULL);
18455 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018456 case XML_SCHEMA_TYPE_PARTICLE:
18457 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018458 default:
18459 break;
18460 }
18461 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018462 if (ctxt->nberrors != 0)
18463 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018464 /*
18465 * Circularity checks.
18466 */
18467 for (i = 0; i < nbItems; i++) {
18468 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018469 switch (item->type) {
18470 case XML_SCHEMA_TYPE_COMPLEX:
18471 case XML_SCHEMA_TYPE_SIMPLE:
18472 xmlSchemaCheckTypeDefCircular(
18473 (xmlSchemaTypePtr) item, ctxt, NULL);
18474 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018475 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018476 xmlSchemaCheckGroupDefCircular(
18477 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018478 break;
18479 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18480 xmlSchemaCheckAttributeGroupCircular(
18481 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18482 break;
18483 default:
18484 break;
18485 }
18486 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018487 if (ctxt->nberrors != 0)
18488 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018489 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018490 * Set the "term" of particles pointing to model group definitions
18491 * to the contained model group.
18492 */
18493 for (i = 0; i < nbItems; i++) {
18494 item = items[i];
18495 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18496 (((xmlSchemaParticlePtr) item)->children != NULL) &&
18497 (((xmlSchemaParticlePtr) item)->children->type ==
18498 XML_SCHEMA_TYPE_GROUP)) {
18499 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18500 ctxt, NULL);
18501 }
18502 }
18503 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018504 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018505 */
18506 for (i = 0; i < nbItems; i++) {
18507 item = items[i];
18508 switch (item->type) {
18509 case XML_SCHEMA_TYPE_SIMPLE:
18510 case XML_SCHEMA_TYPE_COMPLEX:
18511 xmlSchemaTypeFixup(item, ctxt, NULL);
18512 break;
18513 default:
18514 break;
18515 }
18516 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018517 if (ctxt->nberrors != 0)
18518 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018519 /*
18520 * Validate value contraint values.
18521 */
18522 for (i = 0; i < nbItems; i++) {
18523 item = items[i];
18524 switch (item->type) {
18525 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018526 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18527 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018528 break;
18529 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018530 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018531 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018532 break;
18533 default:
18534 break;
18535 }
18536 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018537 if (ctxt->nberrors != 0)
18538 return;
18539 /*
18540 * Build the content model for complex types.
18541 */
18542 for (i = 0; i < nbItems; i++) {
18543 item = items[i];
18544 switch (item->type) {
18545 case XML_SCHEMA_TYPE_COMPLEX:
18546 xmlSchemaBuildContentModel(item, ctxt, NULL);
18547 break;
18548 default:
18549 break;
18550 }
18551 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018552}
18553
18554/**
18555 * xmlSchemaAssembleByLocation:
18556 * @pctxt: a schema parser context
18557 * @vctxt: a schema validation context
18558 * @schema: the existing schema
18559 * @node: the node that fired the assembling
18560 * @nsName: the namespace name of the new schema
18561 * @location: the location of the schema
18562 *
18563 * Expands an existing schema by an additional schema.
18564 *
18565 * Returns 0 if the new schema is correct, a positive error code
18566 * number otherwise and -1 in case of an internal or API error.
18567 */
18568static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018569xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
18570 xmlSchemaPtr schema,
18571 xmlNodePtr node,
18572 const xmlChar *nsName,
18573 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018574{
18575 const xmlChar *targetNs, *oldtns;
18576 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018577 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018578 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018579 xmlSchemaParserCtxtPtr pctxt;
18580
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018581 /*
18582 * This should be used:
18583 * 1. on <import>(s)
18584 * 2. if requested by the validated instance
18585 * 3. if requested via the API
18586 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018587 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018588 return (-1);
18589 /*
18590 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018591 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018592 if ((vctxt->pctxt == NULL) &&
18593 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
18594 xmlSchemaVErr(vctxt, node,
18595 XML_SCHEMAV_INTERNAL,
18596 "Internal error: xmlSchemaAssembleByLocation, "
18597 "failed to create a temp. parser context.\n",
18598 NULL, NULL);
18599 return (-1);
18600 }
18601 pctxt = vctxt->pctxt;
18602 /*
18603 * Set the counter to produce unique names for anonymous items.
18604 */
18605 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018606 /*
18607 * Acquire the schema document.
18608 */
18609 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
18610 nsName, location, &doc, &targetNs, 0);
18611 if (ret != 0) {
18612 if (doc != NULL)
18613 xmlFreeDoc(doc);
18614 } else if (doc != NULL) {
18615 docElem = xmlDocGetRootElement(doc);
18616 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018617 * Create new assemble info.
18618 */
18619 if (pctxt->assemble == NULL) {
18620 pctxt->assemble = xmlSchemaNewAssemble();
18621 if (pctxt->assemble == NULL) {
18622 xmlSchemaVErrMemory(vctxt,
18623 "Memory error: xmlSchemaAssembleByLocation, "
18624 "allocating assemble info", NULL);
18625 xmlFreeDoc(doc);
18626 return (-1);
18627 }
18628 }
18629 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018630 * Save and reset the context & schema.
18631 */
18632 oldflags = schema->flags;
18633 oldtns = schema->targetNamespace;
18634 olddoc = schema->doc;
18635
18636 xmlSchemaClearSchemaDefaults(schema);
18637 schema->targetNamespace = targetNs;
18638 /* schema->nbCurItems = 0; */
18639 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018640 pctxt->ctxtType = NULL;
18641 pctxt->parentItem = NULL;
18642
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018643 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18644 if (pctxt->nberrors != 0) {
18645 vctxt->nberrors += pctxt->nberrors;
18646 goto finally;
18647 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018648 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018649 if (pctxt->nberrors != 0) {
18650 vctxt->nberrors += pctxt->nberrors;
18651 goto finally;
18652 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018653 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018654 if (pctxt->nberrors != 0)
18655 vctxt->nberrors += pctxt->nberrors;
18656finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018657 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018658 * Set the counter of items.
18659 */
18660 schema->counter = pctxt->counter;
18661 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018662 * Free the list of assembled components.
18663 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018664 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018665 /*
18666 * Restore the context & schema.
18667 */
18668 schema->flags = oldflags;
18669 schema->targetNamespace = oldtns;
18670 schema->doc = olddoc;
18671 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018672 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018673 return (ret);
18674}
18675
18676/**
18677 * xmlSchemaAssembleByXSIAttr:
18678 * @vctxt: a schema validation context
18679 * @xsiAttr: an xsi attribute
18680 * @noNamespace: whether a schema with no target namespace is exptected
18681 *
18682 * Expands an existing schema by an additional schema using
18683 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18684 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18685 * must be set to 1.
18686 *
18687 * Returns 0 if the new schema is correct, a positive error code
18688 * number otherwise and -1 in case of an internal or API error.
18689 */
18690static int
18691xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
18692 xmlAttrPtr xsiAttr,
18693 int noNamespace)
18694{
18695 xmlChar *value;
18696 const xmlChar *cur, *end;
18697 const xmlChar *nsname = NULL, *location;
18698 int count = 0;
18699 int ret = 0;
18700
18701 if (xsiAttr == NULL) {
18702 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
18703 NULL, NULL,
18704 "Internal error: xmlSchemaAssembleByXSIAttr, "
18705 "bad arguments", NULL);
18706 return (-1);
18707 }
18708 /*
18709 * Parse the value; we will assume an even number of values
18710 * to be given (this is how Xerces and XSV work).
18711 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018712 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018713 cur = value;
18714 do {
18715 if (noNamespace != 1) {
18716 /*
18717 * Get the namespace name.
18718 */
18719 while (IS_BLANK_CH(*cur))
18720 cur++;
18721 end = cur;
18722 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18723 end++;
18724 if (end == cur)
18725 break;
18726 count++;
18727 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
18728 cur = end;
18729 }
18730 /*
18731 * Get the URI.
18732 */
18733 while (IS_BLANK_CH(*cur))
18734 cur++;
18735 end = cur;
18736 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18737 end++;
18738 if (end == cur)
18739 break;
18740 count++;
18741 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018742 cur = end;
18743 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018744 xsiAttr->parent, nsname, location);
18745 if (ret == -1) {
18746 xmlSchemaVCustomErr(vctxt,
18747 XML_SCHEMAV_INTERNAL,
18748 (xmlNodePtr) xsiAttr, NULL,
18749 "Internal error: xmlSchemaAssembleByXSIAttr, "
18750 "assembling schemata", NULL);
18751 if (value != NULL)
18752 xmlFree(value);
18753 return (-1);
18754 }
18755 } while (*cur != 0);
18756 if (value != NULL)
18757 xmlFree(value);
18758 return (ret);
18759}
18760
18761/**
18762 * xmlSchemaAssembleByXSIElem:
18763 * @vctxt: a schema validation context
18764 * @elem: an element node possibly holding xsi attributes
18765 * @noNamespace: whether a schema with no target namespace is exptected
18766 *
18767 * Assembles an existing schema by an additional schema using
18768 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
18769 * of the given @elem.
18770 *
18771 * Returns 0 if the new schema is correct, a positive error code
18772 * number otherwise and -1 in case of an internal or API error.
18773 */
18774static int
18775xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
18776 xmlNodePtr elem)
18777{
18778 int ret = 0, retNs = 0;
18779 xmlAttrPtr attr;
18780
18781 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
18782 if (attr != NULL) {
18783 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
18784 if (retNs == -1)
18785 return (-1);
18786 }
18787 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
18788 if (attr != NULL) {
18789 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
18790 if (ret == -1)
18791 return (-1);
18792 }
18793 if (retNs != 0)
18794 return (retNs);
18795 else
18796 return (ret);
18797}
18798
Daniel Veillard4255d502002-04-16 15:50:10 +000018799/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018800 * xmlSchemaValidateCallback:
18801 * @ctxt: a schema validation context
18802 * @name: the name of the element detected (might be NULL)
18803 * @type: the type
18804 *
18805 * A transition has been made in the automata associated to an element
18806 * content model
18807 */
18808static void
18809xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018810 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018811 xmlSchemaBasicItemPtr item, xmlNodePtr node)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018812{
Daniel Veillard4255d502002-04-16 15:50:10 +000018813 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018814
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018815 /*
18816 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
18817 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018818 ctxt->node = node;
18819 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018820
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018821 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018822
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018823 /*
18824 * Assemble new schemata using xsi.
18825 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018826 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018827 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018828
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018829 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18830 if (ret == -1) {
18831 xmlSchemaVCustomErr(ctxt,
18832 XML_SCHEMAV_INTERNAL,
18833 ctxt->node, NULL,
18834 "Internal error: xmlSchemaValidateElement, "
18835 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018836 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018837 }
18838 /*
18839 * NOTE: We won't react on schema parser errors here.
18840 * TODO: But a warning would be nice.
18841 */
18842 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018843 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018844 case XML_SCHEMA_TYPE_ELEMENT: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018845#ifdef DEBUG_CONTENT
18846 xmlGenericError(xmlGenericErrorContext,
18847 "xmlSchemaValidateCallback: %s, %s, %s\n",
18848 name, ((xmlSchemaElementPtr) item)->name, node->name);
18849#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018850 xmlSchemaValidateElementByDeclaration(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018851 (xmlSchemaElementPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018852 break;
18853 }
18854 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018855#ifdef DEBUG_CONTENT
18856 xmlGenericError(xmlGenericErrorContext,
18857 "xmlSchemaValidateCallback: %s, <any>, %s\n",
18858 name, node->name);
18859#endif
18860 xmlSchemaValidateElementByWildcard(ctxt,
18861 (xmlSchemaWildcardPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018862 break;
18863 default:
18864 break;
18865 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018866leave:
18867
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018868 xmlSchemaEndElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000018869 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018870}
Daniel Veillard4255d502002-04-16 15:50:10 +000018871
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018872static int
18873xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18874 const xmlChar *value,
18875 xmlSchemaValPtr *val,
18876 xmlNodePtr node)
18877{
18878 int ret;
18879
18880 ret = xmlValidateQName(value, 1);
18881 if (ret != 0)
18882 return (ret);
18883
18884 {
18885 xmlChar *uri = NULL;
18886 xmlChar *local = NULL;
18887 xmlChar *prefix;
18888
18889 local = xmlSplitQName2(value, &prefix);
18890 if (prefix != NULL) {
18891 xmlNsPtr ns;
18892
18893 /*
18894 * TODO: Make this streamable.
18895 */
18896 if ((node == NULL) || (node->doc == NULL)) {
18897 xmlFree(prefix);
18898 xmlFree(local);
18899 return (3);
18900 }
18901
18902 ns = xmlSearchNs(node->doc, node, prefix);
18903 if (ns == NULL) {
18904 xmlFree(prefix);
18905 xmlFree(local);
18906 return (1);
18907 }
18908 }
18909 if (prefix != NULL) {
18910 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
18911 ret = 1;
18912 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
18913 NULL) == NULL)
18914 ret = 1;
18915
18916 if ((ret == 0) && (val != NULL)) {
18917 if (prefix != NULL) {
18918 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
18919 BAD_CAST xmlStrdup(uri));
18920 local = NULL;
18921 } else
18922 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
18923 NULL);
18924 if (*val == NULL)
18925 ret = -1;
18926 }
18927 if (local != NULL)
18928 xmlFree(local);
18929 }
18930
18931 return (ret);
18932}
18933
Daniel Veillard01fa6152004-06-29 17:04:39 +000018934/**
18935 * xmlSchemaValidateSimpleTypeValue:
18936 * @ctxt: a schema validation context
18937 * @value: the value to be validated
18938 * @fireErrors: shall errors be reported?
18939 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018940 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018941 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000018942 *
18943 * Validates a value by the given type (user derived or built-in).
18944 *
18945 * Returns 0 if the value is valid, a positive error code
18946 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000018947 */
18948static int
18949xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018950 xmlSchemaTypePtr type,
18951 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018952 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018953 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018954 int normalize,
18955 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018956{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018957 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018958 int ret = 0;
18959 xmlChar *normValue = NULL;
18960 int wtsp;
18961
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018962 node = ctxt->node;
18963 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018964 wtsp = ctxt->valueWS;
18965 /*
18966 * Normalize the value.
18967 */
18968 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018969 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018970 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
18971
18972 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018973 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018974 normValue = xmlSchemaCollapseString(value);
18975 else
18976 normValue = xmlSchemaWhiteSpaceReplace(value);
18977 ctxt->valueWS = norm;
18978 if (normValue != NULL)
18979 value = (const xmlChar *) normValue;
18980 }
18981 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018982 /*
18983 * The nodes of a content must be checked only once,
18984 * this is not working since list types will fire this
18985 * multiple times.
18986 */
18987 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
18988 xmlNodePtr cur = ctxt->cur;
18989
18990 do {
18991 switch (cur->type) {
18992 case XML_TEXT_NODE:
18993 case XML_CDATA_SECTION_NODE:
18994 case XML_PI_NODE:
18995 case XML_COMMENT_NODE:
18996 case XML_XINCLUDE_START:
18997 case XML_XINCLUDE_END:
18998 break;
18999 case XML_ENTITY_REF_NODE:
19000 case XML_ENTITY_NODE:
19001 /* TODO: Scour the entities for illegal nodes. */
19002 TODO break;
19003 case XML_ELEMENT_NODE: {
19004 /* NOTE: Changed to an internal error, since the
19005 * existence of an element node will be already checked in
19006 * xmlSchemaValidateElementBySimpleType and in
19007 * xmlSchemaValidateElementByComplexType.
19008 */
19009 xmlSchemaVCustomErr(ctxt,
19010 XML_SCHEMAV_INTERNAL,
19011 /* XML_SCHEMAS_ERR_INVALIDELEM, */
19012 node, type,
19013 "Element '%s' found in simple type content",
19014 cur->name);
19015 return (XML_SCHEMAV_INTERNAL);
19016 }
19017 case XML_ATTRIBUTE_NODE:
19018 case XML_DOCUMENT_NODE:
19019 case XML_DOCUMENT_TYPE_NODE:
19020 case XML_DOCUMENT_FRAG_NODE:
19021 case XML_NOTATION_NODE:
19022 case XML_HTML_DOCUMENT_NODE:
19023 case XML_DTD_NODE:
19024 case XML_ELEMENT_DECL:
19025 case XML_ATTRIBUTE_DECL:
19026 case XML_ENTITY_DECL:
19027 case XML_NAMESPACE_DECL:
19028#ifdef LIBXML_DOCB_ENABLED
19029 case XML_DOCB_DOCUMENT_NODE:
19030#endif
19031 xmlSchemaVCustomErr(ctxt,
19032 XML_SCHEMAV_INTERNAL,
19033 /* XML_SCHEMAS_ERR_INVALIDELEM, */
19034 node, NULL,
19035 "Node of unexpected type found in simple type content",
19036 NULL);
19037 return (XML_SCHEMAV_INTERNAL);
19038 }
19039 cur = cur->next;
19040 } while (cur != NULL);
19041 }
19042
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019043 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019044
19045 if (ctxt->value != NULL) {
19046 xmlSchemaFreeValue(ctxt->value);
19047 ctxt->value = NULL;
19048 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019049 /*
19050 * STREAM-READ-CHILDREN.
19051 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019052 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
19053 (ctxt->schema != NULL)) {
19054 /*
19055 * NOTATIONs need to be processed here, since they need
19056 * to lookup in the hashtable of NOTATION declarations.
19057 */
19058 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
19059 } else
19060 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019061 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019062 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
19063 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
19064 else
19065 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019066 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019067 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019068 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019069 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019070 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019071 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019072 } else if ((ctxt->value == NULL) &&
19073 (type->builtInType == XML_SCHEMAS_STRING) &&
19074 (ctxt->nodeInfo != NULL) &&
19075 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019076 xmlChar *valdup;
19077 /*
19078 * Create a precomputed string value for "string" as well if
19079 * requested.
19080 */
19081 valdup = xmlStrdup(value);
19082 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19083 BAD_CAST valdup);
19084 if ((valdup != NULL) && (ctxt->value == NULL))
19085 xmlFree(valdup);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019086 }
19087 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
19088 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
19089 * a literal in the ·lexical space· of {base type definition}
19090 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019091 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019092 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019093 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019094 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019095 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019096 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019097 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019098 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019099 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019100 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019101 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019102 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000019103 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019104 */
19105 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019106 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019107 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019108 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019109 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019110 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019111 type->name, NULL);
19112 } else if (ret > 0) {
19113 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019114 /*
19115 Disabled, since the facet validation already reports errors.
19116 if (fireErrors)
19117 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
19118 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019119 }
19120 }
19121 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
19122
19123 xmlSchemaTypePtr tmpType;
19124 const xmlChar *cur, *end;
19125 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019126 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019127
19128 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
19129 * of white space separated tokens, each of which ·match·es a literal
19130 * in the ·lexical space· of {item type definition}
19131 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000019132
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000019133 if (value == NULL)
19134 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000019135 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019136 cur = value;
19137 do {
19138 while (IS_BLANK_CH(*cur))
19139 cur++;
19140 end = cur;
19141 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
19142 end++;
19143 if (end == cur)
19144 break;
19145 tmp = xmlStrndup(cur, end - cur);
19146 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019147 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019148 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019149 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019150 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019151 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19152 "validating an item of list simple type '%s'\n",
19153 type->name, NULL);
19154 break;
19155 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019156 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019157 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019158 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019159 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019160 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019161 cur = end;
19162 } while (*cur != 0);
19163 /*
19164 * Check facets.
19165 */
19166 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019167 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019168 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019169 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019170 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019171 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019172 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019173 value, len, fireErrors);
19174 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019175 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019176 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19177 "validating facets of list simple type '%s'\n",
19178 type->name, NULL);
19179 } else if (ret > 0) {
19180 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019181 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000019182 Disabled, since the facet validation already reports errors.
19183 if (fireErrors)
19184 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019185 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019186 }
19187
Daniel Veillard01fa6152004-06-29 17:04:39 +000019188 }
19189 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
19190 xmlSchemaTypeLinkPtr memberLink;
19191
19192 /*
19193 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
19194 * not apply directly; however, the normalization behavior of ·union·
19195 * types is controlled by the value of whiteSpace on that one of the
19196 * ·memberTypes· against which the ·union· is successfully validated.
19197 *
19198 * This means that the value is normalized by the first validating
19199 * member type, then the facets of the union type are applied. This
19200 * needs changing of the value!
19201 */
19202
19203 /*
19204 * 1.2.3 if {variety} is ·union· then the string must ·match· a
19205 * literal in the ·lexical space· of at least one member of
19206 * {member type definitions}
19207 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019208#ifdef DEBUG_UNION_VALIDATION
19209 printf("Union ST : '%s'\n", (const char *) type->name);
19210 printf(" fireErrors : %d\n", fireErrors);
19211 printf(" applyFacets: %d\n", applyFacets);
19212#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000019213 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
19214 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019215 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019216 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019217 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019218 type->name, NULL);
19219 ret = -1;
19220 }
19221 if (ret == 0) {
19222 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019223 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
19224 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019225 if ((ret <= 0) || (ret == 0))
19226 break;
19227 memberLink = memberLink->next;
19228 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019229 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019230 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019231 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019232 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019233 type->name, NULL);
19234 } else if (ret > 0) {
19235 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019236 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019237 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019238 }
19239 }
19240 /*
19241 * Apply facets (pattern, enumeration).
19242 */
19243 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
19244 int mws;
19245 /*
19246 * The normalization behavior of ·union· types is controlled by
19247 * the value of whiteSpace on that one of the ·memberTypes·
19248 * against which the ·union· is successfully validated.
19249 */
19250 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019251 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019252 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19253 "the value was already normalized for the union simple "
19254 "type '%s'.\n", type->name, NULL);
19255 }
19256 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
19257 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019258 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019259 normValue = xmlSchemaCollapseString(value);
19260 else
19261 normValue = xmlSchemaWhiteSpaceReplace(value);
19262 if (normValue != NULL)
19263 value = (const xmlChar *) normValue;
19264 }
19265
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019266 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019267 value, 0, fireErrors);
19268 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019269 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019270 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19271 "validating facets of union simple type '%s'\n",
19272 type->name, NULL);
19273 } else if (ret > 0) {
19274 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
19275 /*
19276 if (fireErrors)
19277 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
19278 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019279 }
19280 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019281 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019282 ctxt->valueWS = wtsp;
19283 if (normValue != NULL)
19284 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019285 return (ret);
19286}
19287
19288/**
19289 * xmlSchemaValidateSimpleTypeElement:
19290 * @ctxt: a schema validation context
19291 * @node: the element node to be validated.
19292 *
19293 * Validate the element against a simple type.
19294 *
19295 * Returns 0 if the element is valid, a positive error code
19296 * number otherwise and -1 in case of an internal or API error.
19297 */
19298static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019299xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019300 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019301 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019302 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019303{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019304 xmlSchemaTypePtr oldtype;
19305 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019306 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019307 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019308 int ret = 0, retval = 0;
19309
Daniel Veillard01fa6152004-06-29 17:04:39 +000019310 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019311 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19312 "Internal error: xmlSchemaValidateElementBySimpleType, "
19313 "bad arguments", NULL);
19314 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019315 }
19316
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019317 oldtype = ctxt->type;
19318 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019319 /*
19320 * cvc-type: 3.1.2 The element information item must have no element
19321 * information item [children].
19322 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019323 /*
19324 * STREAM: Child nodes are processed.
19325 */
19326 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019327 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019328 /*
19329 * TODO: Entities, will they produce elements as well?
19330 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019331 if (cur->type == XML_ELEMENT_NODE) {
19332 xmlSchemaVCustomErr(ctxt,
19333 XML_SCHEMAV_CVC_TYPE_3_1_2,
19334 node, type,
19335 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019336 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019337 }
19338 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019339 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019340
Daniel Veillard01fa6152004-06-29 17:04:39 +000019341 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019342 * cvc-type 3.1.1:
19343 *
19344 * The attributes of must be empty, excepting those whose namespace name
19345 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
19346 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019347 */
19348 /*
19349 * STREAM: Attribute nodes are processed.
19350 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019351 attr = node->properties;
19352 while (attr != NULL) {
19353 if ((attr->ns == NULL) ||
19354 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
19355 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
19356 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
19357 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
19358 (!xmlStrEqual
19359 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019360 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019361 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
19362 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019363 }
19364 attr = attr->next;
19365 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019366 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019367 * This will skip validation if the type is 'anySimpleType' and
19368 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019369 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019370 if ((! isNil) &&
19371 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019372 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
19373 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019374 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019375
19376 value = xmlNodeGetContent(node);
19377 /*
19378 * NOTE: This call will not check the content nodes, since
19379 * this should be checked here already.
19380 */
19381 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
19382 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019383 if (value != NULL)
19384 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019385 if (retval != 0)
19386 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000019387 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019388 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019389 return (ret);
19390}
Daniel Veillard4255d502002-04-16 15:50:10 +000019391
19392/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019393 * xmlSchemaValQNameAcquire:
19394 * @value: the lexical represantation of the QName value
19395 * @node: the node to search for the corresponding namespace declaration
19396 * @nsName: the resulting namespace name if found
19397 *
19398 * Checks that a value conforms to the lexical space of the type QName;
19399 * if valid, the corresponding namespace name is searched and retured
19400 * as a copy in @nsName. The local name is returned in @localName as
19401 * a copy.
19402 *
19403 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
19404 * namespace declaration was found in scope; -1 in case of an internal or
19405 * API error.
19406 */
19407static int
19408xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
19409 xmlChar **nsName, xmlChar **localName)
19410{
19411 int ret;
19412 xmlChar *local = NULL;
19413
19414 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
19415 return (-1);
19416 *nsName = NULL;
19417 *localName = NULL;
19418 ret = xmlValidateQName(value, 1);
19419 if (ret == 0) {
19420 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019421 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019422
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019423 /*
19424 * NOTE: xmlSplitQName2 will return a duplicated
19425 * string.
19426 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019427 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019428 if (local == NULL)
19429 local = xmlStrdup(value);
19430 ns = xmlSearchNs(node->doc, node, prefix);
19431 /*
19432 * A namespace need not to be found if the prefix is NULL.
19433 */
19434 if (ns != NULL) {
19435 /*
19436 * TODO: Is it necessary to duplicate the URI here?
19437 */
19438 *nsName = xmlStrdup(ns->href);
19439 } else if (prefix != NULL) {
19440 xmlFree(prefix);
19441 if (local != NULL)
19442 xmlFree(local);
19443 return (2);
19444 }
19445 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019446 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019447 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019448 } else
19449 return (1);
19450 return (ret);
19451}
19452
19453/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019454 * xmlSchemaHasElemContent:
19455 * @node: the node
19456 *
19457 * Scours the content of the given node for element
19458 * nodes.
19459 *
19460 * Returns 1 if an element node is found,
19461 * 0 otherwise.
19462 */
19463static int
19464xmlSchemaHasElemContent(xmlNodePtr node)
19465{
19466 if (node == NULL)
19467 return (0);
19468 node = node->children;
19469 while (node != NULL) {
19470 if (node->type == XML_ELEMENT_NODE)
19471 return (1);
19472 node = node->next;
19473 }
19474 return (0);
19475}
19476/**
19477 * xmlSchemaHasElemOrCharContent:
19478 * @node: the node
19479 *
19480 * Scours the content of the given node for element
19481 * and character nodes.
19482 *
19483 * Returns 1 if an element or character node is found,
19484 * 0 otherwise.
19485 */
19486static int
19487xmlSchemaHasElemOrCharContent(xmlNodePtr node)
19488{
19489 if (node == NULL)
19490 return (0);
19491 node = node->children;
19492 while (node != NULL) {
19493 switch (node->type) {
19494 case XML_ELEMENT_NODE:
19495 /*
19496 * TODO: Ask Daniel if these are all character nodes.
19497 */
19498 case XML_TEXT_NODE:
19499 case XML_CDATA_SECTION_NODE:
19500 /*
19501 * TODO: How XML_ENTITY_NODEs evaluated?
19502 */
19503 case XML_ENTITY_REF_NODE:
19504 case XML_ENTITY_NODE:
19505 return (1);
19506 break;
19507 default:
19508 break;
19509 }
19510 node = node->next;
19511 }
19512 return (0);
19513}
19514
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019515/************************************************************************
19516 * *
19517 * Identity-constraints (IDC) *
19518 * *
19519 ************************************************************************/
19520
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019521/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019522 * xmlSchemaAugmentIDC:
19523 * @idcDef: the IDC definition
19524 *
19525 * Creates an augmented IDC definition item.
19526 *
19527 * Returns the item, or NULL on internal errors.
19528 */
19529static void
19530xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
19531 xmlSchemaValidCtxtPtr vctxt)
19532{
19533 xmlSchemaIDCAugPtr aidc;
19534
19535 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
19536 if (aidc == NULL) {
19537 xmlSchemaVErrMemory(vctxt,
19538 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
19539 NULL);
19540 return;
19541 }
19542 aidc->bubbleDepth = -1;
19543 aidc->def = idcDef;
19544 aidc->next = NULL;
19545 if (vctxt->aidcs == NULL)
19546 vctxt->aidcs = aidc;
19547 else {
19548 aidc->next = vctxt->aidcs;
19549 vctxt->aidcs = aidc;
19550 }
19551}
19552
19553/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019554 * xmlSchemaIDCNewBinding:
19555 * @idcDef: the IDC definition of this binding
19556 *
19557 * Creates a new IDC binding.
19558 *
19559 * Returns the new binding in case of succeeded, NULL on internal errors.
19560 */
19561static xmlSchemaPSVIIDCBindingPtr
19562xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
19563{
19564 xmlSchemaPSVIIDCBindingPtr ret;
19565
19566 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
19567 sizeof(xmlSchemaPSVIIDCBinding));
19568 if (ret == NULL) {
19569 xmlSchemaVErrMemory(NULL,
19570 "allocating a PSVI IDC binding item", NULL);
19571 return (NULL);
19572 }
19573 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
19574 ret->definition = idcDef;
19575 return (ret);
19576}
19577
19578/**
19579 * xmlSchemaIDCStoreNodeTableItem:
19580 * @vctxt: the WXS validation context
19581 * @item: the IDC node table item
19582 *
19583 * The validation context is used to store an IDC node table items.
19584 * They are stored to avoid copying them if IDC node-tables are merged
19585 * with corresponding parent IDC node-tables (bubbling).
19586 *
19587 * Returns 0 if succeeded, -1 on internal errors.
19588 */
19589static int
19590xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
19591 xmlSchemaPSVIIDCNodePtr item)
19592{
19593 /*
19594 * Add to gobal list.
19595 */
19596 if (vctxt->idcNodes == NULL) {
19597 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19598 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
19599 if (vctxt->idcNodes == NULL) {
19600 xmlSchemaVErrMemory(vctxt,
19601 "allocating the IDC node table item list", NULL);
19602 return (-1);
19603 }
19604 vctxt->sizeIdcNodes = 20;
19605 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
19606 vctxt->sizeIdcNodes *= 2;
19607 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19608 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
19609 sizeof(xmlSchemaPSVIIDCNodePtr));
19610 if (vctxt->idcNodes == NULL) {
19611 xmlSchemaVErrMemory(vctxt,
19612 "re-allocating the IDC node table item list", NULL);
19613 return (-1);
19614 }
19615 }
19616 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
19617
19618 return (0);
19619}
19620
19621/**
19622 * xmlSchemaIDCStoreKey:
19623 * @vctxt: the WXS validation context
19624 * @item: the IDC key
19625 *
19626 * The validation context is used to store an IDC key.
19627 *
19628 * Returns 0 if succeeded, -1 on internal errors.
19629 */
19630static int
19631xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
19632 xmlSchemaPSVIIDCKeyPtr key)
19633{
19634 /*
19635 * Add to gobal list.
19636 */
19637 if (vctxt->idcKeys == NULL) {
19638 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19639 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
19640 if (vctxt->idcKeys == NULL) {
19641 xmlSchemaVErrMemory(vctxt,
19642 "allocating the IDC key storage list", NULL);
19643 return (-1);
19644 }
19645 vctxt->sizeIdcKeys = 40;
19646 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
19647 vctxt->sizeIdcKeys *= 2;
19648 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19649 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
19650 sizeof(xmlSchemaPSVIIDCKeyPtr));
19651 if (vctxt->idcKeys == NULL) {
19652 xmlSchemaVErrMemory(vctxt,
19653 "re-allocating the IDC key storage list", NULL);
19654 return (-1);
19655 }
19656 }
19657 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
19658
19659 return (0);
19660}
19661
19662/**
19663 * xmlSchemaIDCAppendNodeTableItem:
19664 * @bind: the IDC binding
19665 * @ntItem: the node-table item
19666 *
19667 * Appends the IDC node-table item to the binding.
19668 *
19669 * Returns 0 on success and -1 on internal errors.
19670 */
19671static int
19672xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19673 xmlSchemaPSVIIDCNodePtr ntItem)
19674{
19675 if (bind->nodeTable == NULL) {
19676 bind->sizeNodes = 10;
19677 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19678 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19679 if (bind->nodeTable == NULL) {
19680 xmlSchemaVErrMemory(NULL,
19681 "allocating an array of IDC node-table items", NULL);
19682 return(-1);
19683 }
19684 } else if (bind->sizeNodes <= bind->nbNodes) {
19685 bind->sizeNodes *= 2;
19686 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19687 xmlRealloc(bind->nodeTable, bind->sizeNodes *
19688 sizeof(xmlSchemaPSVIIDCNodePtr));
19689 if (bind->nodeTable == NULL) {
19690 xmlSchemaVErrMemory(NULL,
19691 "re-allocating an array of IDC node-table items", NULL);
19692 return(-1);
19693 }
19694 }
19695 bind->nodeTable[bind->nbNodes++] = ntItem;
19696 return(0);
19697}
19698
19699/**
19700 * xmlSchemaIDCAquireBinding:
19701 * @vctxt: the WXS validation context
19702 * @matcher: the IDC matcher
19703 *
19704 * Looks up an PSVI IDC binding, for the IDC definition and
19705 * of the given matcher. If none found, a new one is created
19706 * and added to the IDC table.
19707 *
19708 * Returns an IDC binding or NULL on internal errors.
19709 */
19710static xmlSchemaPSVIIDCBindingPtr
19711xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19712 xmlSchemaIDCMatcherPtr matcher)
19713{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019714 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019715
19716 info = vctxt->elemInfos[matcher->depth];
19717
19718 if (info->idcTable == NULL) {
19719 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19720 if (info->idcTable == NULL)
19721 return (NULL);
19722 return(info->idcTable);
19723 } else {
19724 xmlSchemaPSVIIDCBindingPtr bind = NULL;
19725
19726 bind = info->idcTable;
19727 do {
19728 if (bind->definition == matcher->aidc->def)
19729 return(bind);
19730 if (bind->next == NULL) {
19731 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19732 if (bind->next == NULL)
19733 return (NULL);
19734 return(bind->next);
19735 }
19736 bind = bind->next;
19737 } while (bind != NULL);
19738 }
19739 return (NULL);
19740}
19741
19742/**
19743 * xmlSchemaIDCFreeKey:
19744 * @key: the IDC key
19745 *
19746 * Frees an IDC key together with its compiled value.
19747 */
19748static void
19749xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19750{
19751 if (key->compValue != NULL)
19752 xmlSchemaFreeValue(key->compValue);
19753 xmlFree(key);
19754}
19755
19756/**
19757 * xmlSchemaIDCFreeBinding:
19758 *
19759 * Frees an IDC binding. Note that the node table-items
19760 * are not freed.
19761 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019762static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019763xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19764{
19765 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019766 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19767 int i;
19768 /*
19769 * Node-table items for keyrefs are not stored globally
19770 * to the validation context, since they are not bubbled.
19771 * We need to free them here.
19772 */
19773 for (i = 0; i < bind->nbNodes; i++) {
19774 xmlFree(bind->nodeTable[i]->keys);
19775 xmlFree(bind->nodeTable[i]);
19776 }
19777 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019778 xmlFree(bind->nodeTable);
19779 }
19780 xmlFree(bind);
19781}
19782
19783/**
19784 * xmlSchemaIDCFreeIDCTable:
19785 * @bind: the first IDC binding in the list
19786 *
19787 * Frees an IDC table, i.e. all the IDC bindings in the list.
19788 */
19789static void
19790xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19791{
19792 xmlSchemaPSVIIDCBindingPtr prev;
19793
19794 while (bind != NULL) {
19795 prev = bind;
19796 bind = bind->next;
19797 xmlSchemaIDCFreeBinding(prev);
19798 }
19799}
19800
19801/**
19802 * xmlSchemaIDCFreeMatcherList:
19803 * @matcher: the first IDC matcher in the list
19804 *
19805 * Frees a list of IDC matchers.
19806 */
19807static void
19808xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19809{
19810 xmlSchemaIDCMatcherPtr next;
19811
19812 while (matcher != NULL) {
19813 next = matcher->next;
19814 if (matcher->keySeqs != NULL) {
19815 int i;
19816 for (i = 0; i < matcher->sizeKeySeqs; i++)
19817 if (matcher->keySeqs[i] != NULL)
19818 xmlFree(matcher->keySeqs[i]);
19819 xmlFree(matcher->keySeqs);
19820 }
19821 xmlFree(matcher);
19822 matcher = next;
19823 }
19824}
19825
19826/**
19827 * xmlSchemaAreValuesEqual:
19828 * @ta: the first type
19829 * @a: the first value
19830 * @tb: the second type
19831 * @b: the second value
19832 *
19833 * Compares two values.
19834 *
19835 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
19836 */
19837static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019838xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
19839 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019840 xmlSchemaValPtr a,
19841 xmlSchemaTypePtr tb,
19842 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019843{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019844 /* Same user derived/built-in derived/built-in primitive types. */
19845 if (ta == tb)
19846 goto compareValue;
19847
19848 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019849 * Note that comparison with anySimpleTypes with be supported for
19850 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019851 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019852#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019853 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
19854 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19855 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019856#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019857
19858 /*
19859 * 4.2.1 equal (data-types)
19860 *
19861 * the ·value space·s of all ·primitive· datatypes are disjoint
19862 * (they do not share any values)
19863 */
19864 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
19865 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
19866 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
19867 return(0);
19868
19869 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19870 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
19871 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19872 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
19873 TODO
19874 return(0);
19875 }
19876 /*
19877 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
19878 * T then the ·value space· of T' is a subset of the ·value space· of T.
19879 */
19880 /*
19881 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
19882 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
19883 */
19884
19885 {
19886 xmlSchemaTypePtr pta = ta, ptb = tb;
19887
19888 /* Note that we will compare the primitives here. */
19889 while ((pta->builtInType == 0) ||
19890 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19891 pta = pta->baseType;
19892 while ((ptb->builtInType == 0) ||
19893 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19894 ptb = ptb->baseType;
19895 if (pta == ptb)
19896 goto compareValue;
19897 return(0);
19898 }
19899compareValue:
19900 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019901 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019902 int aws, bws;
19903
19904 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
19905 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
19906
19907 ret = xmlSchemaCompareValuesWhtsp(
19908 a, (xmlSchemaWhitespaceValueType) aws,
19909 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019910 if (ret == 0)
19911 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019912 else if (ret == -2) {
19913 xmlSchemaVErr(vctxt, vctxt->node,
19914 XML_SCHEMAV_INTERNAL,
19915 "Internal error: xmlSchemaAreValuesEqual, "
19916 "failed to compare the values.\n",
19917 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019918 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019919 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019920 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019921 }
19922}
19923
19924/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019925 * xmlSchemaIDCAddStateObject:
19926 * @vctxt: the WXS validation context
19927 * @matcher: the IDC matcher
19928 * @sel: the XPath information
19929 * @parent: the parent "selector" state object if any
19930 * @type: "selector" or "field"
19931 *
19932 * Creates/reuses and activates state objects for the given
19933 * XPath information; if the XPath expression consists of unions,
19934 * multiple state objects are created for every unioned expression.
19935 *
19936 * Returns 0 on success and -1 on internal errors.
19937 */
19938static int
19939xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19940 xmlSchemaIDCMatcherPtr matcher,
19941 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019942 int type)
19943{
19944 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019945
19946 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019947 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019948 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019949 if (vctxt->xpathStatePool != NULL) {
19950 sto = vctxt->xpathStatePool;
19951 vctxt->xpathStatePool = sto->next;
19952 sto->next = NULL;
19953 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019954 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019955 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019956 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019957 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19958 if (sto == NULL) {
19959 xmlSchemaVErrMemory(NULL,
19960 "allocating an IDC state object", NULL);
19961 return (-1);
19962 }
19963 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19964 }
19965 /*
19966 * Add to global list.
19967 */
19968 if (vctxt->xpathStates != NULL)
19969 sto->next = vctxt->xpathStates;
19970 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019971
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019972 /*
19973 * Free the old xpath validation context.
19974 */
19975 if (sto->xpathCtxt != NULL)
19976 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19977
19978 /*
19979 * Create a new XPath (pattern) validation context.
19980 */
19981 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19982 (xmlPatternPtr) sel->xpathComp);
19983 if (sto->xpathCtxt == NULL) {
19984 xmlSchemaVErr(vctxt, vctxt->node,
19985 XML_SCHEMAV_INTERNAL,
19986 "Internal error: xmlSchemaIDCAddStateObject, "
19987 "failed to create the XPath validation context.\n",
19988 NULL, NULL);
19989 return (-1);
19990 }
19991 sto->type = type;
19992 sto->depth = vctxt->depth;
19993 sto->matcher = matcher;
19994 sto->sel = sel;
19995 sto->nbHistory = 0;
19996
19997#if DEBUG_IDC
19998 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19999 sto->sel->xpath);
20000#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020001 return (0);
20002}
20003
20004/**
20005 * xmlSchemaXPathEvaluate:
20006 * @vctxt: the WXS validation context
20007 * @nodeType: the nodeType of the current node
20008 *
20009 * Evaluates all active XPath state objects.
20010 *
20011 * Returns the number of IC "field" state objects which resolved to
20012 * this node, 0 if none resolved and -1 on internal errors.
20013 */
20014static int
20015xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020016 xmlElementType nodeType)
20017{
20018 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020019 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020020
20021 if (vctxt->xpathStates == NULL)
20022 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020023
20024 if (nodeType == XML_ATTRIBUTE_NODE)
20025 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020026#if DEBUG_IDC
20027 {
20028 xmlChar *str = NULL;
20029 xmlGenericError(xmlGenericErrorContext,
20030 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020031 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20032 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020033 FREE_AND_NULL(str)
20034 }
20035#endif
20036 /*
20037 * Process all active XPath state objects.
20038 */
20039 first = vctxt->xpathStates;
20040 sto = first;
20041 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020042#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020043 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020044 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
20045 sto->matcher->aidc->def->name, sto->sel->xpath);
20046 else
20047 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
20048 sto->matcher->aidc->def->name, sto->sel->xpath);
20049#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020050 if (nodeType == XML_ELEMENT_NODE)
20051 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
20052 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
20053 else
20054 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
20055 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
20056
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020057 if (res == -1) {
20058 xmlSchemaVErr(vctxt, vctxt->node,
20059 XML_SCHEMAV_INTERNAL,
20060 "Internal error: xmlSchemaXPathEvaluate, "
20061 "failed to evaluate a node.\n",
20062 NULL, NULL);
20063 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020064 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020065 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020066 goto next_sto;
20067 /*
20068 * Full match.
20069 */
20070#if DEBUG_IDC
20071 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020072 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020073#endif
20074 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020075 * Register a match in the state object history.
20076 */
20077 if (sto->history == NULL) {
20078 sto->history = (int *) xmlMalloc(5 * sizeof(int));
20079 if (sto->history == NULL) {
20080 xmlSchemaVErrMemory(NULL,
20081 "allocating the state object history", NULL);
20082 return(-1);
20083 }
20084 sto->sizeHistory = 10;
20085 } else if (sto->sizeHistory <= sto->nbHistory) {
20086 sto->sizeHistory *= 2;
20087 sto->history = (int *) xmlRealloc(sto->history,
20088 sto->sizeHistory * sizeof(int));
20089 if (sto->history == NULL) {
20090 xmlSchemaVErrMemory(NULL,
20091 "re-allocating the state object history", NULL);
20092 return(-1);
20093 }
20094 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020095 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020096
20097#ifdef DEBUG_IDC
20098 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
20099 vctxt->depth);
20100#endif
20101
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020102 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
20103 xmlSchemaIDCSelectPtr sel;
20104 /*
20105 * Activate state objects for the IDC fields of
20106 * the IDC selector.
20107 */
20108#if DEBUG_IDC
20109 xmlGenericError(xmlGenericErrorContext, "IDC: "
20110 "activating field states\n");
20111#endif
20112 sel = sto->matcher->aidc->def->fields;
20113 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020114 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
20115 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
20116 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020117 sel = sel->next;
20118 }
20119 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
20120 /*
20121 * An IDC key node was found.
20122 */
20123#if DEBUG_IDC
20124 xmlGenericError(xmlGenericErrorContext,
20125 "IDC: key found\n");
20126#endif
20127 /*
20128 * Notify that the character value of this node is
20129 * needed.
20130 */
20131 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020132 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020133 resolved++;
20134 }
20135next_sto:
20136 if (sto->next == NULL) {
20137 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020138 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020139 */
20140 head = first;
20141 sto = vctxt->xpathStates;
20142 } else
20143 sto = sto->next;
20144 }
20145 return (resolved);
20146}
20147
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020148static const xmlChar *
20149xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr ctxt,
20150 xmlChar **buf,
20151 xmlSchemaPSVIIDCKeyPtr *seq,
20152 int count)
20153{
20154 int i, res;
20155 const xmlChar *value = NULL;
20156
20157 *buf = xmlStrdup(BAD_CAST "[");
20158 for (i = 0; i < count; i++) {
20159 *buf = xmlStrcat(*buf, BAD_CAST "'");
20160 res = xmlSchemaGetCanonValueWhtsp(seq[i]->compValue, &value,
20161 (xmlSchemaWhitespaceValueType)
20162 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
20163 if (res == 0)
20164 *buf = xmlStrcat(*buf, value);
20165 else {
20166 xmlSchemaVErr(ctxt, ctxt->node,
20167 XML_SCHEMAV_INTERNAL,
20168 "Internal error: xmlSchemaFormatIDCKeySequence, "
20169 "failed to compute canonical value.\n",
20170 NULL, NULL);
20171 *buf = xmlStrcat(*buf, BAD_CAST "???");
20172 }
20173 if (i < count -1)
20174 *buf = xmlStrcat(*buf, BAD_CAST "', ");
20175 else
20176 *buf = xmlStrcat(*buf, BAD_CAST "'");
20177 if (value != NULL) {
20178 xmlFree((xmlChar *) value);
20179 value = NULL;
20180 }
20181 }
20182 *buf = xmlStrcat(*buf, BAD_CAST "]");
20183
20184 return (BAD_CAST *buf);
20185}
20186
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020187/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020188 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020189 * @vctxt: the WXS validation context
20190 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020191 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020192 *
20193 * Processes and pops the history items of the IDC state objects.
20194 * IDC key-sequences are validated/created on IDC bindings.
20195 *
20196 * Returns 0 on success and -1 on internal errors.
20197 */
20198static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020199xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020200 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020201{
20202 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020203 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020204 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020205 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020206
20207 if (vctxt->xpathStates == NULL)
20208 return (0);
20209 sto = vctxt->xpathStates;
20210
20211#if DEBUG_IDC
20212 {
20213 xmlChar *str = NULL;
20214 xmlGenericError(xmlGenericErrorContext,
20215 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020216 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20217 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020218 FREE_AND_NULL(str)
20219 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020220#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020221 /*
20222 * Evaluate the state objects.
20223 */
20224 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020225 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020226#if DEBUG_IDC
20227 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
20228 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020229#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020230 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020231 goto deregister_check;
20232
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020233 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020234
20235 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020236 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020237 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020238 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020239 sto = sto->next;
20240 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020241 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020242 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
20243 if (! IS_SIMPLE_TYPE(type)) {
20244 /*
20245 * Not qualified if the field resolves to a node of non
20246 * simple type.
20247 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020248 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020249 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020250 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020251 (xmlSchemaTypePtr) sto->matcher->aidc->def,
20252 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020253 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020254
20255 sto->nbHistory--;
20256 goto deregister_check;
20257 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020258 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020259 /*
20260 * Failed to provide the normalized value; maby
20261 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020262 */
20263 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020264 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020265 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020266 (xmlSchemaTypePtr) sto->matcher->aidc->def,
20267 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020268 "was either invalid or something strange happend",
20269 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020270 /*
20271 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020272 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020273 "Internal error: xmlSchemaXPathProcessHistory, "
20274 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020275 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020276 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020277 sto->nbHistory--;
20278 goto deregister_check;
20279 } else {
20280 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
20281 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020282 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020283
20284 /*
20285 * The key will be anchored on the matcher's list of
20286 * key-sequences. The position in this list is determined
20287 * by the target node's depth relative to the matcher's
20288 * depth of creation (i.e. the depth of the scope element).
20289 */
20290 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020291 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020292
20293 /*
20294 * Create/grow the array of key-sequences.
20295 */
20296 if (matcher->keySeqs == NULL) {
20297 if (pos > 9)
20298 matcher->sizeKeySeqs = pos * 2;
20299 else
20300 matcher->sizeKeySeqs = 10;
20301 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
20302 xmlMalloc(matcher->sizeKeySeqs *
20303 sizeof(xmlSchemaPSVIIDCKeyPtr *));
20304 if (matcher->keySeqs == NULL) {
20305 xmlSchemaVErrMemory(NULL,
20306 "allocating an array of key-sequences",
20307 NULL);
20308 return(-1);
20309 }
20310 memset(matcher->keySeqs, 0,
20311 matcher->sizeKeySeqs *
20312 sizeof(xmlSchemaPSVIIDCKeyPtr *));
20313 } else if (pos >= matcher->sizeKeySeqs) {
20314 int i = matcher->sizeKeySeqs;
20315
20316 matcher->sizeKeySeqs *= 2;
20317 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
20318 xmlRealloc(matcher->keySeqs,
20319 matcher->sizeKeySeqs *
20320 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020321 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020322 xmlSchemaVErrMemory(NULL,
20323 "reallocating an array of key-sequences",
20324 NULL);
20325 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020326 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020327 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020328 * The array needs to be NULLed.
20329 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020330 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020331 for (; i < matcher->sizeKeySeqs; i++)
20332 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020333 }
20334
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020335 /*
20336 * Get/create the key-sequence.
20337 */
20338 keySeq = matcher->keySeqs[pos];
20339 if (keySeq == NULL) {
20340 goto create_sequence;
20341 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020342 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020343 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020344 * cvc-identity-constraint:
20345 * 3 For each node in the ·target node set· all
20346 * of the {fields}, with that node as the context
20347 * node, evaluate to either an empty node-set or
20348 * a node-set with exactly one member, which must
20349 * have a simple type.
20350 *
20351 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020352 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020353 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020354 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020355 vctxt->nodeInfo,
20356 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020357 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020358 "with more than one member",
20359 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020360 sto->nbHistory--;
20361 goto deregister_check;
20362 } else {
20363 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020364 }
20365 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020366
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020367create_sequence:
20368 /*
20369 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020370 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020371 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
20372 matcher->aidc->def->nbFields *
20373 sizeof(xmlSchemaPSVIIDCKeyPtr));
20374 if (keySeq == NULL) {
20375 xmlSchemaVErrMemory(NULL,
20376 "allocating an IDC key-sequence", NULL);
20377 return(-1);
20378 }
20379 memset(keySeq, 0, matcher->aidc->def->nbFields *
20380 sizeof(xmlSchemaPSVIIDCKeyPtr));
20381 matcher->keySeqs[pos] = keySeq;
20382create_key:
20383 /*
20384 * Created a key once per node only.
20385 */
20386 if (key == NULL) {
20387 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
20388 sizeof(xmlSchemaPSVIIDCKey));
20389 if (key == NULL) {
20390 xmlSchemaVErrMemory(NULL,
20391 "allocating a IDC key", NULL);
20392 xmlFree(keySeq);
20393 matcher->keySeqs[pos] = NULL;
20394 return(-1);
20395 }
20396 /*
20397 * Consume the compiled value.
20398 */
20399 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020400 key->compValue = vctxt->nodeInfo->value;
20401 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020402 /*
20403 * Store the key in a global list.
20404 */
20405 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
20406 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020407 return (-1);
20408 }
20409 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020410 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020411 }
20412 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020413
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020414 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
20415 xmlSchemaPSVIIDCBindingPtr bind;
20416 xmlSchemaPSVIIDCNodePtr ntItem;
20417 xmlSchemaIDCMatcherPtr matcher;
20418 xmlSchemaIDCPtr idc;
20419 int pos, i, j, nbKeys;
20420 /*
20421 * Here we have the following scenario:
20422 * An IDC 'selector' state object resolved to a target node,
20423 * during the time this target node was in the
20424 * ancestor-or-self axis, the 'field' state object(s) looked
20425 * out for matching nodes to create a key-sequence for this
20426 * target node. Now we are back to this target node and need
20427 * to put the key-sequence, together with the target node
20428 * itself, into the node-table of the corresponding IDC
20429 * binding.
20430 */
20431 matcher = sto->matcher;
20432 idc = matcher->aidc->def;
20433 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020434 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020435 /*
20436 * Check if the matcher has any key-sequences at all, plus
20437 * if it has a key-sequence for the current target node.
20438 */
20439 if ((matcher->keySeqs == NULL) ||
20440 (matcher->sizeKeySeqs <= pos)) {
20441 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
20442 goto selector_key_error;
20443 else
20444 goto selector_leave;
20445 }
20446
20447 keySeq = &(matcher->keySeqs[pos]);
20448 if (*keySeq == NULL) {
20449 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
20450 goto selector_key_error;
20451 else
20452 goto selector_leave;
20453 }
20454
20455 for (i = 0; i < nbKeys; i++) {
20456 if ((*keySeq)[i] == NULL) {
20457 /*
20458 * Not qualified, if not all fields did resolve.
20459 */
20460 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
20461 /*
20462 * All fields of a "key" IDC must resolve.
20463 */
20464 goto selector_key_error;
20465 }
20466 goto selector_leave;
20467 }
20468 }
20469 /*
20470 * All fields did resolve.
20471 */
20472
20473 /*
20474 * 4.1 If the {identity-constraint category} is unique(/key),
20475 * then no two members of the ·qualified node set· have
20476 * ·key-sequences· whose members are pairwise equal, as
20477 * defined by Equal in [XML Schemas: Datatypes].
20478 *
20479 * Get the IDC binding from the matcher and check for
20480 * duplicate key-sequences.
20481 */
20482 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
20483 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
20484 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020485 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020486
20487 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020488 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020489 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020490 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020491 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020492 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020493 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020494 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020495 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020496 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020497 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
20498 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020499 if (res == -1) {
20500 return (-1);
20501 } else if (res == 0)
20502 break;
20503 }
20504 if (res == 1) {
20505 /*
20506 * Duplicate found.
20507 */
20508 break;
20509 }
20510 i++;
20511 } while (i < bind->nbNodes);
20512 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020513 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020514 /*
20515 * TODO: Try to report the key-sequence.
20516 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020517 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020518 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020519 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020520 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020521 "Duplicate key-sequence %s",
20522 xmlSchemaFormatIDCKeySequence(vctxt, &str,
20523 (*keySeq), nbKeys), NULL);
20524 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020525 goto selector_leave;
20526 }
20527 }
20528 /*
20529 * Add a node-table item to the IDC binding.
20530 */
20531 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
20532 sizeof(xmlSchemaPSVIIDCNode));
20533 if (ntItem == NULL) {
20534 xmlSchemaVErrMemory(NULL,
20535 "allocating an IDC node-table item", NULL);
20536 xmlFree(*keySeq);
20537 *keySeq = NULL;
20538 return(-1);
20539 }
20540 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
20541
20542 /*
20543 * Store the node-table item on global list.
20544 */
20545 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
20546 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
20547 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020548 xmlFree(*keySeq);
20549 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020550 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020551 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020552 }
20553 /*
20554 * Init the node-table item. Consume the key-sequence.
20555 */
20556 ntItem->node = vctxt->node;
20557 ntItem->keys = *keySeq;
20558 *keySeq = NULL;
20559 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
20560 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20561 /*
20562 * Free the item, since keyref items won't be
20563 * put on a global list.
20564 */
20565 xmlFree(ntItem->keys);
20566 xmlFree(ntItem);
20567 }
20568 return (-1);
20569 }
20570
20571 goto selector_leave;
20572selector_key_error:
20573 /*
20574 * 4.2.1 (KEY) The ·target node set· and the
20575 * ·qualified node set· are equal, that is, every
20576 * member of the ·target node set· is also a member
20577 * of the ·qualified node set· and vice versa.
20578 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020579 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020580 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020581 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020582 (xmlSchemaTypePtr) idc,
20583 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020584 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020585selector_leave:
20586 /*
20587 * Free the key-sequence if not added to the IDC table.
20588 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020589 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020590 xmlFree(*keySeq);
20591 *keySeq = NULL;
20592 }
20593 } /* if selector */
20594
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020595 sto->nbHistory--;
20596
20597deregister_check:
20598 /*
20599 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020600 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020601 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020602#if DEBUG_IDC
20603 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
20604 sto->sel->xpath);
20605#endif
20606 if (vctxt->xpathStates != sto) {
20607 xmlSchemaVErr(vctxt, vctxt->node,
20608 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020609 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020610 "The state object to be removed is not the first "
20611 "in the list.\n",
20612 NULL, NULL);
20613 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020614 nextsto = sto->next;
20615 /*
20616 * Unlink from the list of active XPath state objects.
20617 */
20618 vctxt->xpathStates = sto->next;
20619 sto->next = vctxt->xpathStatePool;
20620 /*
20621 * Link it to the pool of reusable state objects.
20622 */
20623 vctxt->xpathStatePool = sto;
20624 sto = nextsto;
20625 } else
20626 sto = sto->next;
20627 } /* while (sto != NULL) */
20628 return (0);
20629}
20630
20631/**
20632 * xmlSchemaIDCRegisterMatchers:
20633 * @vctxt: the WXS validation context
20634 * @elemDecl: the element declaration
20635 *
20636 * Creates helper objects to evaluate IDC selectors/fields
20637 * successively.
20638 *
20639 * Returns 0 if OK and -1 on internal errors.
20640 */
20641static int
20642xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
20643 xmlSchemaElementPtr elemDecl)
20644{
20645 xmlSchemaIDCMatcherPtr matcher, last = NULL;
20646 xmlSchemaIDCPtr idc, refIdc;
20647 xmlSchemaIDCAugPtr aidc;
20648
20649 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
20650 if (idc == NULL)
20651 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020652
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020653#if DEBUG_IDC
20654 {
20655 xmlChar *str = NULL;
20656 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020657 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020658 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20659 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020660 FREE_AND_NULL(str)
20661 }
20662#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020663 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020664 xmlSchemaVErr(vctxt, vctxt->node,
20665 XML_SCHEMAV_INTERNAL,
20666 "Internal error: xmlSchemaIDCRegisterMatchers: "
20667 "The chain of IDC matchers is expected to be empty.\n",
20668 NULL, NULL);
20669 return (-1);
20670 }
20671 do {
20672 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20673 /*
20674 * Since IDCs bubbles are expensive we need to know the
20675 * depth at which the bubbles should stop; this will be
20676 * the depth of the top-most keyref IDC. If no keyref
20677 * references a key/unique IDC, the bubbleDepth will
20678 * be -1, indicating that no bubbles are needed.
20679 */
20680 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
20681 if (refIdc != NULL) {
20682 /*
20683 * Lookup the augmented IDC.
20684 */
20685 aidc = vctxt->aidcs;
20686 while (aidc != NULL) {
20687 if (aidc->def == refIdc)
20688 break;
20689 aidc = aidc->next;
20690 }
20691 if (aidc == NULL) {
20692 xmlSchemaVErr(vctxt, vctxt->node,
20693 XML_SCHEMAV_INTERNAL,
20694 "Internal error: xmlSchemaIDCRegisterMatchers: "
20695 "Could not find an augmented IDC item for an IDC "
20696 "definition.\n",
20697 NULL, NULL);
20698 return (-1);
20699 }
20700 if ((aidc->bubbleDepth == -1) ||
20701 (vctxt->depth < aidc->bubbleDepth))
20702 aidc->bubbleDepth = vctxt->depth;
20703 }
20704 }
20705 /*
20706 * Lookup the augmented IDC item for the IDC definition.
20707 */
20708 aidc = vctxt->aidcs;
20709 while (aidc != NULL) {
20710 if (aidc->def == idc)
20711 break;
20712 aidc = aidc->next;
20713 }
20714 if (aidc == NULL) {
20715 xmlSchemaVErr(vctxt, vctxt->node,
20716 XML_SCHEMAV_INTERNAL,
20717 "Internal error: xmlSchemaIDCRegisterMatchers: "
20718 "Could not find an augmented IDC item for an IDC definition.\n",
20719 NULL, NULL);
20720 return (-1);
20721 }
20722 /*
20723 * Create an IDC matcher for every IDC definition.
20724 */
20725 matcher = (xmlSchemaIDCMatcherPtr)
20726 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20727 if (matcher == NULL) {
20728 xmlSchemaVErrMemory(vctxt,
20729 "allocating an IDC matcher", NULL);
20730 return (-1);
20731 }
20732 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20733 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020734 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020735 else
20736 last->next = matcher;
20737 last = matcher;
20738
20739 matcher->type = IDC_MATCHER;
20740 matcher->depth = vctxt->depth;
20741 matcher->aidc = aidc;
20742#if DEBUG_IDC
20743 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20744#endif
20745 /*
20746 * Init the automaton state object.
20747 */
20748 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020749 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020750 return (-1);
20751
20752 idc = idc->next;
20753 } while (idc != NULL);
20754 return (0);
20755}
20756
20757/**
20758 * xmlSchemaBubbleIDCNodeTables:
20759 * @depth: the current tree depth
20760 *
20761 * Merges IDC bindings of an element at @depth into the corresponding IDC
20762 * bindings of its parent element. If a duplicate note-table entry is found,
20763 * both, the parent node-table entry and child entry are discarded from the
20764 * node-table of the parent.
20765 *
20766 * Returns 0 if OK and -1 on internal errors.
20767 */
20768static int
20769xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20770{
20771 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020772 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20773 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020774 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20775 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020776 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020777 int duplTop;
20778
20779 /*
20780 * The node table has the following sections:
20781 *
20782 * O --> old node-table entries (first)
20783 * O
20784 * + --> new node-table entries
20785 * +
20786 * % --> new duplicate node-table entries
20787 * %
20788 * # --> old duplicate node-table entries
20789 * # (last)
20790 *
20791 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020792 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020793 if (bind == NULL) {
20794 /* Fine, no table, no bubbles. */
20795 return (0);
20796 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020797
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020798 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20799 /*
20800 * Walk all bindings; create new or add to existing bindings.
20801 * Remove duplicate key-sequences.
20802 */
20803start_binding:
20804 while (bind != NULL) {
20805 /*
20806 * Skip keyref IDCs.
20807 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020808 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20809 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020810 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020811 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020812 /*
20813 * Check if the key/unique IDC table needs to be bubbled.
20814 */
20815 aidc = vctxt->aidcs;
20816 do {
20817 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020818 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020819 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020820 bind = bind->next;
20821 goto start_binding;
20822 }
20823 break;
20824 }
20825 aidc = aidc->next;
20826 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020827
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020828 if (parTable != NULL)
20829 parBind = *parTable;
20830 while (parBind != NULL) {
20831 /*
20832 * Search a matching parent binding for the
20833 * IDC definition.
20834 */
20835 if (parBind->definition == bind->definition) {
20836
20837 /*
20838 * Compare every node-table entry of the child node,
20839 * i.e. the key-sequence within, ...
20840 */
20841 oldNum = parBind->nbNodes; /* Skip newly added items. */
20842 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020843 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020844
20845 for (i = 0; i < bind->nbNodes; i++) {
20846 node = bind->nodeTable[i];
20847 if (node == NULL)
20848 continue;
20849 /*
20850 * ...with every key-sequence of the parent node, already
20851 * evaluated to be a duplicate key-sequence.
20852 */
20853 if (parBind->nbDupls != 0) {
20854 j = bind->nbNodes + newDupls;
20855 while (j < duplTop) {
20856 parNode = parBind->nodeTable[j];
20857 for (k = 0; k < bind->definition->nbFields; k++) {
20858 key = node->keys[k];
20859 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020860 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020861 key->compValue,
20862 parKey->type, parKey->compValue);
20863 if (ret == -1) {
20864 /* TODO: Internal error */
20865 return(-1);
20866 } else if (ret == 0)
20867 break;
20868
20869 }
20870 if (ret == 1)
20871 /* Duplicate found. */
20872 break;
20873 j++;
20874 }
20875 if (j != duplTop) {
20876 /* Duplicate found. */
20877 continue;
20878 }
20879 }
20880 /*
20881 * ... and with every key-sequence of the parent node.
20882 */
20883 j = 0;
20884 while (j < oldNum) {
20885 parNode = parBind->nodeTable[j];
20886 /*
20887 * Compare key by key.
20888 */
20889 for (k = 0; k < parBind->definition->nbFields; k++) {
20890 key = node->keys[k];
20891 parKey = parNode->keys[k];
20892
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020893 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020894 key->compValue,
20895 parKey->type, parKey->compValue);
20896 if (ret == -1) {
20897 /* TODO: Internal error */
20898 } else if (ret == 0)
20899 break;
20900
20901 }
20902 if (ret == 1)
20903 /*
20904 * The key-sequences are equal.
20905 */
20906 break;
20907 j++;
20908 }
20909 if (j != oldNum) {
20910 /*
20911 * Handle duplicates.
20912 */
20913 newDupls++;
20914 oldNum--;
20915 parBind->nbNodes--;
20916 /*
20917 * Move last old item to pos of duplicate.
20918 */
20919 parBind->nodeTable[j] =
20920 parBind->nodeTable[oldNum];
20921
20922 if (parBind->nbNodes != oldNum) {
20923 /*
20924 * If new items exist, move last new item to
20925 * last of old items.
20926 */
20927 parBind->nodeTable[oldNum] =
20928 parBind->nodeTable[parBind->nbNodes];
20929 }
20930 /*
20931 * Move duplicate to last pos of new/old items.
20932 */
20933 parBind->nodeTable[parBind->nbNodes] = parNode;
20934
20935 } else {
20936 /*
20937 * Add the node-table entry (node and key-sequence) of
20938 * the child node to the node table of the parent node.
20939 */
20940 if (parBind->nodeTable == NULL) {
20941 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020942 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020943 if (parBind->nodeTable == NULL) {
20944 xmlSchemaVErrMemory(NULL,
20945 "allocating IDC list of node-table items", NULL);
20946 return(-1);
20947 }
20948 parBind->sizeNodes = 1;
20949 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020950 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020951 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20952 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20953 sizeof(xmlSchemaPSVIIDCNodePtr));
20954 if (parBind->nodeTable == NULL) {
20955 xmlSchemaVErrMemory(NULL,
20956 "re-allocating IDC list of node-table items", NULL);
20957 return(-1);
20958 }
20959 }
20960
20961 /*
20962 * Move first old duplicate to last position
20963 * of old duplicates +1.
20964 */
20965 if (parBind->nbDupls != 0) {
20966 parBind->nodeTable[duplTop] =
20967 parBind->nodeTable[parBind->nbNodes + newDupls];
20968 }
20969 /*
20970 * Move first new duplicate to last position of
20971 * new duplicates +1.
20972 */
20973 if (newDupls != 0) {
20974 parBind->nodeTable[parBind->nbNodes + newDupls] =
20975 parBind->nodeTable[parBind->nbNodes];
20976 }
20977 /*
20978 * Append the new node-table entry to the 'new node-table
20979 * entries' section.
20980 */
20981 parBind->nodeTable[parBind->nbNodes] = node;
20982 parBind->nbNodes++;
20983 duplTop++;
20984 }
20985 }
20986 parBind->nbDupls += newDupls;
20987 break;
20988 }
20989 if (parBind->next == NULL)
20990 lastParBind = parBind;
20991 parBind = parBind->next;
20992 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020993 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020994 /*
20995 * No binding for the IDC was found: create a new one and
20996 * copy all node-tables.
20997 */
20998 parBind = xmlSchemaIDCNewBinding(bind->definition);
20999 if (parBind == NULL)
21000 return(-1);
21001
21002 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21003 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
21004 if (parBind->nodeTable == NULL) {
21005 xmlSchemaVErrMemory(NULL,
21006 "allocating an array of IDC node-table items", NULL);
21007 xmlSchemaIDCFreeBinding(parBind);
21008 return(-1);
21009 }
21010 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021011 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021012 memcpy(parBind->nodeTable, bind->nodeTable,
21013 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021014 if (*parTable == NULL)
21015 *parTable = parBind;
21016 else
21017 lastParBind->next = parBind;
21018 }
21019 bind = bind->next;
21020 }
21021 return (0);
21022}
21023
21024/**
21025 * xmlSchemaCheckCVCIDCKeyRef:
21026 * @vctxt: the WXS validation context
21027 * @elemDecl: the element declaration
21028 *
21029 * Check the cvc-idc-keyref constraints.
21030 */
21031static int
21032xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
21033{
21034 xmlSchemaPSVIIDCBindingPtr refbind, bind;
21035
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021036 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021037 /*
21038 * Find a keyref.
21039 */
21040 while (refbind != NULL) {
21041 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
21042 int i, j, k, res;
21043 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
21044 xmlSchemaPSVIIDCKeyPtr refKey, key;
21045
21046 /*
21047 * Find the referred key/unique.
21048 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021049 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021050 do {
21051 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
21052 bind->definition)
21053 break;
21054 bind = bind->next;
21055 } while (bind != NULL);
21056
21057 /*
21058 * Search for a matching key-sequences.
21059 */
21060 for (i = 0; i < refbind->nbNodes; i++) {
21061 res = 0;
21062 if (bind != NULL) {
21063 refKeys = refbind->nodeTable[i]->keys;
21064 for (j = 0; j < bind->nbNodes; j++) {
21065 keys = bind->nodeTable[j]->keys;
21066 for (k = 0; k < bind->definition->nbFields; k++) {
21067 refKey = refKeys[k];
21068 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021069 res = xmlSchemaAreValuesEqual(vctxt,
21070 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021071 refKey->type, refKey->compValue);
21072 if (res == 0)
21073 break;
21074 else if (res == -1) {
21075 return (-1);
21076 }
21077 }
21078 if (res == 1) {
21079 /*
21080 * Match found.
21081 */
21082 break;
21083 }
21084 }
21085 }
21086 if (res == 0) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000021087 xmlChar *str = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021088 /* TODO: Report the key-sequence. */
21089 xmlSchemaVCustomErr(vctxt,
21090 XML_SCHEMAV_CVC_IDC,
21091 refbind->nodeTable[i]->node,
21092 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000021093 "No match found for key reference %s",
21094 xmlSchemaFormatIDCKeySequence(vctxt, &str,
21095 refbind->nodeTable[i]->keys,
21096 refbind->definition->nbFields));
21097 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021098 }
21099 }
21100 }
21101 refbind = refbind->next;
21102 }
21103 return (0);
21104}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021105
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021106/**
21107 * xmlSchemaBeginElement:
21108 * @vctxt: the WXS validation context
21109 *
21110 * Just a temporary workaround to simulate streaming validation
21111 * a bit.
21112 */
21113static void
21114xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
21115{
21116 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021117 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
21118 vctxt->nodeInfo->node = vctxt->node;
21119 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021120 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021121 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021122 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021123 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021124}
21125
21126/**
21127 * xmlSchemaEndElement:
21128 * @vctxt: the WXS validation context
21129 *
21130 * Just a temporary workaround to simulate streaming validation
21131 * a bit.
21132 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021133static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021134xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
21135{
21136 if (vctxt->depth < 0) {
21137 /* TODO: raise error? */
21138 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021139 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021140 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021141 /*
21142 * Evaluate the history of changes of active state objects.
21143 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021144 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
21145 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021146
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021147 if (vctxt->nodeInfo->value != NULL) {
21148 xmlSchemaFreeValue(vctxt->nodeInfo->value);
21149 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021150 }
21151 /*
21152 * TODO: 6 The element information item must be ·valid· with respect to each of
21153 * the {identity-constraint definitions} as per Identity-constraint
21154 * Satisfied (§3.11.4).
21155 */
21156 /*
21157 * Validate IDC keyrefs.
21158 */
21159 xmlSchemaCheckCVCIDCKeyRef(vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021160
21161 /*
21162 * Merge/free the IDC table.
21163 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021164 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021165#ifdef DEBUG_IDC
21166 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021167 vctxt->nodeInfo->namespaceName,
21168 vctxt->nodeInfo->localName,
21169 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021170#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021171 if (vctxt->depth > 0) {
21172 /*
21173 * Merge the IDC node table with the table of the parent node.
21174 */
21175 xmlSchemaBubbleIDCNodeTables(vctxt);
21176 }
21177 /*
21178 * TODO: Don't free the PSVI IDC tables if they are
21179 * requested for the PSVI.
21180 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021181 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021182 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021183 }
21184
21185 /*
21186 * Cleanup IDC matchers.
21187 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021188 if (vctxt->nodeInfo->idcMatchers != NULL) {
21189 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
21190 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021191 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021192
21193 /*
21194 * Skip further processing if we are on the validation root.
21195 */
21196 if (vctxt->depth == 0) {
21197 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021198 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021199 }
21200
21201 /*
21202 * Reset the bubbleDepth if needed.
21203 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021204 if (vctxt->aidcs != NULL) {
21205 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
21206 do {
21207 if (aidc->bubbleDepth == vctxt->depth) {
21208 /*
21209 * A bubbleDepth of a key/unique IDC matches the current
21210 * depth, this means that we are leaving the scope of the
21211 * top-most keyref IDC.
21212 */
21213 aidc->bubbleDepth = -1;
21214 }
21215 aidc = aidc->next;
21216 } while (aidc != NULL);
21217 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021218 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021219 /*
21220 * Clear the current elemInfo.
21221 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021222 if (vctxt->nodeInfo->value != NULL) {
21223 xmlSchemaFreeValue(vctxt->nodeInfo->value);
21224 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021225 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021226 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
21227 vctxt->node = vctxt->nodeInfo->node;
21228
21229 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021230}
21231
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021232/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021233 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000021234 * @ctxt: a schema validation context
21235 * @node: the top node.
21236 *
21237 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021238 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000021239 *
21240 * Returns 0 if the element is schemas valid, a positive error code
21241 * number otherwise and -1 in case of internal or API error.
21242 */
21243static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021244xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
21245 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021246{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021247 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021248 int ret = 0;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021249 xmlSchemaTypePtr actualType = NULL, localType = NULL, type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021250 xmlAttrPtr attr;
21251 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021252 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000021253
21254 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021255 * This one is called by xmlSchemaValidateElementByWildcardInternal,
21256 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021257 * Note that @elemDecl will be the declaration and never the
21258 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021259 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021260
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021261 if (ctxt == NULL) {
21262 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
21263 "Internal error: xmlSchemaValidateElementByDeclaration, "
21264 "bad arguments.\n",
21265 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021266 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021267 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021268
21269 elem = ctxt->node;
21270
21271 /*
21272 * cvc-elt (3.3.4) : 1
21273 */
21274 if (elemDecl == NULL) {
21275 xmlSchemaVCustomErr(ctxt,
21276 XML_SCHEMAV_CVC_ELT_1,
21277 elem, NULL,
21278 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021279 /*
21280 * Evaluate IDCs even if an error occured.
21281 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021282 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021283 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021284 return (ctxt->err);
21285 }
21286 /*
21287 * cvc-elt (3.3.4) : 2
21288 */
21289 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21290 xmlSchemaVCustomErr(ctxt,
21291 XML_SCHEMAV_CVC_ELT_2,
21292 elem, NULL,
21293 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021294 /*
21295 * Evaluate IDCs even if an error occured.
21296 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021297 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021298 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021299 return (ctxt->err);
21300 }
21301
21302 /*
21303 * cvc-elt (3.3.4) : 3
21304 * Handle 'xsi:nil'.
21305 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021306
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021307 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021308 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021309 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
21310 ctxt->node = (xmlNodePtr) attr;
21311 ctxt->cur = attr->children;
21312 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
21313 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21314 BAD_CAST attrValue, 1, 1, 1, 1);
21315 ctxt->node = elem;
21316 ctxt->type = (xmlSchemaTypePtr) elemDecl;
21317 if (ret < 0) {
21318 xmlSchemaVCustomErr(ctxt,
21319 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021320 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021321 "Internal error: xmlSchemaValidateElementByDeclaration, "
21322 "validating the attribute 'xsi:nil'", NULL);
21323 if (attrValue != NULL)
21324 xmlFree(attrValue);
21325 return (-1);
21326 }
21327 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021328 /*
21329 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021330 */
21331 xmlSchemaVCustomErr(ctxt,
21332 XML_SCHEMAV_CVC_ELT_3_1,
21333 elem, NULL,
21334 "The element is not 'nillable'", NULL);
21335 } else {
21336 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021337 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021338 ret = 0;
21339 /*
21340 * cvc-elt (3.3.4) : 3.2.1
21341 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021342 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
21343 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021344 xmlSchemaVCustomErr(ctxt,
21345 XML_SCHEMAV_CVC_ELT_3_2_1,
21346 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021347 elem, (xmlSchemaTypePtr) elemDecl,
21348 "The 'nilled' element must have no character or "
21349 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021350 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
21351 }
21352 /*
21353 * cvc-elt (3.3.4) : 3.2.2
21354 */
21355 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21356 (elemDecl->value != NULL)) {
21357 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
21358 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021359 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021360 "There is a fixed value constraint defined for "
21361 "the 'nilled' element", NULL);
21362 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
21363 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021364 if (ret == 0)
21365 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021366 }
21367 }
21368 if (attrValue != NULL)
21369 xmlFree(attrValue);
21370 }
21371
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021372 type = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021373 actualType = type;
21374
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021375 /*
21376 * cvc-elt (3.3.4) : 4
21377 * Handle 'xsi:type'.
21378 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021379
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021380 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
21381 if (attr != NULL) {
21382 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021383
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021384 /*
21385 * TODO: We should report a *warning* that the type was overriden
21386 * by the instance.
21387 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021388
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021389 /*
21390 * cvc-elt (3.3.4) : 4.1
21391 */
21392 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
21393 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
21394 &nsName, &local);
21395 if (ret < 0) {
21396 xmlSchemaVCustomErr(ctxt,
21397 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021398 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021399 "Internal error: xmlSchemaValidateElementByDeclaration, "
21400 "validating the attribute 'xsi:type'", NULL);;
21401 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021402 FREE_AND_NULL(nsName)
21403 FREE_AND_NULL(local)
21404 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021405 } else if (ret == 1) {
21406 xmlSchemaVSimpleTypeErr(ctxt,
21407 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
21408 (xmlNodePtr) attr, attrValue,
21409 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
21410 } else if (ret == 2) {
21411 xmlSchemaVCustomErr(ctxt,
21412 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
21413 (xmlNodePtr) attr,
21414 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21415 "The QName value '%s' has no "
21416 "corresponding namespace declaration in scope",
21417 attrValue);
21418 } else {
21419 /*
21420 * cvc-elt (3.3.4) : 4.2
21421 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021422 localType = xmlSchemaGetType(ctxt->schema, local, nsName);
21423 if (localType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021424 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021425
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021426 xmlSchemaVCustomErr(ctxt,
21427 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021428 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021429 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021430 "The value '%s' of the xsi:type attribute does not "
21431 "resolve to a type definition",
21432 xmlSchemaFormatQName(&strA, nsName, local));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021433 FREE_AND_NULL(strA);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021434 } else {
21435 int set = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021436 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021437 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21438 * "The ·local type definition· must be validly
21439 * derived from the {type definition} given the union of
21440 * the {disallowed substitutions} and the {type definition}'s
21441 * {prohibited substitutions}, as defined in
21442 * Type Derivation OK (Complex) (§3.4.6)
21443 * (if it is a complex type definition),
21444 * or given {disallowed substitutions} as defined in Type
21445 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21446 * definition)."
21447 *
21448 * {disallowed substitutions}: the "block" on the element decl.
21449 * {prohibited substitutions}: the "block" on the type def.
21450 */
21451 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21452 (type->flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21453 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
21454
21455 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21456 (type->flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21457 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
21458
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021459 if (xmlSchemaCheckCOSDerivedOK(ctxt->schema, localType,
21460 type, set) != 0) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021461 xmlChar *strA = NULL, *strB = NULL;
21462
21463 xmlSchemaVCustomErrExt(ctxt,
21464 /* TODO: Error code */
21465 XML_SCHEMAV_CVC_ELT_4_2, elem, localType,
21466 "The xsi:type definition '%s' is not validly derived from "
21467 "the type definition '%s'",
21468 xmlSchemaFormatQName(&strA,
21469 localType->targetNamespace,
21470 localType->name),
21471 xmlSchemaFormatQName(&strB,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021472 ELEM_TYPE(elemDecl)->targetNamespace,
21473 ELEM_TYPE(elemDecl)->name), NULL);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021474 FREE_AND_NULL(strA)
21475 FREE_AND_NULL(strB)
21476 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021477 }
21478 }
21479 FREE_AND_NULL(attrValue)
21480 FREE_AND_NULL(nsName)
21481 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021482 }
21483 /* TODO: Change the handling of missing types according to
21484 * the spec.
21485 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021486 if (localType != NULL)
21487 actualType = localType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021488 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021489 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021490 XML_SCHEMAV_CVC_TYPE_1,
21491 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021492 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021493 /*
21494 * Evaluate IDCs even if an error occured.
21495 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021496 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021497 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021498 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021499 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021500
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021501 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021502 * Remember the actual-type definition.
21503 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021504 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021505
21506 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021507 * TODO: Since this should be already checked by the content model automaton,
21508 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
21509 * has been changed to XML_SCHEMAV_INTERNAL.
21510 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021511 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000021512 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021513 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021514 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021515 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021516 "Element %s: missing child %s\n",
21517 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021518 }
21519 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021520 }
21521 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021522 /*
21523 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021524 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021525 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000021526 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021527 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021528 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021529 "Element %s: missing child %s found %s\n",
21530 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021531 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021532 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021533 */
21534 if (elemHasContent == -1)
21535 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021536
21537 /*
21538 * IDC: Register identity-constraint XPath matchers.
21539 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021540 if (elemDecl->idcs != NULL)
21541 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
21542 /*
21543 * Evaluate IDCs.
21544 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021545 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021546 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021547 /*
21548 * cvc-elt (3.3.4) : 5
21549 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021550 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021551 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021552 * cvc-elt (3.3.4) : 5.1
21553 * If the declaration has a {value constraint},
21554 * the item has neither element nor character [children] and
21555 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021556 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021557 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
21558 /*
21559 * cvc-elt (3.3.4) : 5.1.1
21560 * If the ·actual type definition· is a ·local type definition·
21561 * then the canonical lexical representation of the {value constraint}
21562 * value must be a valid default for the ·actual type definition· as
21563 * defined in Element Default Valid (Immediate) (§3.3.6).
21564 */
21565 /*
21566 * NOTE: 'local' above means types aquired by xsi:type.
21567 */
21568 ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021569 if (actualType != ELEM_TYPE(elemDecl)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021570 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
21571 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021572 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021573 if (ret < 0) {
21574 xmlSchemaVCustomErr(ctxt,
21575 XML_SCHEMAV_INTERNAL,
21576 elem, actualType,
21577 "Internal error: xmlSchemaValidateElementByDeclaration, "
21578 "validating a default value", NULL);
21579 return (-1);
21580 }
21581 }
21582 /*
21583 * cvc-elt (3.3.4) : 5.1.2
21584 * The element information item with the canonical lexical
21585 * representation of the {value constraint} value used as its
21586 * ·normalized value· must be ·valid· with respect to the
21587 * ·actual type definition· as defined by Element Locally Valid (Type)
21588 * (§3.3.4).
21589 */
21590 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021591 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021592 * done above.
21593 */
21594 if (ret == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021595 if (actualType != ELEM_TYPE(elemDecl))
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021596 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021597 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021598 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021599 ctxt->node = elem;
21600 if (ret < 0) {
21601 xmlSchemaVCustomErr(ctxt,
21602 XML_SCHEMAV_INTERNAL,
21603 elem, actualType,
21604 "Internal error: xmlSchemaValidateElementByDeclaration, "
21605 "validating against the type", NULL);
21606 return (-1);
21607 }
21608 /*
21609 * PSVI: Create a text node on the instance element.
21610 */
21611 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
21612 xmlNodePtr textChild;
21613
21614 textChild = xmlNewText(elemDecl->value);
21615 if (textChild == NULL) {
21616 xmlSchemaVCustomErr(ctxt,
21617 XML_SCHEMAV_INTERNAL,
21618 elem, actualType,
21619 "Internal error: xmlSchemaValidateElementByDeclaration, "
21620 "could not create a default text node for the instance",
21621 NULL);
21622 } else
21623 xmlAddChild(elem, textChild);
21624 }
21625 }
21626
21627 } else {
21628 /*
21629 * 5.2.1 The element information item must be ·valid· with respect
21630 * to the ·actual type definition· as defined by Element Locally
21631 * Valid (Type) (§3.3.4).
21632 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021633 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
21634 /*
21635 * Consume the computed value for IDCs, ect. Note that default
21636 * values are not supported yet.
21637 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021638 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021639 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021640 ctxt->value = NULL;
21641 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021642 ctxt->node = elem;
21643 if (ret < 0) {
21644 xmlSchemaVCustomErr(ctxt,
21645 XML_SCHEMAV_INTERNAL,
21646 elem, actualType,
21647 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021648 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021649 return (-1);
21650 }
21651 /*
21652 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
21653 * not applied, all of the following must be true:
21654 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021655 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
21656 /*
21657 * 5.2.2.1 The element information item must have no element
21658 * information item [children].
21659 *
21660 * TODO REDUNDANT: If the actual type exists, the above call to
21661 * xmlSchemaValidateElementByType will already check for element
21662 * nodes.
21663 */
21664 if (xmlSchemaHasElemContent(elem)) {
21665 xmlSchemaVCustomErr(ctxt,
21666 XML_SCHEMAV_CVC_ELT_5_2_2_1,
21667 elem, (xmlSchemaTypePtr) elemDecl,
21668 "Elements in the content are not allowed if it is "
21669 "constrained by a fixed value", NULL);
21670 } else {
21671 /*
21672 * 5.2.2.2 The appropriate case among the following must
21673 * be true:
21674 */
21675
21676 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
21677 xmlChar *value;
21678 /*
21679 * 5.2.2.2.1 If the {content type} of the ·actual type
21680 * definition· is mixed, then the *initial value* of the
21681 * item must match the canonical lexical representation
21682 * of the {value constraint} value.
21683 *
21684 * ... the *initial value* of an element information
21685 * item is the string composed of, in order, the
21686 * [character code] of each character information item in
21687 * the [children] of that element information item.
21688 */
21689 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21690 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21691 /*
21692 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021693 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021694 */
21695 xmlSchemaVCustomErr(ctxt,
21696 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
21697 elem, (xmlSchemaTypePtr) elemDecl,
21698 "The value does not match the cononical "
21699 "lexical representation of the fixed constraint",
21700 NULL);
21701 }
21702 if (value != NULL)
21703 xmlFree(value);
21704 } else if ((actualType->contentType ==
21705 XML_SCHEMA_CONTENT_SIMPLE) ||
21706 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
21707 xmlChar *value;
21708
21709 /*
21710 * 5.2.2.2.2 If the {content type} of the ·actual type
21711 * definition· is a simple type definition, then the
21712 * *actual value* of the item must match the canonical
21713 * lexical representation of the {value constraint} value.
21714 */
21715 /*
21716 * TODO: *actual value* is the normalized value, impl. this.
21717 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021718 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021719 *
21720 */
21721 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21722 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21723 xmlSchemaVCustomErr(ctxt,
21724 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
21725 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021726 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021727 "lexical representation of the fixed constraint",
21728 NULL);
21729 }
21730 if (value != NULL)
21731 xmlFree(value);
21732
21733 }
21734 /*
21735 * TODO: What if the content type is not 'mixed' or simple?
21736 */
21737
21738 }
21739
21740 }
21741 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021742 /*
21743 * TODO: 7 If the element information item is the ·validation root·, it must be
21744 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
21745 */
21746
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021747 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021748}
21749
Daniel Veillard4255d502002-04-16 15:50:10 +000021750/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021751 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021752 * @ctxt: a schema validation context
21753 * @node: the top node.
21754 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021755 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
21756 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021757 *
21758 * Returns 0 if the element is valid, a positive error code
21759 * number otherwise and -1 in case of an internal error.
21760 */
21761static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021762xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
21763 xmlSchemaWildcardPtr wild,
21764 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021765{
21766 const xmlChar *uri;
21767 int ret = 0;
21768 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021769
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021770 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021771 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
21772 if (ret == -1) {
21773 xmlSchemaVCustomErr(ctxt,
21774 XML_SCHEMAV_INTERNAL,
21775 ctxt->node, NULL,
21776 "Internal error: xmlSchemaValidateElement, "
21777 "assembling schema by xsi", NULL);
21778 return (-1);
21779 }
21780 /*
21781 * NOTE: We won't react on schema parser errors here.
21782 * TODO: But a warning would be nice.
21783 */
21784 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021785 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
21786 xmlSchemaElementPtr decl = NULL;
21787
21788 if (node->ns != NULL)
21789 decl = xmlHashLookup3(ctxt->schema->elemDecl,
21790 node->name, node->ns->href, NULL);
21791 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021792 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
21793 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021794 if (decl != NULL) {
21795 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021796 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021797 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021798 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021799 "Internal error: xmlSchemaValidateAnyInternal, "
21800 "validating an element in the context of a wildcard.",
21801 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000021802 }
21803 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021804 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21805 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021806 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021807 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021808 /*
21809 * Evaluate IDCs even if a validation error occured.
21810 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021811 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021812 return(-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021813
Daniel Veillardc0826a72004-08-10 14:17:33 +000021814 return (ctxt->err);
21815 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021816 /*
21817 * Evaluate IDCs; we need to know if an IDC field resolves to
21818 * such a node. This node has no type definition and will
21819 * definitely result in an IDC validation error if an IDC field
21820 * resolves.
21821 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021822 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021823 return(-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021824 }
21825 if (node->children != NULL) {
21826 child = node->children;
21827 do {
21828 if (child->type == XML_ELEMENT_NODE) {
21829 if (child->ns != NULL)
21830 uri = child->ns->href;
21831 else
21832 uri = NULL;
21833 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021834 /* TODO: error code. */
21835 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021836 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021837 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000021838 return (ctxt->err);
21839 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021840
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021841 ctxt->node = child;
21842 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021843
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021844 /*
21845 * Recurse over the children.
21846 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021847 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
21848 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021849 if (ret == -1)
21850 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021851
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021852 if (xmlSchemaEndElement(ctxt) == -1)
21853 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021854
Daniel Veillardc0826a72004-08-10 14:17:33 +000021855 if (ret != 0)
21856 return (ret);
21857 }
21858 child = child->next;
21859 } while (child != NULL);
21860 }
21861 return (0);
21862}
21863
21864/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021865 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021866 * @ctxt: a schema validation context
21867 *
21868 * Returns 0 if the element is valid, a positive error code
21869 * number otherwise and -1 in case of an internal or API error.
21870 */
21871static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021872xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021873 xmlSchemaWildcardPtr wild)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021874{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021875
21876 if ((wild == NULL) || (wild->type != XML_SCHEMA_TYPE_ANY) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021877 (ctxt->node == NULL)) {
21878 xmlSchemaVCustomErr(ctxt,
21879 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
21880 "Internal error: xmlSchemaValidateElementByWildcard, "
21881 "bad arguments", NULL);
21882 return (-1);
21883 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000021884#if 0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021885 if (wild->negNsSet != NULL) {
21886 /*
21887 * Workaround for negated namespaces.
21888 */
21889 if (ctxt->node->ns != NULL) {
21890 if (xmlSchemaMatchesWildcardNs(wild, ctxt->node->ns->href) == 0) {
21891 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21892 return (XML_SCHEMAV_ELEMENT_CONTENT);
21893 }
21894 } else if (xmlSchemaMatchesWildcardNs(wild, NULL) == 0) {
21895 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21896 return (XML_SCHEMAV_ELEMENT_CONTENT);
21897 }
21898 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000021899#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021900 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021901 wild, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000021902}
21903
21904/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021905 * xmlSchemaValidateElementByAnyType:
William M. Brack2f2a6632004-08-20 23:09:47 +000021906 * @ctxt: a schema validation context
21907 * @node: the current element
21908 *
21909 * This one validates the content of an element of the type
21910 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
21911 * thus elements in the subtree will be validated, if a corresponding
21912 * declaration in the schema exists.
21913 *
21914 * Returns 0 if the element and its subtree is valid, a positive error code
21915 * otherwise and -1 in case of an internal or API error.
21916 */
21917static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021918xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
21919 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000021920{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021921 xmlSchemaTypePtr oldtype;
21922 xmlNodePtr top, cur;
21923 xmlSchemaElementPtr decl;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021924 int skipContent, ret, insub = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021925
21926 if ((type == NULL) || (ctxt->node == NULL))
21927 return (-1);
21928
21929 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021930 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021931
21932 oldtype = ctxt->type;
21933 top = ctxt->node;
21934 /*
21935 * STREAM: Child nodes are processed.
21936 */
21937 cur = ctxt->node->children;
21938 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021939 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021940 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021941 /*
21942 * The process contents of the wildcard is "lax", thus
21943 * we need to validate the element if a declaration
21944 * exists.
21945 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021946 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021947 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021948 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000021949 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021950 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
21951 ctxt->node = cur;
21952
21953 if (insub) {
21954 /*
21955 * BEGIN element.
21956 */
21957 xmlSchemaBeginElement(ctxt);
21958 } else
21959 insub = 1;
21960
21961 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021962 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
21963 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000021964 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021965 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000021966 "Internal error: xmlSchemaValidateAnyTypeContent, "
21967 "validating an element in the context of a wildcard.",
21968 NULL, NULL);
21969 return (ret);
21970 } else if (ret > 0)
21971 return (ret);
21972 skipContent = 1;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021973 } else {
21974 /*
21975 * IDCs.
21976 */
21977 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
21978 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000021979 }
21980 }
21981 /*
21982 * Browse the full subtree, deep first.
21983 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021984 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021985 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021986 cur = cur->children;
21987 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021988 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021989 cur = cur->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021990 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021991 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021992 while (cur != top) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021993 if (cur->type == XML_ELEMENT_NODE) {
21994 /*
21995 * END element.
21996 */
21997 xmlSchemaEndElement(ctxt);
21998 }
21999 if (cur->parent != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022000 cur = cur->parent;
22001 if ((cur != top) && (cur->next != NULL)) {
22002 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000022003 break;
22004 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022005 if (cur->parent == NULL) {
22006 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000022007 break;
22008 }
22009 }
22010 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022011 if (cur == top)
22012 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000022013 } else
22014 break;
22015 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022016 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000022017 return (0);
22018}
22019
22020/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022021 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000022022 * @ctxt: a schema validation context
22023 * @node: the top node.
22024 *
22025 * Validate the content of an element expected to be a complex type type
22026 * xmlschema-1.html#cvc-complex-type
22027 * Validation Rule: Element Locally Valid (Complex Type)
22028 *
22029 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000022030 * number otherwise and -1 in case of internal or API error.
22031 * Note on reported errors: Although it might be nice to report
22032 * the name of the simple/complex type, used to validate the content
22033 * of a node, it is quite unnecessary: for global defined types
22034 * the local name of the element is equal to the NCName of the type,
22035 * for local defined types it makes no sense to output the internal
22036 * computed name of the type. TODO: Instead, one should attach the
22037 * struct of the type involved to the error handler - this allows
22038 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000022039 */
22040static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022041xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022042 xmlSchemaTypePtr type,
22043 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022044{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022045 xmlSchemaTypePtr oldtype;
22046 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022047 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000022048 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022049 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000022050
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022051 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
22052 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022054 oldtype = ctxt->type;
22055 ctxt->type = type;
22056 elem = ctxt->node;
22057
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022058 /*
22059 * Verify the attributes
22060 */
22061 /*
22062 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022063 */
22064 /* NOTE: removed, since a check for abstract is
22065 * done in the cvc-type constraint.
22066 *
22067 *
22068 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22069 * xmlSchemaVComplexTypeErr(ctxt,
22070 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
22071 * elem, type,
22072 * "The type definition is abstract");
22073 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
22074 *}
22075 */
22076
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022077 attrs = ctxt->attr;
22078 attrTop = ctxt->attrTop;
22079 /*
22080 * STREAM: Attribute nodes are processed.
22081 */
22082 xmlSchemaRegisterAttributes(ctxt, elem->properties);
22083 xmlSchemaValidateAttributes(ctxt, elem, type);
22084 if (ctxt->attr != NULL)
22085 xmlSchemaFreeAttributeStates(ctxt->attr);
22086 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022087 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022088
22089 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022090 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022091 * model was defined. Somehow ->contModel is always not NULL
22092 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022093 * TODO: Check if the obove still occurs.
22094 */
Daniel Veillard4255d502002-04-16 15:50:10 +000022095 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000022096 case XML_SCHEMA_CONTENT_EMPTY: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022097 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022098 * 1 If the {content type} is empty, then the element information
22099 * item has no character or element information item [children].
22100 */
22101 /*
22102 * TODO: Is the entity stuff correct?
22103 */
22104 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
22105 xmlSchemaVComplexTypeErr(ctxt,
22106 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
22107 elem, type,
22108 "Character or element content is not allowed, "
22109 "because the content type is empty");
22110 }
22111 break;
22112 }
22113 case XML_SCHEMA_CONTENT_MIXED:
22114 /*
22115 * Some speedups for anyType or types derived directly from it.
22116 */
22117 if (IS_ANYTYPE(type)) {
22118 /*
22119 * Corresponds to <element name="foo" [type="xsd:anyType"]/>.
22120 */
22121 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
22122 /* TODO: Handle -1. */
22123 break;
22124 }
22125 if (IS_ANYTYPE(type->baseType) &&
22126 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
22127 (type->subtypes == type->baseType->subtypes)) {
22128 /*
22129 * Corresponds to an <extension> of anyType.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022130 */
22131 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
22132 /* TODO: Handle -1. */
22133 break;
22134 }
22135 /* No break on purpose. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022136 case XML_SCHEMA_CONTENT_ELEMENTS: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022137 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022138 xmlChar *values[10];
22139 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022140 /*
22141 * SPEC (2.4) If the {content type} is element-only or mixed,
22142 * then the sequence of the element information item's
22143 * element information item [children], if any, taken in
22144 * order, is ·valid· with respect to the {content type}'s
22145 * particle, as defined in Element Sequence Locally Valid
22146 * (Particle) (§3.9.4).
22147 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022148 /*
22149 * Content model check initialization.
22150 */
22151 if (type->contModel != NULL) {
22152 oldregexp = ctxt->regexp;
22153 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
22154 (xmlRegExecCallbacks)
22155 xmlSchemaValidateCallback, ctxt);
22156#ifdef DEBUG_AUTOMATA
22157 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
22158#endif
22159 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022160 /*
22161 * STREAM: Children are processed.
22162 */
22163 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022164 while (child != NULL) {
22165 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000022166 if (child->ns != NULL)
22167 nsUri = child->ns->href;
22168 else
22169 nsUri = NULL;
22170 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022171 child->name, nsUri, child);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022172 if (ctxt->err == XML_SCHEMAV_INTERNAL) {
22173 xmlRegFreeExecCtxt(ctxt->regexp);
22174 ctxt->regexp = oldregexp;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022175 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022176 }
22177#if 0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022178 if (ctxt->flags & XML_SCHEMA_VALID_INVALID_NEG_WILDCARD) {
22179 ctxt->flags ^= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
22180 ret = -1;
22181 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022182#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022183 /*
22184 * URGENT TODO: Could we anchor an error report
22185 * here to notify of invalid elements?
22186 * TODO: Perhaps it would be better to report
22187 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022188 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022189#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000022190 if (ret < 0)
22191 xmlGenericError(xmlGenericErrorContext,
22192 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000022193 else
22194 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000022195 " --> %s\n", child->name);
22196#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022197 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022198 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
22199 &values[0], &terminal);
22200 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022201 XML_SCHEMAV_ELEMENT_CONTENT,
22202 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022203 "This element is not expected",
22204 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022205 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022206 /*
22207 * Note that this will skip further validation of the
22208 * content.
22209 */
22210 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022211 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000022212 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
22213 /*
22214 * TODO: Ask Daniel if this are all character nodes.
22215 */
22216 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
22217 (child->type == XML_ENTITY_NODE) ||
22218 (child->type == XML_ENTITY_REF_NODE) ||
22219 (child->type == XML_CDATA_SECTION_NODE))) {
22220 /*
22221 * 2.3 If the {content type} is element-only, then the
22222 * element information item has no character information
22223 * item [children] other than those whose [character
22224 * code] is defined as a white space in [XML 1.0 (Second
22225 * Edition)].
22226 */
William M. Brack2f2a6632004-08-20 23:09:47 +000022227 xmlSchemaVComplexTypeErr(ctxt,
22228 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022229 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000022230 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022231 "because the content type is element-only");
22232 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022233 break;
22234 }
22235 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022236 }
22237 /*
22238 * Content model check finalization.
22239 */
22240 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022241 if (ret == 0) {
22242 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022243 &values[0], &terminal);
Daniel Veillard0e460da2005-03-30 22:47:10 +000022244 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022245 * If a next value still exists, It does not have to
Daniel Veillard0e460da2005-03-30 22:47:10 +000022246 * mean that there's an element missing, since it
22247 * might be an optional element. So double check it.
22248 */
22249 ret = xmlRegExecPushString(ctxt->regexp,
22250 NULL, NULL);
22251 if (ret <= 0) {
22252 ret = 1;
22253 xmlSchemaVComplexTypeElemErr(ctxt,
22254 XML_SCHEMAV_ELEMENT_CONTENT,
22255 elem, type, "Missing child element(s)",
22256 nbval, nbneg, values);
22257 } else
22258 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022259#ifdef DEBUG_AUTOMATA
Daniel Veillard0e460da2005-03-30 22:47:10 +000022260 xmlGenericError(xmlGenericErrorContext,
22261 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022262#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022263#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022264 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022265 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022266 "Element %s content check succeeded\n",
22267 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022268#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022269 }
22270 xmlRegFreeExecCtxt(ctxt->regexp);
22271 ctxt->regexp = oldregexp;
22272 }
22273 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000022274 break;
22275 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022276 case XML_SCHEMA_CONTENT_BASIC:
22277 /*
22278 * If the simple content was already validated
22279 * (e.g. a default value), the content need not
22280 * to be validated again.
22281 */
22282 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000022283 xmlChar *value = NULL;
22284 /*
22285 * We hit a complexType with a simpleContent resolving
22286 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000022287 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000022288 /*
22289 * 2.2 If the {content type} is a simple type definition,
22290 * then the element information item has no element
22291 * information item [children], and the ·normalized value·
22292 * of the element information item is ·valid· with respect
22293 * to that simple type definition as defined by String
22294 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022295 */
22296 /*
22297 * STREAM: Children are processed.
22298 */
22299 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022300 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022301 /*
22302 * TODO: Could the entity stuff produce elements
22303 * as well?
22304 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000022305 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000022306 xmlSchemaVComplexTypeErr(ctxt,
22307 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022308 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000022309 "Element content is not allowed, because "
22310 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000022311 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22312 break;
22313 }
22314 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022315 }
22316 ctxt->node = elem;
22317 ctxt->cur = elem->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022318 if (ret != 0) {
22319 FREE_AND_NULL(value)
22320 break;
22321 }
22322 /*
22323 * Validate the character content against a simple type.
22324 */
22325 if (elem->children == NULL)
22326 value = NULL;
22327 else
22328 value = xmlNodeGetContent(elem);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022329 /*
22330 * NOTE: This call won't check the correct types of the
22331 * content nodes, since this should be done here.
22332 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022333 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
22334 type->contentTypeDef, value, 1, 1, 1, 0);
22335 if (ret > 0) {
22336 /*
22337 * NOTE: Although an error will be reported by
22338 * xmlSchemaValidateSimpleTypeValue, the spec wants
22339 * a specific complex type error to be reported
22340 * additionally.
22341 */
22342 xmlSchemaVComplexTypeErr(ctxt,
22343 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
22344 elem, type,
22345 "The character content is not valid");
22346 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22347 } else if (ret < 0) {
22348 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
22349 "Internal error: xmlSchemaValidateComplexType, "
22350 "Element '%s': Error while validating character "
22351 "content against complex type '%s'.\n",
22352 elem->name, type->name);
22353 if (value != NULL)
22354 xmlFree(value);
22355 ctxt->type = oldtype;
22356 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022357 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000022358 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022359 xmlFree(value);
22360
Daniel Veillard01fa6152004-06-29 17:04:39 +000022361 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022362 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022363 default:
22364 TODO xmlGenericError(xmlGenericErrorContext,
22365 "unimplemented content type %d\n",
22366 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000022367 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022368 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022369 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000022370}
22371
22372/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022373 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000022374 * @ctxt: a schema validation context
22375 * @elem: an element
22376 * @type: the list of type declarations
22377 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022378 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000022379 *
22380 * Returns 0 if the element is schemas valid, a positive error code
22381 * number otherwise and -1 in case of internal or API error.
22382 */
22383static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022384xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022385 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022386 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022387 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022388{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022389 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000022390
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022391
22392 if ((ctxt == NULL) || (type == NULL)) {
22393 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
22394 "Internal error: xmlSchemaValidateElementByType, "
22395 "bad arguments", NULL);
22396 return (-1);
22397 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022398 /*
22399 * This one is called by "xmlSchemaValidateElementByDeclaration".
22400 * It will forward to the proper validation
22401 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022402 */
22403 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022404 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022405 XML_SCHEMAV_CVC_TYPE_1,
22406 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022407 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022408 return (XML_SCHEMAV_CVC_TYPE_1);
22409 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022410
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022411 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022412 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022413 XML_SCHEMAV_CVC_TYPE_2,
22414 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022415 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022416 return (XML_SCHEMAV_CVC_TYPE_2);
22417 }
22418
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022419 switch (type->type) {
22420 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022421 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
22422 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022423 break;
22424 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022425 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022426 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022427 break;
22428 case XML_SCHEMA_TYPE_BASIC:
22429 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
22430 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
22431 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022432 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022433 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022434 break;
22435 default:
22436 ret = -1;
22437 break;
22438 }
22439 if (ret == -1)
22440 return (-1);
22441 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022442 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022443}
22444
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022445static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022446xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022447 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022448 const xmlChar *value,
22449 xmlSchemaValPtr *val)
22450{
22451 xmlSchemaTypePtr prim;
22452
22453 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022454 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022455 XML_SCHEMAV_INTERNAL,
22456 "Internal error: xmlSchemaPostCreateVal, "
22457 "bad arguments", NULL, NULL);
22458 return (-1);
22459 }
22460 /*
22461 * Only string or anySimpleType values are expected to be post-created.
22462 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022463 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022464 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
22465 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
22466 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022467 if (value == NULL)
22468 /* TODO: Can this happen at all? */
22469 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
22470 xmlStrdup(BAD_CAST ""));
22471 else
22472 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
22473 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022474 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022475 XML_SCHEMAV_INTERNAL,
22476 "Internal error: xmlSchemaPostCreateVal, "
22477 "failed to create the value", NULL, NULL);
22478 return (-1);
22479 }
22480 return (0);
22481 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022482 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022483 XML_SCHEMAV_INTERNAL,
22484 "Internal error: xmlSchemaPostCreateVal, "
22485 "the given type is not supported", NULL, NULL);
22486 return (-1);
22487}
22488
22489static int
22490xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022491 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022492{
22493 xmlChar *value;
22494 const xmlChar *defValue;
22495 xmlSchemaValPtr defVal;
22496 int fixed;
22497 int ret;
22498
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022499 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022500 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
22501 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
22502 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022503 vctxt->node = vctxt->attrInfo->node;
22504 vctxt->cur = vctxt->node->children;
22505 /* STREAM */
22506 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022507
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022508 /*
22509 * NOTE: This call also checks the content nodes for correct type.
22510 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022511 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022512 value, 1, 1, 1, 1);
22513
22514 /*
22515 * Handle 'fixed' attributes.
22516 */
22517 if (ret > 0) {
22518 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
22519 /*
22520 * NOTE: Fixed value constraints will be not
22521 * applied if the value was invalid, because:
22522 * 1. The validation process does not return a precomputed
22523 * value.
22524 * 2. An invalid value implies a violation of a fixed
22525 * value constraint.
22526 */
22527 } else if (ret == 0) {
22528 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022529 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022530 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022531 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022532
22533 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022534 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022535 /*
22536 * cvc-au : Attribute Locally Valid (Use)
22537 * For an attribute information item to be·valid·
22538 * with respect to an attribute use its ·normalized
22539 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022540 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022541 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022542 *
22543 * TODO: Use somehow the *normalized* value and the *canonical*
22544 * fixed value. This here compares the canonical values of both.
22545 * The normalized value of, for example, a float type can differ
22546 * from its canonical representation. This all means that a fixed
22547 * value can only be OK, if it's present in the canonical form in
22548 * the instance.
22549 * NOTE: Since the value for string and anySimpleType is not always
22550 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022551 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022552 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022553 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022554 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022555 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022556 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
22557 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022558 ret = -1;
22559 goto exit;
22560 }
22561 value = NULL;
22562 }
22563 if (defVal == NULL) {
22564 xmlChar *str;
22565
22566 /*
22567 * Post-create the default/fixed value.
22568 */
22569 if (defValue == NULL)
22570 str = xmlStrdup(BAD_CAST "");
22571 else
22572 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022573 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
22574 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022575 ret = -1;
22576 FREE_AND_NULL(str)
22577 goto exit;
22578 }
22579 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
22580 }
22581 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
22582 (xmlSchemaWhitespaceValueType) ws,
22583 defVal,
22584 (xmlSchemaWhitespaceValueType) ws) != 0)
22585 {
22586 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022587 }
22588 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022589 }
22590exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022591 if (value != NULL) {
22592 xmlFree(value);
22593 }
22594 return (ret);
22595}
22596
Daniel Veillard4255d502002-04-16 15:50:10 +000022597/**
22598 * xmlSchemaValidateAttributes:
22599 * @ctxt: a schema validation context
22600 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000022601 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000022602 *
22603 * Validate the attributes of an element.
22604 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000022605 * 1. Existent, invalid attributes are reported in the form
22606 * "prefix:localName".
22607 * Reason: readability - it is easier to find the actual XML
22608 * representation of the attributes QName.
22609 * 2. Missing attributes are reported in the form
22610 * {"URI", "localName"}.
22611 * This is necessary, since the the prefix need not to be declared
22612 * at all, and thus is not computable.
22613 *
Daniel Veillard4255d502002-04-16 15:50:10 +000022614 * Returns 0 if the element is schemas valid, a positive error code
22615 * number otherwise and -1 in case of internal or API error.
22616 */
22617static int
Daniel Veillard3646d642004-06-02 19:19:14 +000022618xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022619{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022620 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000022621 int ret;
22622 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022623 const xmlChar *defValue;
22624 xmlSchemaValPtr defVal;
22625 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022626 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000022627 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000022628 int found;
William M. Brack803812b2004-06-03 02:11:24 +000022629 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022630 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022631 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000022632#ifdef DEBUG_ATTR_VALIDATION
22633 int redundant = 0;
22634#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000022635
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022636
Daniel Veillardc0826a72004-08-10 14:17:33 +000022637 /*
22638 * Allow all attributes if the type is anyType.
22639 */
22640 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
22641 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022642
22643 oldnode = ctxt->node;
22644 if (type != NULL)
22645 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000022646 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000022647 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022648 attrDecl = attrUse->attr;
22649#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022650 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000022651 printf("attr use - use: %d\n", attrDecl->occurs);
22652#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022653 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022654
22655 if (curState->decl == attrUse->attr) {
22656#ifdef DEBUG_ATTR_VALIDATION
22657 redundant = 1;
22658#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022659 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022660 attr = curState->attr;
22661#ifdef DEBUG_ATTR_VALIDATION
22662 printf("attr - name: %s\n", attr->name);
22663 if (attr->ns != NULL)
22664 printf("attr - ns: %s\n", attr->ns->href);
22665 else
22666 printf("attr - ns: none\n");
22667#endif
22668 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022669 if (attr == NULL)
22670 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022671 if (attrDecl->ref != NULL) {
22672 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022673 continue;
22674 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022675 if ((attrDecl->refNs == NULL) ||
22676 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022677 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022678 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022679 continue;
22680 }
22681 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000022682 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022683 continue;
22684 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022685 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022686 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022687 if (attr->ns == NULL) {
22688 /*
William M. Bracke7091952004-05-11 15:09:58 +000022689 * accept an unqualified attribute only if the target
22690 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022691 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022692 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000022693 /*
22694 * This check was removed, since the target namespace
22695 * was evaluated during parsing and already took
22696 * "attributeFormDefault" into account.
22697 */
22698 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022699 continue;
22700 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000022701 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022702 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022703 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022704 attr->ns->href))
22705 continue;
22706 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022707 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022708#ifdef DEBUG_ATTR_VALIDATION
22709 printf("found\n");
22710#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022711 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000022712 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022713 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22714 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022715 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022716 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022717 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022718 if (!found) {
22719 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
22720 xmlSchemaAttrStatePtr tmp;
22721
Daniel Veillard3646d642004-06-02 19:19:14 +000022722#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022723 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022724#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022725 /*
22726 * Add a new dummy attribute state.
22727 */
22728 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
22729 if (tmp == NULL) {
22730 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
22731 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022732 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022733 }
22734 tmp->attr = NULL;
22735 tmp->state = XML_SCHEMAS_ATTR_MISSING;
22736 tmp->decl = attrDecl;
22737 tmp->next = NULL;
22738
22739 if (reqAttrStates == NULL) {
22740 reqAttrStates = tmp;
22741 reqAttrStatesTop = tmp;
22742 } else {
22743 reqAttrStatesTop->next = tmp;
22744 reqAttrStatesTop = tmp;
22745 }
22746 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
22747 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
22748 &fixed, &defValue, &defVal))) {
22749 xmlSchemaAttrStatePtr tmp;
22750 /*
22751 * Handle non existent default/fixed attributes.
22752 */
22753 tmp = (xmlSchemaAttrStatePtr)
22754 xmlMalloc(sizeof(xmlSchemaAttrState));
22755 if (tmp == NULL) {
22756 xmlSchemaVErrMemory(ctxt,
22757 "registering schema specified attributes", NULL);
22758 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022759 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022760 }
22761 tmp->attr = NULL;
22762 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
22763 tmp->decl = attrDecl;
22764 tmp->value = defValue;
22765 tmp->next = NULL;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022766 if (defAttrStatesTop == NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022767 defAttrStates = tmp;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022768 else
22769 defAttrStatesTop->next = tmp;
22770 defAttrStatesTop = tmp;
22771 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022772 }
22773 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000022774 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022775 /*
22776 * Add required attributes to the attribute states of the context.
22777 */
22778 if (reqAttrStates != NULL) {
22779 if (ctxt->attr == NULL) {
22780 ctxt->attr = reqAttrStates;
22781 } else {
22782 ctxt->attrTop->next = reqAttrStates;
22783 }
22784 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000022785 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022786 /*
22787 * Process wildcards.
22788 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022789
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022790 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022791#ifdef DEBUG_ATTR_VALIDATION
22792 xmlSchemaWildcardNsPtr ns;
22793 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022794 if (type->attributeWildcard->processContents ==
22795 XML_SCHEMAS_ANY_LAX)
22796 printf("processContents: lax\n");
22797 else if (type->attributeWildcard->processContents ==
22798 XML_SCHEMAS_ANY_STRICT)
22799 printf("processContents: strict\n");
22800 else
22801 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022802 if (type->attributeWildcard->any)
22803 printf("type: any\n");
22804 else if (type->attributeWildcard->negNsSet != NULL) {
22805 printf("type: negated\n");
22806 if (type->attributeWildcard->negNsSet->value == NULL)
22807 printf("ns: (absent)\n");
22808 else
22809 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
22810 } else if (type->attributeWildcard->nsSet != NULL) {
22811 printf("type: set\n");
22812 ns = type->attributeWildcard->nsSet;
22813 while (ns != NULL) {
22814 if (ns->value == NULL)
22815 printf("ns: (absent)\n");
22816 else
22817 printf("ns: %s\n", ns->value);
22818 ns = ns->next;
22819 }
22820 } else
22821 printf("empty\n");
22822
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022823
22824#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000022825 curState = ctxt->attr;
22826 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022827 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
22828 if (curState->attr->ns != NULL)
22829 nsURI = curState->attr->ns->href;
22830 else
22831 nsURI = NULL;
22832 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
22833 nsURI)) {
22834 /*
22835 * Handle processContents.
22836 */
22837 if ((type->attributeWildcard->processContents ==
22838 XML_SCHEMAS_ANY_LAX) ||
22839 (type->attributeWildcard->processContents ==
22840 XML_SCHEMAS_ANY_STRICT)) {
22841
22842 attr = curState->attr;
22843 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022844 attr->name, nsURI);
22845 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022846 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022847 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022848 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22849 /* TODO
22850 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
22851 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022852 } else if (type->attributeWildcard->processContents ==
22853 XML_SCHEMAS_ANY_LAX) {
22854 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022855 } else
22856 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022857 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000022858 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022859 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022860 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022861 curState = curState->next;
22862 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022863 }
22864
Daniel Veillardc0826a72004-08-10 14:17:33 +000022865 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022866 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022867
22868 /*
22869 * Validate the value of the attribute.
22870 */
22871 if (ctxt->value != NULL) {
22872 xmlSchemaFreeValue(ctxt->value);
22873 ctxt->value = NULL;
22874 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022875 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022876 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022877 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022878 switch (curState->state) {
22879 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022880
22881 /*
22882 * Create an attribute info if needed.
22883 */
22884 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022885 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22886 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022887 if (ctxt->attrInfo == NULL) {
22888 xmlSchemaVErrMemory(ctxt,
22889 "allocating an attribute info", NULL);
22890 goto fatal_exit;
22891 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000022892 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022893 }
22894 /*
22895 * Init the attribute info.
22896 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000022897 if (ctxt->attrInfo->value != NULL) {
22898 xmlSchemaFreeValue(ctxt->attrInfo->value);
22899 ctxt->attrInfo->value = NULL;
22900 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022901 ctxt->attrInfo->flags = 0;
22902 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
22903 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022904 if (curState->decl != NULL)
22905 ctxt->attrInfo->typeDef = curState->decl->subtypes;
22906 else
22907 ctxt->attrInfo->typeDef = NULL;
22908 if (curState->attr->ns != NULL)
22909 ctxt->attrInfo->namespaceName =
22910 curState->attr->ns->href;
22911 else
22912 ctxt->attrInfo->namespaceName = NULL;
22913 ctxt->attrInfo->localName = curState->attr->name;
22914
22915 ctxt->nodeInfo = ctxt->attrInfo;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022916 /*
22917 * Evaluate IDCs.
22918 */
22919 if (ctxt->xpathStates != NULL) {
22920 ret = xmlSchemaXPathEvaluate(ctxt,
22921 XML_ATTRIBUTE_NODE);
22922 if (ret == -1)
22923 goto fatal_exit;
22924 }
22925
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022926 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022927 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022928 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022929 if ((ret != 0) && (ctxt->value != NULL)) {
22930 xmlSchemaFreeValue(ctxt->value);
22931 ctxt->value = NULL;
22932 }
22933 /* No break on purpose. */
22934 case XML_SCHEMAS_ATTR_CHECKED:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022935 if (ctxt->xpathStates != NULL) {
22936 /*
22937 * Evaluate IDCs.
22938 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022939 if (ctxt->value != NULL) {
22940 ctxt->attrInfo->value = ctxt->value;
22941 ctxt->value = NULL;
22942 }
22943 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22944 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022945 }
22946 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022947 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022948 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022949 }
22950 curState = curState->next;
22951 }
22952
22953 /*
22954 * Report missing and illegal attributes.
22955 */
22956 curState = ctxt->attr;
22957 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000022958 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
22959 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022960 if (curState->decl != NULL) {
22961 if (curState->decl->ref != NULL)
22962 attrDecl = curState->decl->refDecl;
22963 else
22964 attrDecl = curState->decl;
22965 } else
22966 attrDecl = NULL;
22967 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
22968 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
22969 } else if (curState->state ==
22970 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
22971 xmlSchemaVCustomErr(ctxt,
22972 XML_SCHEMAV_CVC_ATTRIBUTE_2,
22973 (xmlNodePtr) attr,
22974 (xmlSchemaTypePtr) attrDecl,
22975 "The type definition is absent",
22976 NULL);
22977 } else if (curState->state ==
22978 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
22979 xmlSchemaVCustomErr(ctxt,
22980 XML_SCHEMAV_CVC_AU,
22981 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
22982 "The value does not match the fixed value "
22983 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022984 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
22985 xmlSchemaVWildcardErr(ctxt,
22986 XML_SCHEMAV_CVC_WILDCARD,
22987 (xmlNodePtr) attr,
22988 type->attributeWildcard,
22989 "No global attribute declaration found, but "
22990 "stipulated by the strict processContents of "
22991 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022992 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000022993 /* TODO: "prohibited" won't ever be touched here!.
22994 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
22995 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022996 /*
22997 * TODO: One might report different error messages
22998 * for the following errors.
22999 */
23000 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000023001 xmlSchemaVIllegalAttrErr(ctxt,
23002 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
23003 } else {
23004 xmlSchemaVIllegalAttrErr(ctxt,
23005 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
23006 }
23007 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000023008 }
23009 curState = curState->next;
23010 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023011 }
23012
23013 /*
23014 * Add missing default/fixed attributes.
23015 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023016 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023017 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023018
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023019 while (curState != NULL) {
23020 attrDecl = curState->decl;
23021 if (attrDecl->ref != NULL)
23022 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023023 /*
23024 * Evaluate IDCs on default attributes.
23025 */
23026 if (ctxt->xpathStates != NULL) {
23027 /*
23028 * Create an attribute info if needed.
23029 */
23030 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023031 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
23032 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023033 if (ctxt->attrInfo == NULL) {
23034 xmlSchemaVErrMemory(ctxt,
23035 "allocating an attribute info", NULL);
23036 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023037 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023038 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023039 }
23040 /*
23041 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000023042 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023043 */
23044 ctxt->attrInfo->flags = 0;
23045 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
23046 ctxt->attrInfo->node = NULL;
23047 ctxt->attrInfo->typeDef = attrDecl->subtypes;
23048 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
23049 ctxt->attrInfo->localName = attrDecl->name;
23050
23051 ctxt->nodeInfo = ctxt->attrInfo;
23052
23053 ret = xmlSchemaXPathEvaluate(ctxt,
23054 XML_ATTRIBUTE_NODE);
23055 if (ret == -1)
23056 goto fatal_exit;
23057 if (ctxt->attrInfo->value != NULL) {
23058 xmlSchemaFreeValue(ctxt->attrInfo->value);
23059 ctxt->attrInfo->value = NULL;
23060 }
23061 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000023062 /*
23063 * IDCs will consume the precomputed default value,
23064 * so we need to clone it somehow.
23065 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023066 /*
23067 * string or anySimpleType does not create a precomputed value
23068 * by default, so it will be created here on demand.
23069 * TODO: default/fixed attributes are a bit unoptimized:
23070 * the string value will be hold by ->defValue and inside
23071 * the precomputed value.
23072 */
23073 if (attrDecl->defVal == NULL) {
23074 xmlChar *str = xmlStrdup(attrDecl->defValue);
23075
23076 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000023077 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023078 str,
23079 &(attrDecl->defVal)) == -1) {
23080 FREE_AND_NULL(str)
23081 goto fatal_exit;
23082 }
23083 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023084 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
23085 /* TODO: error on NULL return. */
23086 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000023087
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023088 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
23089 goto fatal_exit;
23090 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023091
23092 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
23093 /*
23094 * PSVI: Add a new attribute node to the current element.
23095 */
23096 if (attrDecl->targetNamespace == NULL) {
23097 xmlNewProp(elem, attrDecl->name, curState->value);
23098 } else {
23099 xmlNsPtr ns;
23100
23101 ns = xmlSearchNsByHref(elem->doc, elem,
23102 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023103 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023104 xmlChar prefix[12];
23105 int counter = 1;
23106
23107 attr = curState->attr;
23108 /*
23109 * Create a namespace declaration on the validation
23110 * root node if no namespace declaration is in scope.
23111 */
23112 snprintf((char *) prefix, sizeof(prefix), "p");
23113 /*
23114 * This is somehow not performant, since the ancestor
23115 * axis beyond @elem will be searched as well.
23116 */
23117 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
23118 while (ns != NULL) {
23119 if (counter > 1000) {
23120 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
23121 XML_SCHEMAV_INTERNAL,
23122 "Internal error: xmlSchemaValidateAttributes, "
23123 "could not compute a ns prefix for "
23124 "default/fixed attribute '%s'.\n",
23125 attrDecl->name, NULL);
23126
23127 break;
23128 }
23129 snprintf((char *) prefix,
23130 sizeof(prefix), "p%d", counter++);
23131 ns = xmlSearchNs(elem->doc, elem,
23132 BAD_CAST prefix);
23133 }
23134 if (ns == NULL) {
23135 ns = xmlNewNs(ctxt->validationRoot,
23136 attrDecl->targetNamespace, BAD_CAST prefix);
23137 xmlNewNsProp(elem, ns, attrDecl->name,
23138 curState->value);
23139 }
23140 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023141 xmlNewNsProp(elem, ns, attrDecl->name,
23142 curState->value);
23143 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023144 }
23145 }
23146 curState = curState->next;
23147 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000023148 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023149 ret = ctxt->err;
23150 goto exit;
23151
23152fatal_exit:
23153 ret = -1;
23154
23155exit:
23156
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023157 if (defAttrStates != NULL)
23158 xmlSchemaFreeAttributeStates(defAttrStates);
23159
Daniel Veillard3646d642004-06-02 19:19:14 +000023160#ifdef DEBUG_ATTR_VALIDATION
23161 if (redundant)
23162 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023163 "xmlSchemaValidateAttributes: redundant call by "
23164 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000023165#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023166 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023167 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023168 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000023169}
23170
23171/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023172 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000023173 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000023174 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023175 * The starting point of the validation, called by
23176 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000023177 *
23178 * Returns 0 if the element is schemas valid, a positive error code
23179 * number otherwise and -1 in case of internal or API error.
23180 */
23181static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023182xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023183{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023184 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023185 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000023186
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023187 ctxt->err = 0;
23188 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023189 if (ctxt->schema == NULL) {
23190 /*
23191 * No schema was specified at time of creation of the validation
23192 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
23193 * of the instance to build a schema.
23194 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023195 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023196 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
23197 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023198 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
23199 if (ctxt->schema == NULL)
23200 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023201 ctxt->xsiAssemble = 1;
23202 } else
23203 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023204 /*
23205 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000023206 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023207 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023208 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
23209 if (ret == -1) {
23210 xmlSchemaVCustomErr(ctxt,
23211 XML_SCHEMAV_INTERNAL,
23212 ctxt->node, NULL,
23213 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023214 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023215 }
23216 /*
23217 * NOTE: We won't react on schema parser errors here.
23218 * TODO: But a warning would be nice.
23219 */
23220 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023221 if (ret != -1) {
23222 if (ctxt->node->ns != NULL)
23223 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
23224 ctxt->node->ns->href);
23225 else
23226 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
23227
23228 if (elemDecl == NULL) {
23229 xmlSchemaVCustomErr(ctxt,
23230 XML_SCHEMAV_CVC_ELT_1,
23231 ctxt->node, NULL,
23232 "No matching global declaration available", NULL);
23233 ret = XML_SCHEMAV_CVC_ELT_1;
23234 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023235 /*
23236 * Augment the IDC definitions.
23237 */
23238 if (ctxt->schema->idcDef != NULL) {
23239 xmlHashScan(ctxt->schema->idcDef,
23240 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
23241 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023242 ctxt->depth = -1;
23243 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023244 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023245 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023246 if (ret < 0) {
23247 xmlSchemaVCustomErr(ctxt,
23248 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
23249 "Internal error: xmlSchemaValidateElement, "
23250 "calling validation by declaration", NULL);
23251 }
23252 }
23253 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023254
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023255 if (ctxt->xsiAssemble) {
23256 if (ctxt->schema != NULL) {
23257 xmlSchemaFree(ctxt->schema);
23258 ctxt->schema = NULL;
23259 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023260 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023261 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023262 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000023263}
23264
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023265
Daniel Veillard4255d502002-04-16 15:50:10 +000023266/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023267 * xmlSchemaValidateOneElement:
23268 * @ctxt: a schema validation context
23269 * @elem: an element node
23270 *
23271 * Validate a branch of a tree, starting with the given @elem.
23272 *
23273 * Returns 0 if the element and its subtree is valid, a positive error
23274 * code number otherwise and -1 in case of an internal or API error.
23275 */
23276int
23277xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23278{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023279 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023280 return (-1);
23281
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023282 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023283 xmlSchemaVErr(ctxt, NULL,
23284 XML_SCHEMAV_INTERNAL,
23285 "API error: xmlSchemaValidateOneElement, "
23286 "no schema specified.\n", NULL, NULL);
23287 return (-1);
23288 }
23289
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023290 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023291 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023292 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023293 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023294}
23295
23296/************************************************************************
23297 * *
23298 * SAX Validation code *
23299 * *
23300 ************************************************************************/
23301
23302/************************************************************************
23303 * *
23304 * Validation interfaces *
23305 * *
23306 ************************************************************************/
23307
23308/**
23309 * xmlSchemaNewValidCtxt:
23310 * @schema: a precompiled XML Schemas
23311 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023312 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023313 *
23314 * Returns the validation context or NULL in case of error
23315 */
23316xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023317xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23318{
Daniel Veillard4255d502002-04-16 15:50:10 +000023319 xmlSchemaValidCtxtPtr ret;
23320
23321 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23322 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023323 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023324 return (NULL);
23325 }
23326 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000023327 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023328 return (ret);
23329}
23330
23331/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023332 * xmlSchemaClearValidCtxt:
23333 * @ctxt: the schema validation context
23334 *
23335 * Free the resources associated to the schema validation context;
23336 * leaves some fields alive intended for reuse of the context.
23337 */
23338static void
23339xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23340{
23341 if (vctxt == NULL)
23342 return;
23343
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023344 vctxt->flags = 0;
23345
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023346 vctxt->validationRoot = NULL;
23347 if (vctxt->attr != NULL) {
23348 xmlSchemaFreeAttributeStates(vctxt->attr);
23349 vctxt->attr = NULL;
23350 }
23351 if (vctxt->value != NULL) {
23352 xmlSchemaFreeValue(vctxt->value);
23353 vctxt->value = NULL;
23354 }
23355 /*
23356 * Augmented IDC information.
23357 */
23358 if (vctxt->aidcs != NULL) {
23359 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23360 do {
23361 next = cur->next;
23362 xmlFree(cur);
23363 cur = next;
23364 } while (cur != NULL);
23365 vctxt->aidcs = NULL;
23366 }
23367 if (vctxt->idcNodes != NULL) {
23368 int i;
23369 xmlSchemaPSVIIDCNodePtr item;
23370
23371 for (i = 0; i < vctxt->nbIdcNodes; i++) {
23372 item = vctxt->idcNodes[i];
23373 xmlFree(item->keys);
23374 xmlFree(item);
23375 }
23376 xmlFree(vctxt->idcNodes);
23377 vctxt->idcNodes = NULL;
23378 }
23379 /*
23380 * Note that we won't delete the XPath state pool here.
23381 */
23382 if (vctxt->xpathStates != NULL) {
23383 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23384 vctxt->xpathStates = NULL;
23385 }
23386 if (vctxt->attrInfo != NULL) {
23387 if (vctxt->attrInfo->value != NULL) {
23388 xmlSchemaFreeValue(vctxt->attrInfo->value);
23389 }
23390 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
23391 }
23392 if (vctxt->elemInfos != NULL) {
23393 int i;
23394 xmlSchemaNodeInfoPtr info;
23395
23396 for (i = 0; i < vctxt->sizeElemInfos; i++) {
23397 info = vctxt->elemInfos[i];
23398 if (info == NULL)
23399 break;
23400 if (info->value != NULL) {
23401 xmlSchemaFreeValue(info->value);
23402 info->value = NULL;
23403 }
23404 if (info->idcMatchers != NULL) {
23405 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
23406 info->idcMatchers = NULL;
23407 }
23408 if (info->idcTable != NULL) {
23409 xmlSchemaIDCFreeIDCTable(info->idcTable);
23410 info->idcTable = NULL;
23411 }
23412 }
23413 }
23414}
23415
23416/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023417 * xmlSchemaFreeValidCtxt:
23418 * @ctxt: the schema validation context
23419 *
23420 * Free the resources associated to the schema validation context
23421 */
23422void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023423xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23424{
Daniel Veillard4255d502002-04-16 15:50:10 +000023425 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023426 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023427 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000023428 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000023429 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023430 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023431 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023432 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023433 if (ctxt->idcNodes != NULL) {
23434 int i;
23435 xmlSchemaPSVIIDCNodePtr item;
23436
23437 for (i = 0; i < ctxt->nbIdcNodes; i++) {
23438 item = ctxt->idcNodes[i];
23439 xmlFree(item->keys);
23440 xmlFree(item);
23441 }
23442 xmlFree(ctxt->idcNodes);
23443 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023444 if (ctxt->idcKeys != NULL) {
23445 int i;
23446 for (i = 0; i < ctxt->nbIdcKeys; i++)
23447 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23448 xmlFree(ctxt->idcKeys);
23449 }
23450
23451 if (ctxt->xpathStates != NULL)
23452 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23453 if (ctxt->xpathStatePool != NULL)
23454 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23455
23456 /*
23457 * Augmented IDC information.
23458 */
23459 if (ctxt->aidcs != NULL) {
23460 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23461 do {
23462 next = cur->next;
23463 xmlFree(cur);
23464 cur = next;
23465 } while (cur != NULL);
23466 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023467 if (ctxt->attrInfo != NULL) {
23468 if (ctxt->attrInfo->value != NULL)
23469 xmlSchemaFreeValue(ctxt->attrInfo->value);
23470 xmlFree(ctxt->attrInfo);
23471 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023472 if (ctxt->elemInfos != NULL) {
23473 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023474 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023475
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023476 for (i = 0; i < ctxt->sizeElemInfos; i++) {
23477 info = ctxt->elemInfos[i];
23478 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023479 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023480 if (info->value != NULL)
23481 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023482 if (info->idcMatchers != NULL)
23483 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023484 if (info->idcTable != NULL)
23485 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023486 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023487 * TODO: Don't know if those will have to be freed if in streaming
23488 * mode.
23489 *
23490 * xmlFree(info->localName);
23491 * if (info->namespaceName != NULL)
23492 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023493 */
23494 xmlFree(info);
23495 }
23496 xmlFree(ctxt->elemInfos);
23497 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023498 xmlFree(ctxt);
23499}
23500
23501/**
23502 * xmlSchemaSetValidErrors:
23503 * @ctxt: a schema validation context
23504 * @err: the error function
23505 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023506 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023507 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023508 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023509 */
23510void
23511xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023512 xmlSchemaValidityErrorFunc err,
23513 xmlSchemaValidityWarningFunc warn, void *ctx)
23514{
Daniel Veillard4255d502002-04-16 15:50:10 +000023515 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023516 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023517 ctxt->error = err;
23518 ctxt->warning = warn;
23519 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023520 if (ctxt->pctxt != NULL)
23521 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023522}
23523
23524/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023525 * xmlSchemaGetValidErrors:
23526 * @ctxt: a XML-Schema validation context
23527 * @err: the error function result
23528 * @warn: the warning function result
23529 * @ctx: the functions context result
23530 *
23531 * Get the error and warning callback informations
23532 *
23533 * Returns -1 in case of error and 0 otherwise
23534 */
23535int
23536xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23537 xmlSchemaValidityErrorFunc * err,
23538 xmlSchemaValidityWarningFunc * warn, void **ctx)
23539{
23540 if (ctxt == NULL)
23541 return (-1);
23542 if (err != NULL)
23543 *err = ctxt->error;
23544 if (warn != NULL)
23545 *warn = ctxt->warning;
23546 if (ctx != NULL)
23547 *ctx = ctxt->userData;
23548 return (0);
23549}
23550
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023551
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023552/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023553 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023554 * @ctxt: a schema validation context
23555 * @options: a combination of xmlSchemaValidOption
23556 *
23557 * Sets the options to be used during the validation.
23558 *
23559 * Returns 0 in case of success, -1 in case of an
23560 * API error.
23561 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023562int
23563xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23564 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023565
23566{
23567 int i;
23568
23569 if (ctxt == NULL)
23570 return (-1);
23571 /*
23572 * WARNING: Change the start value if adding to the
23573 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023574 * TODO: Is there an other, more easy to maintain,
23575 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023576 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023577 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023578 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023579 xmlSchemaVErr(ctxt, NULL,
23580 XML_SCHEMAV_INTERNAL,
23581 "Internal error: xmlSchemaSetValidOptions, "
23582 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023583 return (-1);
23584 }
23585 }
23586 ctxt->options = options;
23587 return (0);
23588}
23589
23590/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023591 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023592 * @ctxt: a schema validation context
23593 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023594 * Get the validation context options.
23595 *
23596 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023597 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023598int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023599xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
23600
23601{
23602 if (ctxt == NULL)
23603 return (-1);
23604 else
23605 return (ctxt->options);
23606}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023607
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023608
Daniel Veillard259f0df2004-08-18 09:13:18 +000023609/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023610 * xmlSchemaValidateDoc:
23611 * @ctxt: a schema validation context
23612 * @doc: a parsed document tree
23613 *
23614 * Validate a document tree in memory.
23615 *
23616 * Returns 0 if the document is schemas valid, a positive error code
23617 * number otherwise and -1 in case of internal or API error.
23618 */
23619int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023620xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23621{
Daniel Veillard4255d502002-04-16 15:50:10 +000023622 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023623 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023624
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023625 ctxt->doc = doc;
23626 ctxt->node = xmlDocGetRootElement(doc);
23627 if (ctxt->node == NULL) {
23628 xmlSchemaVCustomErr(ctxt,
23629 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23630 (xmlNodePtr) doc, NULL,
23631 "The document has no document element", NULL);
23632 return (ctxt->err);
23633 }
23634 ctxt->validationRoot = ctxt->node;
23635 xmlSchemaStartValidation(ctxt);
23636
23637 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000023638}
23639
23640/**
23641 * xmlSchemaValidateStream:
23642 * @ctxt: a schema validation context
23643 * @input: the input to use for reading the data
23644 * @enc: an optional encoding information
23645 * @sax: a SAX handler for the resulting events
23646 * @user_data: the context to provide to the SAX handler.
23647 *
23648 * Validate a document tree in memory.
23649 *
23650 * Returns 0 if the document is schemas valid, a positive error code
23651 * number otherwise and -1 in case of internal or API error.
23652 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023653int
Daniel Veillard4255d502002-04-16 15:50:10 +000023654xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023655 xmlParserInputBufferPtr input, xmlCharEncoding enc,
23656 xmlSAXHandlerPtr sax, void *user_data)
23657{
Daniel Veillard4255d502002-04-16 15:50:10 +000023658 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023659 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023660 ctxt->input = input;
23661 ctxt->enc = enc;
23662 ctxt->sax = sax;
23663 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023664 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023665}
23666
Daniel Veillard5d4644e2005-04-01 13:11:58 +000023667#define bottom_xmlschemas
23668#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000023669#endif /* LIBXML_SCHEMAS_ENABLED */