blob: eb8b865b1f6eef43f90814251e0149ff20d56f2f [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 "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001886 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 } 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) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001893 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001894 /*
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) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011216
11217 /*
11218 * Lead nodes with the negated namespace to the sink-state
11219 * {"*", "##other"}.
11220 */
11221 xmlAutomataNewTransition2(ctxt->am, start, NULL,
11222 BAD_CAST "*", wild->negNsSet->value, wild);
11223 /* ctxt->state =
11224 * Capture those nodes with a transition which rejects
11225 * everything {"", ""}.
11226 */
11227#if 0
11228 xmlAutomataNewTransition2(ctxt->am, ctxt->state, NULL,
11229 NULL, NULL, wild);
11230#endif
11231 /*
11232 * Open a door for nodes with any other namespace
11233 * {"*", "*"}
11234 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011235 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011236 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011237 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11238 }
11239 } else {
11240 int counter;
11241 xmlAutomataStatePtr hop;
11242 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011244 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011245 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011246
11247 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11248 hop = xmlAutomataNewState(ctxt->am);
11249 if (wild->any == 1) {
11250 ctxt->state =
11251 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011252 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011253 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11254 ctxt->state =
11255 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011256 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011257 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11258 } else if (wild->nsSet != NULL) {
11259 ns = wild->nsSet;
11260 do {
11261 ctxt->state =
11262 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011263 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011264 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11265 ns = ns->next;
11266 } while (ns != NULL);
11267
11268 } else if (wild->negNsSet != NULL) {
11269 xmlAutomataStatePtr deadEnd;
11270
11271 deadEnd = xmlAutomataNewState(ctxt->am);
11272 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011274 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011275 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011276 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11277 }
11278 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11279 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011281 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011282 xmlAutomataNewEpsilon(ctxt->am, start, end);
11283 }
11284 ctxt->state = end;
11285 break;
11286 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011287 case XML_SCHEMA_TYPE_ELEMENT:
11288 xmlSchemaBuildContentModelForElement(ctxt, particle);
11289 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011290 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011291 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011292
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011293 /*
11294 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011295 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11298 sub = particle->children->children;
11299 while (sub != NULL) {
11300 xmlSchemaBuildAContentModel(ctxt,
11301 (xmlSchemaParticlePtr) sub, name);
11302 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011303 }
11304 } else {
11305 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011306
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011307 if (particle->maxOccurs >= UNBOUNDED) {
11308 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011309 xmlAutomataStatePtr tmp;
11310 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011311
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011312 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011313 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011314 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011315
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011316 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011318
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 tmp = ctxt->state;
11326 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11327 oldstate, counter);
11328 ctxt->state =
11329 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11330 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011331
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011332 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011333 sub = particle->children->children;
11334 while (sub != NULL) {
11335 xmlSchemaBuildAContentModel(ctxt,
11336 (xmlSchemaParticlePtr) sub, name);
11337 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011338 }
11339 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11340 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011341 if (particle->minOccurs == 0) {
11342 xmlAutomataNewEpsilon(ctxt->am,
11343 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011344 }
11345 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011346 } else if ((particle->maxOccurs > 1)
11347 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011348 xmlAutomataStatePtr tmp;
11349 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011350
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011351 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011352 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011353 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011354
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011355 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011356 particle->minOccurs - 1,
11357 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011358
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011359 sub = particle->children->children;
11360 while (sub != NULL) {
11361 xmlSchemaBuildAContentModel(ctxt,
11362 (xmlSchemaParticlePtr) sub, name);
11363 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011364 }
11365 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011366 xmlAutomataNewCountedTrans(ctxt->am,
11367 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011368 ctxt->state =
11369 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11370 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011371 if (particle->minOccurs == 0) {
11372 xmlAutomataNewEpsilon(ctxt->am,
11373 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011374 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011375 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011376 sub = particle->children->children;
11377 while (sub != NULL) {
11378 xmlSchemaBuildAContentModel(ctxt,
11379 (xmlSchemaParticlePtr) sub, name);
11380 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011381 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011382 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011383 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11384 ctxt->state);
11385 }
11386 }
11387 }
11388 break;
11389 }
11390 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011391 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011392 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011393
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011394 start = ctxt->state;
11395 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011396
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011397 /*
11398 * iterate over the subtypes and remerge the end with an
11399 * epsilon transition
11400 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011401 if (particle->maxOccurs == 1) {
11402 sub = particle->children->children;
11403 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011404 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011405 xmlSchemaBuildAContentModel(ctxt,
11406 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011407 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011408 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011409 }
11410 } else {
11411 int counter;
11412 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011413 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11414 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011415 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011416 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011417
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011418 /*
11419 * use a counter to keep track of the number of transtions
11420 * which went through the choice.
11421 */
11422 counter =
11423 xmlAutomataNewCounter(ctxt->am, minOccurs,
11424 maxOccurs);
11425 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011426
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011427 sub = particle->children->children;
11428 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011429 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011430 xmlSchemaBuildAContentModel(ctxt,
11431 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011432 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011433 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011434 }
11435 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11436 counter);
11437 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11438 counter);
11439 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011440 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011441 xmlAutomataNewEpsilon(ctxt->am, start, end);
11442 }
11443 ctxt->state = end;
11444 break;
11445 }
11446 case XML_SCHEMA_TYPE_ALL:{
11447 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011448 xmlSchemaParticlePtr sub;
11449 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011450 int lax;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011451
11452 sub = (xmlSchemaParticlePtr) particle->children->children;
11453 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011454 break;
11455 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011456 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011457 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011458
11459 elemDecl = (xmlSchemaElementPtr) sub->children;
11460 if (elemDecl == NULL) {
11461 xmlSchemaPErr(ctxt, NULL,
11462 XML_SCHEMAP_INTERNAL,
11463 "Internal error: xmlSchemaBuildAContentModel, "
11464 "<element> particle a NULL term.\n", NULL, NULL);
11465 return;
11466 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011467 /*
11468 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011469 * {particles} of the group must be 0 or 1; this is
11470 * already ensured during the parse of the content of
11471 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011472 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011473 if ((sub->minOccurs == 1) &&
11474 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011475 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11476 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011477 elemDecl->name,
11478 elemDecl->targetNamespace,
11479 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011480 } else if ((sub->minOccurs == 0) &&
11481 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011482
11483 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11484 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011485 elemDecl->name,
11486 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011487 0,
11488 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011489 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011490 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011491 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011492 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011493 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011494 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011495 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011496 break;
11497 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011498 default:
11499 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011500 "Internal error: xmlSchemaBuildAContentModel, found "
11501 "unexpected term of type %d in content model of complex "
11502 "type '%s'.\n",
11503 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011504 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011505 }
11506}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011507
Daniel Veillard4255d502002-04-16 15:50:10 +000011508/**
11509 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011510 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011512 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011513 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011514 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011515 */
11516static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011517xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011518 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011519 const xmlChar * name)
11520{
Daniel Veillard4255d502002-04-16 15:50:10 +000011521 xmlAutomataStatePtr start;
11522
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011523 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11524 (type->contModel != NULL) ||
11525 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11526 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011527 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011528
11529#ifdef DEBUG_CONTENT
11530 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011531 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011532#endif
11533
Daniel Veillard4255d502002-04-16 15:50:10 +000011534 ctxt->am = xmlNewAutomata();
11535 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011536 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011537 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011538 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011539 }
11540 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011541 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011542 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011543 type->contModel = xmlAutomataCompile(ctxt->am);
11544 if (type->contModel == NULL) {
11545 xmlSchemaPCustomErr(ctxt,
11546 XML_SCHEMAP_INTERNAL,
11547 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011548 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011549 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011550 xmlSchemaPCustomErr(ctxt,
11551 XML_SCHEMAP_NOT_DETERMINISTIC,
11552 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011553 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011554 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011555 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011556#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011557 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011558 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011559 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011560#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011561 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011562 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011563 xmlFreeAutomata(ctxt->am);
11564 ctxt->am = NULL;
11565}
11566
11567/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011568 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011569 * @elem: the schema element context
11570 * @ctxt: the schema parser context
11571 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011572 * Resolves the references of an element declaration
11573 * or particle, which has an element declaration as it's
11574 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011575 */
11576static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011577xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011578 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011579 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011580 const xmlChar * context ATTRIBUTE_UNUSED,
11581 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011582{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011583 if ((ctxt == NULL) || (elemDecl == NULL) ||
11584 ((elemDecl != NULL) && (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011585 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011586 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011588 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011589 xmlSchemaTypePtr type;
11590
11591 /* (type definition) ... otherwise the type definition ·resolved·
11592 * to by the ·actual value· of the type [attribute] ...
11593 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011594 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
11595 elemDecl->namedTypeNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011597 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011598 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011599 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
11600 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011601 XML_SCHEMA_TYPE_BASIC, "type definition");
11602 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011603 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011604 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011605 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011606 xmlSchemaElementPtr substHead;
11607
Daniel Veillardc0826a72004-08-10 14:17:33 +000011608 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011609 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
11610 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011611 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011612 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11613 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011614 if (substHead == NULL) {
11615 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011616 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011617 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
11618 "substitutionGroup", elemDecl->substGroup,
11619 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011620 } else {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011621 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011622 /*
11623 * Set the "substitution group affiliation".
11624 * NOTE that now we use the "refDecl" field for this.
11625 */
11626 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011627 /*
11628 * (type definition)...otherwise the {type definition} of the
11629 * element declaration ·resolved· to by the ·actual value· of
11630 * the substitutionGroup [attribute], if present
11631 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011632 if (elemDecl->subtypes == NULL)
11633 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011634 }
11635 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011636 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11637 (elemDecl->substGroup == NULL))
11638 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011639}
11640
11641/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011642 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011643 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011644 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011645 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011646 * Checks and builds the "member type definitions" property of the union
11647 * simple type. This handles part (1), part (2) is done in
11648 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11649 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011650 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011651 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011652static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011653xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11654 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011655{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011656
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011657 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011658 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011659
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011660 /*
11661 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Daniel Veillard01fa6152004-06-29 17:04:39 +000011662 * define the explicit members as the type definitions ·resolved·
11663 * to by the items in the ·actual value· of the memberTypes [attribute],
11664 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011665 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011666 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011667 /*
11668 * Resolve references.
11669 */
11670 link = type->memberTypes;
11671 lastLink = NULL;
11672 while (link != NULL) {
11673 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011674
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011675 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11676 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11677
11678 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11679 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11680 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
11681 NULL, type, type->node, "memberTypes",
11682 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11683 /*
11684 * Remove the member type link.
11685 */
11686 if (lastLink == NULL)
11687 type->memberTypes = link->next;
11688 else
11689 lastLink->next = link->next;
11690 newLink = link;
11691 link = link->next;
11692 xmlFree(newLink);
11693 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011694 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011695 lastLink = link;
11696 link = link->next;
11697 }
11698 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 /*
11700 * Add local simple types,
11701 */
11702 memberType = type->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011703 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011704 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11705 if (link == NULL) {
11706 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11707 return (-1);
11708 }
11709 link->type = memberType;
11710 link->next = NULL;
11711 if (lastLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011712 type->memberTypes = link;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011713 else
11714 lastLink->next = link;
11715 lastLink = link;
11716 memberType = memberType->next;
11717 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011718 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011719}
11720
Daniel Veillard4255d502002-04-16 15:50:10 +000011721/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011722 * xmlSchemaIsDerivedFromBuiltInType:
11723 * @ctxt: the schema parser context
11724 * @type: the type definition
11725 * @valType: the value type
11726 *
11727 *
11728 * Returns 1 if the type has the given value type, or
11729 * is derived from such a type.
11730 */
William M. Brack803812b2004-06-03 02:11:24 +000011731static int
Daniel Veillard3646d642004-06-02 19:19:14 +000011732xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
11733 xmlSchemaTypePtr type, int valType)
11734{
11735 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011736 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011737 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011738 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011739 return(1);
11740 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
11741 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
11742 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
11743 ((xmlSchemaAttributePtr) type)->subtypes, valType));
11744 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
11745 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
11746 if (type->baseType != NULL)
11747 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
11748 valType));
11749 } else if ((type->subtypes != NULL) &&
11750 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
11751 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11752 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
11753 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
11754 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
11755 valType));
11756 }
11757
11758 return (0);
11759}
11760
11761/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011762 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011763 * @type: the simpleType definition
11764 *
11765 * Returns the primitive type of the given type or
11766 * NULL in case of error.
11767 */
11768static xmlSchemaTypePtr
11769xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11770{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011771
Daniel Veillard01fa6152004-06-29 17:04:39 +000011772 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011773 /*
11774 * Note that anySimpleType is actually not a primitive type
11775 * but we need that here.
11776 */
11777 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11778 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011779 return (type);
11780 type = type->baseType;
11781 }
11782
11783 return (NULL);
11784}
11785
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011786#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011787/**
11788 * xmlSchemaGetBuiltInTypeAncestor:
11789 * @type: the simpleType definition
11790 *
11791 * Returns the primitive type of the given type or
11792 * NULL in case of error.
11793 */
11794static xmlSchemaTypePtr
11795xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11796{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011797 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11798 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
11799 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011800 while (type != NULL) {
11801 if (type->type == XML_SCHEMA_TYPE_BASIC)
11802 return (type);
11803 type = type->baseType;
11804 }
11805
11806 return (NULL);
11807}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011808#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011809
Daniel Veillard01fa6152004-06-29 17:04:39 +000011810/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011811 * xmlSchemaBuildAttributeUsesOwned:
11812 * @ctxt: the schema parser context
11813 * @type: the complex type definition
11814 * @cur: the attribute declaration list
11815 * @lastUse: the top of the attribute use list
11816 *
11817 * Builds the attribute uses list on the given complex type.
11818 * This one is supposed to be called by
11819 * xmlSchemaBuildAttributeValidation only.
11820 */
11821static int
11822xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
11823 xmlSchemaAttributePtr cur,
11824 xmlSchemaAttributeLinkPtr *uses,
11825 xmlSchemaAttributeLinkPtr *lastUse)
11826{
11827 xmlSchemaAttributeLinkPtr tmp;
11828 while (cur != NULL) {
11829 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11830 /*
11831 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11832 * to by the ·actual value·s of the ref [attribute] of the
11833 * <attributeGroup> [children], if any."
11834 */
11835 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11836 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
11837 lastUse) == -1) {
11838 return (-1);
11839 }
11840 } else {
11841 /* W3C: "1 The set of attribute uses corresponding to the
11842 * <attribute> [children], if any."
11843 */
11844 tmp = (xmlSchemaAttributeLinkPtr)
11845 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11846 if (tmp == NULL) {
11847 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11848 return (-1);
11849 }
11850 tmp->attr = cur;
11851 tmp->next = NULL;
11852 if (*uses == NULL)
11853 *uses = tmp;
11854 else
11855 (*lastUse)->next = tmp;
11856 *lastUse = tmp;
11857 }
11858 cur = cur->next;
11859 }
11860 return (0);
11861}
11862
Daniel Veillard50355f02004-06-08 17:52:16 +000011863/**
11864 * xmlSchemaCloneWildcardNsConstraints:
11865 * @ctxt: the schema parser context
11866 * @dest: the destination wildcard
11867 * @source: the source wildcard
11868 *
11869 * Clones the namespace constraints of source
11870 * and assignes them to dest.
11871 * Returns -1 on internal error, 0 otherwise.
11872 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011873static int
11874xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11875 xmlSchemaWildcardPtr *dest,
11876 xmlSchemaWildcardPtr source)
11877{
11878 xmlSchemaWildcardNsPtr cur, tmp, last;
11879
11880 if ((source == NULL) || (*dest == NULL))
11881 return(-1);
11882 (*dest)->any = source->any;
11883 cur = source->nsSet;
11884 last = NULL;
11885 while (cur != NULL) {
11886 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11887 if (tmp == NULL)
11888 return(-1);
11889 tmp->value = cur->value;
11890 if (last == NULL)
11891 (*dest)->nsSet = tmp;
11892 else
11893 last->next = tmp;
11894 last = tmp;
11895 cur = cur->next;
11896 }
11897 if ((*dest)->negNsSet != NULL)
11898 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
11899 if (source->negNsSet != NULL) {
11900 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11901 if ((*dest)->negNsSet == NULL)
11902 return(-1);
11903 (*dest)->negNsSet->value = source->negNsSet->value;
11904 } else
11905 (*dest)->negNsSet = NULL;
11906 return(0);
11907}
11908
Daniel Veillard50355f02004-06-08 17:52:16 +000011909/**
11910 * xmlSchemaUnionWildcards:
11911 * @ctxt: the schema parser context
11912 * @completeWild: the first wildcard
11913 * @curWild: the second wildcard
11914 *
11915 * Unions the namespace constraints of the given wildcards.
11916 * @completeWild will hold the resulting union.
11917 * Returns a positive error code on failure, -1 in case of an
11918 * internal error, 0 otherwise.
11919 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011920static int
11921xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11922 xmlSchemaWildcardPtr completeWild,
11923 xmlSchemaWildcardPtr curWild)
11924{
11925 xmlSchemaWildcardNsPtr cur, curB, tmp;
11926
11927 /*
11928 * 1 If O1 and O2 are the same value, then that value must be the
11929 * value.
11930 */
11931 if ((completeWild->any == curWild->any) &&
11932 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11933 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11934
11935 if ((completeWild->negNsSet == NULL) ||
11936 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11937
11938 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011939 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011940
11941 /*
11942 * Check equality of sets.
11943 */
11944 cur = completeWild->nsSet;
11945 while (cur != NULL) {
11946 found = 0;
11947 curB = curWild->nsSet;
11948 while (curB != NULL) {
11949 if (cur->value == curB->value) {
11950 found = 1;
11951 break;
11952 }
11953 curB = curB->next;
11954 }
11955 if (!found)
11956 break;
11957 cur = cur->next;
11958 }
11959 if (found)
11960 return(0);
11961 } else
11962 return(0);
11963 }
11964 }
11965 /*
11966 * 2 If either O1 or O2 is any, then any must be the value
11967 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011968 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011969 if (completeWild->any == 0) {
11970 completeWild->any = 1;
11971 if (completeWild->nsSet != NULL) {
11972 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11973 completeWild->nsSet = NULL;
11974 }
11975 if (completeWild->negNsSet != NULL) {
11976 xmlFree(completeWild->negNsSet);
11977 completeWild->negNsSet = NULL;
11978 }
11979 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011980 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011981 }
11982 /*
11983 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11984 * then the union of those sets must be the value.
11985 */
11986 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11987 int found;
11988 xmlSchemaWildcardNsPtr start;
11989
11990 cur = curWild->nsSet;
11991 start = completeWild->nsSet;
11992 while (cur != NULL) {
11993 found = 0;
11994 curB = start;
11995 while (curB != NULL) {
11996 if (cur->value == curB->value) {
11997 found = 1;
11998 break;
11999 }
12000 curB = curB->next;
12001 }
12002 if (!found) {
12003 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
12004 if (tmp == NULL)
12005 return (-1);
12006 tmp->value = cur->value;
12007 tmp->next = completeWild->nsSet;
12008 completeWild->nsSet = tmp;
12009 }
12010 cur = cur->next;
12011 }
12012
12013 return(0);
12014 }
12015 /*
12016 * 4 If the two are negations of different values (namespace names
12017 * or ·absent·), then a pair of not and ·absent· must be the value.
12018 */
12019 if ((completeWild->negNsSet != NULL) &&
12020 (curWild->negNsSet != NULL) &&
12021 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12022 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012023
12024 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012025 }
12026 /*
12027 * 5.
12028 */
12029 if (((completeWild->negNsSet != NULL) &&
12030 (completeWild->negNsSet->value != NULL) &&
12031 (curWild->nsSet != NULL)) ||
12032 ((curWild->negNsSet != NULL) &&
12033 (curWild->negNsSet->value != NULL) &&
12034 (completeWild->nsSet != NULL))) {
12035
12036 int nsFound, absentFound = 0;
12037
12038 if (completeWild->nsSet != NULL) {
12039 cur = completeWild->nsSet;
12040 curB = curWild->negNsSet;
12041 } else {
12042 cur = curWild->nsSet;
12043 curB = completeWild->negNsSet;
12044 }
12045 nsFound = 0;
12046 while (cur != NULL) {
12047 if (cur->value == NULL)
12048 absentFound = 1;
12049 else if (cur->value == curB->value)
12050 nsFound = 1;
12051 if (nsFound && absentFound)
12052 break;
12053 cur = cur->next;
12054 }
12055
12056 if (nsFound && absentFound) {
12057 /*
12058 * 5.1 If the set S includes both the negated namespace
12059 * name and ·absent·, then any must be the value.
12060 */
12061 completeWild->any = 1;
12062 if (completeWild->nsSet != NULL) {
12063 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12064 completeWild->nsSet = NULL;
12065 }
12066 if (completeWild->negNsSet != NULL) {
12067 xmlFree(completeWild->negNsSet);
12068 completeWild->negNsSet = NULL;
12069 }
12070 } else if (nsFound && (!absentFound)) {
12071 /*
12072 * 5.2 If the set S includes the negated namespace name
12073 * but not ·absent·, then a pair of not and ·absent· must
12074 * be the value.
12075 */
12076 if (completeWild->nsSet != NULL) {
12077 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12078 completeWild->nsSet = NULL;
12079 }
12080 if (completeWild->negNsSet == NULL) {
12081 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12082 if (completeWild->negNsSet == NULL)
12083 return (-1);
12084 }
12085 completeWild->negNsSet->value = NULL;
12086 } else if ((!nsFound) && absentFound) {
12087 /*
12088 * 5.3 If the set S includes ·absent· but not the negated
12089 * namespace name, then the union is not expressible.
12090 */
12091 xmlSchemaPErr(ctxt, completeWild->node,
12092 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012093 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012094 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012095 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012096 } else if ((!nsFound) && (!absentFound)) {
12097 /*
12098 * 5.4 If the set S does not include either the negated namespace
12099 * name or ·absent·, then whichever of O1 or O2 is a pair of not
12100 * and a namespace name must be the value.
12101 */
12102 if (completeWild->negNsSet == NULL) {
12103 if (completeWild->nsSet != NULL) {
12104 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12105 completeWild->nsSet = NULL;
12106 }
12107 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12108 if (completeWild->negNsSet == NULL)
12109 return (-1);
12110 completeWild->negNsSet->value = curWild->negNsSet->value;
12111 }
12112 }
12113 return (0);
12114 }
12115 /*
12116 * 6.
12117 */
12118 if (((completeWild->negNsSet != NULL) &&
12119 (completeWild->negNsSet->value == NULL) &&
12120 (curWild->nsSet != NULL)) ||
12121 ((curWild->negNsSet != NULL) &&
12122 (curWild->negNsSet->value == NULL) &&
12123 (completeWild->nsSet != NULL))) {
12124
12125 if (completeWild->nsSet != NULL) {
12126 cur = completeWild->nsSet;
12127 } else {
12128 cur = curWild->nsSet;
12129 }
12130 while (cur != NULL) {
12131 if (cur->value == NULL) {
12132 /*
12133 * 6.1 If the set S includes ·absent·, then any must be the
12134 * value.
12135 */
12136 completeWild->any = 1;
12137 if (completeWild->nsSet != NULL) {
12138 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12139 completeWild->nsSet = NULL;
12140 }
12141 if (completeWild->negNsSet != NULL) {
12142 xmlFree(completeWild->negNsSet);
12143 completeWild->negNsSet = NULL;
12144 }
12145 return (0);
12146 }
12147 cur = cur->next;
12148 }
12149 if (completeWild->negNsSet == NULL) {
12150 /*
12151 * 6.2 If the set S does not include ·absent·, then a pair of not
12152 * and ·absent· must be the value.
12153 */
12154 if (completeWild->nsSet != NULL) {
12155 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12156 completeWild->nsSet = NULL;
12157 }
12158 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12159 if (completeWild->negNsSet == NULL)
12160 return (-1);
12161 completeWild->negNsSet->value = NULL;
12162 }
12163 return (0);
12164 }
12165 return (0);
12166
12167}
12168
Daniel Veillard50355f02004-06-08 17:52:16 +000012169/**
12170 * xmlSchemaIntersectWildcards:
12171 * @ctxt: the schema parser context
12172 * @completeWild: the first wildcard
12173 * @curWild: the second wildcard
12174 *
12175 * Intersects the namespace constraints of the given wildcards.
12176 * @completeWild will hold the resulting intersection.
12177 * Returns a positive error code on failure, -1 in case of an
12178 * internal error, 0 otherwise.
12179 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012180static int
12181xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
12182 xmlSchemaWildcardPtr completeWild,
12183 xmlSchemaWildcardPtr curWild)
12184{
William M. Brack803812b2004-06-03 02:11:24 +000012185 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012186
12187 /*
12188 * 1 If O1 and O2 are the same value, then that value must be the
12189 * value.
12190 */
12191 if ((completeWild->any == curWild->any) &&
12192 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12193 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
12194
12195 if ((completeWild->negNsSet == NULL) ||
12196 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
12197
12198 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012199 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012200
12201 /*
12202 * Check equality of sets.
12203 */
12204 cur = completeWild->nsSet;
12205 while (cur != NULL) {
12206 found = 0;
12207 curB = curWild->nsSet;
12208 while (curB != NULL) {
12209 if (cur->value == curB->value) {
12210 found = 1;
12211 break;
12212 }
12213 curB = curB->next;
12214 }
12215 if (!found)
12216 break;
12217 cur = cur->next;
12218 }
12219 if (found)
12220 return(0);
12221 } else
12222 return(0);
12223 }
12224 }
12225 /*
12226 * 2 If either O1 or O2 is any, then the other must be the value.
12227 */
12228 if ((completeWild->any != curWild->any) && (completeWild->any)) {
12229 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12230 return(-1);
12231 return(0);
12232 }
12233 /*
12234 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12235 * name or ·absent·) and the other is a set of (namespace names or
12236 * ·absent·), then that set, minus the negated value if it was in
12237 * the set, minus ·absent· if it was in the set, must be the value.
12238 */
12239 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12240 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12241 const xmlChar *neg;
12242
12243 if (completeWild->nsSet == NULL) {
12244 neg = completeWild->negNsSet->value;
12245 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12246 return(-1);
12247 } else
12248 neg = curWild->negNsSet->value;
12249 /*
12250 * Remove absent and negated.
12251 */
12252 prev = NULL;
12253 cur = completeWild->nsSet;
12254 while (cur != NULL) {
12255 if (cur->value == NULL) {
12256 if (prev == NULL)
12257 completeWild->nsSet = cur->next;
12258 else
12259 prev->next = cur->next;
12260 xmlFree(cur);
12261 break;
12262 }
12263 prev = cur;
12264 cur = cur->next;
12265 }
12266 if (neg != NULL) {
12267 prev = NULL;
12268 cur = completeWild->nsSet;
12269 while (cur != NULL) {
12270 if (cur->value == neg) {
12271 if (prev == NULL)
12272 completeWild->nsSet = cur->next;
12273 else
12274 prev->next = cur->next;
12275 xmlFree(cur);
12276 break;
12277 }
12278 prev = cur;
12279 cur = cur->next;
12280 }
12281 }
12282
12283 return(0);
12284 }
12285 /*
12286 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
12287 * then the intersection of those sets must be the value.
12288 */
12289 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
12290 int found;
12291
12292 cur = completeWild->nsSet;
12293 prev = NULL;
12294 while (cur != NULL) {
12295 found = 0;
12296 curB = curWild->nsSet;
12297 while (curB != NULL) {
12298 if (cur->value == curB->value) {
12299 found = 1;
12300 break;
12301 }
12302 curB = curB->next;
12303 }
12304 if (!found) {
12305 if (prev == NULL)
12306 completeWild->nsSet = cur->next;
12307 else
12308 prev->next = cur->next;
12309 tmp = cur->next;
12310 xmlFree(cur);
12311 cur = tmp;
12312 continue;
12313 }
12314 prev = cur;
12315 cur = cur->next;
12316 }
12317
12318 return(0);
12319 }
12320 /* 5 If the two are negations of different namespace names,
12321 * then the intersection is not expressible
12322 */
12323 if ((completeWild->negNsSet != NULL) &&
12324 (curWild->negNsSet != NULL) &&
12325 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12326 (completeWild->negNsSet->value != NULL) &&
12327 (curWild->negNsSet->value != NULL)) {
12328
12329 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012330 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012331 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012332 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012333 }
12334 /*
12335 * 6 If the one is a negation of a namespace name and the other
12336 * is a negation of ·absent·, then the one which is the negation
12337 * of a namespace name must be the value.
12338 */
12339 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12340 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12341 (completeWild->negNsSet->value == NULL)) {
12342 completeWild->negNsSet->value = curWild->negNsSet->value;
12343 }
12344 return(0);
12345}
12346
Daniel Veillard50355f02004-06-08 17:52:16 +000012347/**
12348 * xmlSchemaIsWildcardNsConstraintSubset:
12349 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012350 * @sub: the first wildcard
12351 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012352 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012353 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12354 *
12355 * Returns 0 if the namespace constraint of @sub is an intensional
12356 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012357 */
12358static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012359xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12360 xmlSchemaWildcardPtr super)
12361{
Daniel Veillard50355f02004-06-08 17:52:16 +000012362 /*
12363 * 1 super must be any.
12364 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012365 if (super->any)
12366 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012367 /*
12368 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12369 * 2.2 super must be a pair of not and the same value.
12370 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012371 if ((sub->negNsSet != NULL) &&
12372 (super->negNsSet != NULL) &&
12373 (sub->negNsSet->value == sub->negNsSet->value))
12374 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012375 /*
12376 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
12377 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012378 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012379 /*
12380 * 3.2.1 super must be the same set or a superset thereof.
12381 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012382 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012383 xmlSchemaWildcardNsPtr cur, curB;
12384 int found = 0;
12385
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012386 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012387 while (cur != NULL) {
12388 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012389 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012390 while (curB != NULL) {
12391 if (cur->value == curB->value) {
12392 found = 1;
12393 break;
12394 }
12395 curB = curB->next;
12396 }
12397 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012398 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012399 cur = cur->next;
12400 }
12401 if (found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012402 return (0);
12403 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012404 xmlSchemaWildcardNsPtr cur;
12405 /*
12406 * 3.2.2 super must be a pair of not and a namespace name or
12407 * ·absent· and that value must not be in sub's set.
12408 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012409 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012410 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012411 if (cur->value == super->negNsSet->value)
12412 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012413 cur = cur->next;
12414 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012415 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012416 }
12417 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012418 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012419}
12420
12421/**
12422 * xmlSchemaBuildCompleteAttributeWildcard:
12423 * @ctxt: the schema parser context
12424 * @attrs: the attribute list
12425 * @completeWild: the resulting complete wildcard
12426 *
12427 * Returns -1 in case of an internal error, 0 otherwise.
12428 */
12429static int
12430xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
12431 xmlSchemaAttributePtr attrs,
12432 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000012433{
12434 while (attrs != NULL) {
12435 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12436 xmlSchemaAttributeGroupPtr group;
12437
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012438 group = (xmlSchemaAttributeGroupPtr) attrs;
12439 /*
12440 * Handle attribute group references.
12441 */
12442 if (group->ref != NULL) {
12443 if (group->refItem == NULL) {
12444 /*
12445 * TODO: Should we raise a warning here?
12446 */
12447 /*
12448 * The referenced attribute group definition could not
12449 * be resolved beforehand, so skip.
12450 */
12451 attrs = attrs->next;
12452 continue;
12453 } else
12454 group = group->refItem;
12455 }
12456 /*
12457 * For every attribute group definition, an intersected wildcard
12458 * will be created (assumed that a wildcard exists on the
12459 * particular attr. gr. def. or on any contained attr. gr. def
12460 * at all).
12461 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12462 * that the intersection will be performed only once.
12463 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012464 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12465 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012466 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12467 group->attributes, &group->attributeWildcard) == -1)
12468 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012469 }
12470 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
12471 }
12472 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012473 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012474 /*
12475 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012476 *
12477 * Although the complete wildcard might not correspond to any
12478 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012479 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012480 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12481 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12482 group->attributeWildcard->node);
Daniel Veillard50355f02004-06-08 17:52:16 +000012483 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
12484 completeWild, group->attributeWildcard) == -1)
12485 return (-1);
12486 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012487 (*completeWild)->node = group->attributeWildcard->node;
12488 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012489 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012490 }
12491 }
12492 attrs = attrs->next;
12493 }
12494
Daniel Veillard50355f02004-06-08 17:52:16 +000012495 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012496}
12497
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012498static int
12499xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12500 int *fixed,
12501 const xmlChar **value,
12502 xmlSchemaValPtr *val)
12503{
12504 *fixed = 0;
12505 *value = NULL;
12506 if (val != 0)
12507 *val = NULL;
12508
12509 if (item->defValue == NULL)
12510 item = item->refDecl;
12511
12512 if (item == NULL)
12513 return (0);
12514
12515 if (item->defValue != NULL) {
12516 *value = item->defValue;
12517 if (val != 0)
12518 *val = item->defVal;
12519 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12520 *fixed = 1;
12521 return (1);
12522 }
12523 return (0);
12524}
Daniel Veillard3646d642004-06-02 19:19:14 +000012525/**
12526 * xmlSchemaMatchesWildcardNs:
12527 * @wild: the wildcard
12528 * @ns: the namespace
12529 *
12530 *
12531 * Returns 1 if the given namespace matches the wildcard,
12532 * 0 otherwise.
12533 */
12534static int
12535xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
12536{
12537 if (wild == NULL)
12538 return(0);
12539
12540 if (wild->any)
12541 return(1);
12542 else if (wild->nsSet != NULL) {
12543 xmlSchemaWildcardNsPtr cur;
12544
12545 cur = wild->nsSet;
12546 while (cur != NULL) {
12547 if (xmlStrEqual(cur->value, ns))
12548 return(1);
12549 cur = cur->next;
12550 }
12551 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
12552 (!xmlStrEqual(wild->negNsSet->value, ns)))
12553 return(1);
12554
12555 return(0);
12556}
12557
12558/**
12559 * xmlSchemaBuildAttributeValidation:
12560 * @ctxt: the schema parser context
12561 * @type: the complex type definition
12562 *
12563 *
12564 * Builds the wildcard and the attribute uses on the given complex type.
12565 * Returns -1 if an internal error occurs, 0 otherwise.
12566 */
12567static int
12568xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
12569{
12570 xmlSchemaTypePtr baseType = NULL;
12571 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000012572 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012573 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012574 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000012575 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012576 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012577 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012578
Daniel Veillard01fa6152004-06-29 17:04:39 +000012579 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012580 /*
12581 * Complex Type Definition with complex content Schema Component.
12582 *
12583 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012584 * TODO: Add checks for absent referenced attribute declarations and
12585 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012586 */
12587 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012588 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012589 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000012590 "attribute uses already builded.\n",
12591 NULL, NULL);
12592 return (-1);
12593 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012594 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012595 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012596 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012597 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012598 type->name, NULL);
12599 return (-1);
12600 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012601 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012602 if (baseType == anyType)
12603 baseIsAnyType = 1;
12604 /*
12605 * Inherit the attribute uses of the base type.
12606 */
12607 /*
12608 * NOTE: It is allowed to "extend" the anyType complex type.
12609 */
12610 if (!baseIsAnyType) {
12611 if (baseType != NULL) {
12612 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
12613 tmp = (xmlSchemaAttributeLinkPtr)
12614 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12615 if (tmp == NULL) {
12616 xmlSchemaPErrMemory(ctxt,
12617 "building attribute uses of complexType", NULL);
12618 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012619 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012620 tmp->attr = cur->attr;
12621 tmp->next = NULL;
12622 if (type->attributeUses == NULL) {
12623 type->attributeUses = tmp;
12624 } else
12625 lastBaseUse->next = tmp;
12626 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012627 }
12628 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012629 }
12630 if ((type->subtypes != NULL) &&
12631 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
12632 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012633 /*
12634 * type --> (<simpleContent>|<complexContent>)
12635 * --> (<restriction>|<extension>) --> attributes
12636 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012637 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012638 } else {
12639 /* Short hand form of the complexType. */
12640 attrs = type->attributes;
12641 }
12642 /*
12643 * Handle attribute wildcards.
12644 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012645 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12646 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012647 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012648 * NOTE: During the parse time, the wildcard is created on the complexType
12649 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012650 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012651 if (err == -1) {
12652 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
12653 "Internal error: xmlSchemaBuildAttributeValidation: "
12654 "failed to build an intersected attribute wildcard.\n",
12655 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012656 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012657 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012658
12659 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12660 ((baseIsAnyType) ||
12661 ((baseType != NULL) &&
12662 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12663 (baseType->attributeWildcard != NULL)))) {
12664 if (type->attributeWildcard != NULL) {
12665 /*
12666 * Union the complete wildcard with the base wildcard.
12667 */
12668 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
12669 baseType->attributeWildcard) == -1)
12670 return (-1);
12671 } else {
12672 /*
12673 * Just inherit the wildcard.
12674 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012675 /*
12676 * NOTE: This is the only case where an attribute
12677 * wildcard is shared.
12678 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012679 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012680 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012681 }
12682
12683 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12684 if (type->attributeWildcard != NULL) {
12685 /*
12686 * Derivation Valid (Restriction, Complex)
12687 * 4.1 The {base type definition} must also have one.
12688 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012689 if (baseType->attributeWildcard == NULL) {
12690 xmlSchemaPCustomErr(ctxt,
12691 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
12692 NULL, type, NULL,
12693 "The type has an attribute wildcard, "
12694 "but the base type %s does not have one",
12695 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12696 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012697 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012698 } else if (xmlSchemaCheckCOSNSSubset(
12699 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012700 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012701 xmlSchemaPCustomErr(ctxt,
12702 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
12703 NULL, type, NULL,
12704 "The attribute wildcard is not a valid "
12705 "subset of the wildcard in the base type %s",
12706 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12707 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012708 return (1);
12709 }
12710 /* 4.3 Unless the {base type definition} is the ·ur-type
12711 * definition·, the complex type definition's {attribute
12712 * wildcard}'s {process contents} must be identical to or
12713 * stronger than the {base type definition}'s {attribute
12714 * wildcard}'s {process contents}, where strict is stronger
12715 * than lax is stronger than skip.
12716 */
12717 if ((type->baseType != anyType) &&
12718 (type->attributeWildcard->processContents <
12719 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012720 xmlSchemaPCustomErr(ctxt,
12721 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
12722 NULL, type, NULL,
12723 "The 'process contents' of the attribute wildcard is weaker than "
12724 "the one in the base type %s",
12725 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12726 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012727 return (1);
12728 }
12729 }
12730 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12731 /*
12732 * Derivation Valid (Extension)
12733 * At this point the type and the base have both, either
12734 * no wildcard or a wildcard.
12735 */
12736 if ((baseType->attributeWildcard != NULL) &&
12737 (baseType->attributeWildcard != type->attributeWildcard)) {
12738 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012739 if (xmlSchemaCheckCOSNSSubset(
12740 baseType->attributeWildcard, type->attributeWildcard)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012741 xmlSchemaPCustomErr(ctxt,
12742 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
12743 NULL, type, NULL,
12744 "The attribute wildcard is not a valid "
12745 "superset of the one in the base type %s",
12746 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12747 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012748 return (1);
12749 }
12750 }
12751 }
12752
Daniel Veillard3646d642004-06-02 19:19:14 +000012753 /*
12754 * Gather attribute uses defined by this type.
12755 */
12756 if (attrs != NULL) {
12757 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
12758 &uses, &lastUse) == -1) {
12759 return (-1);
12760 }
12761 }
12762 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
12763 * "Two distinct attribute declarations in the {attribute uses} must
12764 * not have identical {name}s and {target namespace}s."
12765 *
12766 * For "extension" this is done further down.
12767 */
12768 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
12769 cur = uses;
12770 while (cur != NULL) {
12771 tmp = cur->next;
12772 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012773 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12774 xmlSchemaGetAttrName(tmp->attr))) &&
12775 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12776 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12777
12778 xmlSchemaPAttrUseErr(ctxt,
12779 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12780 NULL, type, NULL, cur->attr,
12781 "Duplicate attribute use %s specified",
12782 xmlSchemaFormatNsUriLocal(&str,
12783 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12784 xmlSchemaGetAttrName(tmp->attr))
12785 );
12786 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012787 break;
12788 }
12789 tmp = tmp->next;
12790 }
12791 cur = cur->next;
12792 }
12793 }
12794 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12795 /*
12796 * Derive by restriction.
12797 */
12798 if (baseIsAnyType) {
12799 type->attributeUses = uses;
12800 } else {
12801 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012802 const xmlChar *bEffValue;
12803 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012804
12805 cur = uses;
12806 while (cur != NULL) {
12807 found = 0;
12808 base = type->attributeUses;
12809 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012810 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12811 xmlSchemaGetAttrName(base->attr)) &&
12812 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
12813 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012814
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012815 found = 1;
12816
Daniel Veillard3646d642004-06-02 19:19:14 +000012817 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12818 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12819 /*
12820 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000012821 */
12822 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012823 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012824 NULL, type, NULL, cur->attr,
12825 "The 'optional' use is inconsistent with a matching "
12826 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012827 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12828 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12829 /*
12830 * derivation-ok-restriction 3
12831 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012832 xmlSchemaPCustomErr(ctxt,
12833 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12834 NULL, type, NULL,
12835 "A matching attribute use for the 'required' "
12836 "attribute use %s of the base type is missing",
12837 xmlSchemaFormatNsUriLocal(&str,
12838 xmlSchemaGetAttrTargetNsURI(base->attr),
12839 xmlSchemaGetAttrName(base->attr)));
12840 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012841 } else {
12842 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012843 * 2.1.3 [Definition:] Let the effective value
12844 * constraint of an attribute use be its {value
12845 * constraint}, if present, otherwise its {attribute
12846 * declaration}'s {value constraint} .
12847 */
12848 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12849 &bEffValue, 0);
12850 /*
12851 * 2.1.3 ... one of the following must be true
12852 *
12853 * 2.1.3.1 B's ·effective value constraint· is
12854 * ·absent· or default.
12855 */
12856 if ((bEffValue != NULL) &&
12857 (effFixed == 1)) {
12858 const xmlChar *rEffValue = NULL;
12859
12860 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12861 &rEffValue, 0);
12862 /*
12863 * 2.1.3.2 R's ·effective value constraint· is
12864 * fixed with the same string as B's.
12865 */
12866 if ((effFixed == 0) ||
12867 (! xmlStrEqual(rEffValue, bEffValue))) {
12868 xmlSchemaPAttrUseErr(ctxt,
12869 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12870 NULL, type, NULL, cur->attr,
12871 "The effective value constraint of the "
12872 "attribute use is inconsistent with "
12873 "its correspondent of the base type",
12874 NULL);
12875 }
12876 }
12877 /*
12878 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
12879 */
12880 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012881 * Override the attribute use.
12882 */
12883 base->attr = cur->attr;
12884 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012885
Daniel Veillard3646d642004-06-02 19:19:14 +000012886 break;
12887 }
12888 base = base->next;
12889 }
12890
12891 if (!found) {
12892 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12893 /*
12894 * derivation-ok-restriction 2.2
12895 */
12896 if ((type->attributeWildcard != NULL) &&
12897 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12898 cur->attr->targetNamespace))
12899 found = 1;
12900
12901 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012902 xmlSchemaPAttrUseErr(ctxt,
12903 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12904 NULL, type, NULL, cur->attr,
12905 "Neither a matching attribute use, "
12906 "nor a matching wildcard in the base type does exist",
12907 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012908 } else {
12909 /*
12910 * Add the attribute use.
12911 *
12912 * Note that this may lead to funny derivation error reports, if
12913 * multiple equal attribute uses exist; but this is not
12914 * allowed anyway, and it will be reported beforehand.
12915 */
12916 tmp = cur;
12917 if (prev != NULL)
12918 prev->next = cur->next;
12919 else
12920 uses = cur->next;
12921 cur = cur->next;
12922 if (type->attributeUses == NULL) {
12923 type->attributeUses = tmp;
12924 } else
12925 lastBaseUse->next = tmp;
12926 lastBaseUse = tmp;
12927
12928 continue;
12929 }
12930 }
12931 }
12932 prev = cur;
12933 cur = cur->next;
12934 }
12935 if (uses != NULL)
12936 xmlSchemaFreeAttributeUseList(uses);
12937 }
12938 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12939 /*
12940 * The spec allows only appending, and not other kinds of extensions.
12941 *
12942 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12943 */
12944 if (uses != NULL) {
12945 if (type->attributeUses == NULL) {
12946 type->attributeUses = uses;
12947 } else
12948 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012949 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012950 } else {
12951 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012952 * Derive implicitely from the ur-type.
12953 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012954 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012955 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012956 /*
12957 * 3.4.6 -> Complex Type Definition Properties Correct
12958 */
12959 if (type->attributeUses != NULL) {
12960 cur = type->attributeUses;
12961 prev = NULL;
12962 while (cur != NULL) {
12963 /*
12964 * 4. Two distinct attribute declarations in the {attribute uses} must
12965 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012966 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012967 * Note that this was already done for "restriction" and types derived from
12968 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012969 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012970 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12971 tmp = cur->next;
12972 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012973 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12974 xmlSchemaGetAttrName(tmp->attr))) &&
12975 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12976 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012977
Daniel Veillardc0826a72004-08-10 14:17:33 +000012978 xmlSchemaPAttrUseErr(ctxt,
12979 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12980 NULL, type, NULL, tmp->attr,
12981 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012982 break;
12983 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012984 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012985 }
12986 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012987 /*
12988 * 5. Two distinct attribute declarations in the {attribute uses} must
12989 * not have {type definition}s which are or are derived from ID.
12990 */
12991 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012992 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012993 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012994 xmlSchemaPAttrUseErr(ctxt,
12995 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12996 NULL, type, NULL, cur->attr,
12997 "There must not exist more than one attribute use, "
12998 "declared of type 'ID' or derived from it",
12999 NULL);
13000 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000013001 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013002 id = cur;
13003 }
13004 /*
13005 * Remove "prohibited" attribute uses. The reason this is done at this late
13006 * stage is to be able to catch dublicate attribute uses. So we had to keep
13007 * prohibited uses in the list as well.
13008 */
13009 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13010 tmp = cur;
13011 if (prev == NULL)
13012 type->attributeUses = cur->next;
13013 else
13014 prev->next = cur->next;
13015 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013016 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013017 } else {
13018 prev = cur;
13019 cur = cur->next;
13020 }
13021 }
13022 }
13023 /*
13024 * TODO: This check should be removed if we are 100% sure of
13025 * the base type attribute uses already being built.
13026 */
13027 if ((baseType != NULL) && (!baseIsAnyType) &&
13028 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013029 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013030 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013031 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013032 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000013033 baseType->name, NULL);
13034 }
13035 return (0);
13036}
13037
13038/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013039 * xmlSchemaTypeFinalContains:
13040 * @schema: the schema
13041 * @type: the type definition
13042 * @final: the final
13043 *
13044 * Evaluates if a type definition contains the given "final".
13045 * This does take "finalDefault" into account as well.
13046 *
13047 * Returns 1 if the type does containt the given "final",
13048 * 0 otherwise.
13049 */
13050static int
13051xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
13052{
13053 int tfinal = final, tflags = type->flags;
13054
13055 if (type == NULL)
13056 return (0);
13057 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
13058 switch (final) {
13059 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
13060 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
13061 break;
13062 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
13063 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
13064 break;
13065 case XML_SCHEMAS_TYPE_FINAL_LIST:
13066 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
13067 break;
13068 case XML_SCHEMAS_TYPE_FINAL_UNION:
13069 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
13070 break;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013071 default:
13072 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013073 }
13074 tflags = schema->flags;
13075 }
13076 if (tflags & tfinal)
13077 return (1);
13078 else
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013079 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013080}
13081
13082/**
13083 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13084 * @type: the Union Simple Type
13085 *
13086 * Returns a list of member types of @type if existing,
13087 * returns NULL otherwise.
13088 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013089static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013090xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13091{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013092 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013093 if (type->memberTypes != NULL)
13094 return (type->memberTypes);
13095 else
13096 type = type->baseType;
13097 }
13098 return (NULL);
13099}
13100
13101/**
13102 * xmlSchemaGetListSimpleTypeItemType:
13103 * @type: the simple type definition
13104 *
13105 * Returns the item type definition of the list simple type.
13106 */
13107static xmlSchemaTypePtr
13108xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
13109{
13110 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
13111 return (NULL);
13112 /*
13113 * Note: In libxml2, the built-in types do not reflect
13114 * the datatype hierarchy (yet?) - we have to treat them
13115 * in a special way.
13116 */
13117 if (type->type == XML_SCHEMA_TYPE_BASIC)
13118 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013119 return (type->subtypes);
13120}
13121
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013122/**
13123 * xmlSchemaGetParticleTotalRangeMin:
13124 * @particle: the particle
13125 *
13126 * Schema Component Constraint: Effective Total Range
13127 * (all and sequence) + (choice)
13128 *
13129 * Returns the minimun Effective Total Range.
13130 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013131static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013132xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013133{
13134 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013135 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013136 return (0);
13137 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013138 int min = -1, cur;
13139 xmlSchemaParticlePtr part =
13140 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013141
13142 if (part == NULL)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013143 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013144 while (part != NULL) {
13145 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13146 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013147 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013148 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013149 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013150 if (cur == 0)
13151 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013152 if ((min > cur) || (min == -1))
13153 min = cur;
13154 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013155 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013156 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013157 } else {
13158 /* <all> and <sequence> */
13159 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013160 xmlSchemaParticlePtr part =
13161 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013162
13163 if (part == NULL)
13164 return (0);
13165 do {
13166 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13167 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013168 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013169 else
13170 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013171 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013172 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013173 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013174 }
13175}
13176
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013177/**
13178 * xmlSchemaGetParticleTotalRangeMax:
13179 * @particle: the particle
13180 *
13181 * Schema Component Constraint: Effective Total Range
13182 * (all and sequence) + (choice)
13183 *
13184 * Returns the maximum Effective Total Range.
13185 */
13186static int
13187xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13188{
13189 if ((particle->children == NULL) ||
13190 (particle->children->children == NULL))
13191 return (0);
13192 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13193 int max = -1, cur;
13194 xmlSchemaParticlePtr part =
13195 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013196
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013197 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13198 if (part->children == NULL)
13199 continue;
13200 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13201 (part->children->type == XML_SCHEMA_TYPE_ANY))
13202 cur = part->maxOccurs;
13203 else
13204 cur = xmlSchemaGetParticleTotalRangeMax(part);
13205 if (cur == UNBOUNDED)
13206 return (UNBOUNDED);
13207 if ((max < cur) || (max == -1))
13208 max = cur;
13209 }
13210 /* TODO: Handle overflows? */
13211 return (particle->maxOccurs * max);
13212 } else {
13213 /* <all> and <sequence> */
13214 int sum = 0, cur;
13215 xmlSchemaParticlePtr part =
13216 (xmlSchemaParticlePtr) particle->children->children;
13217
13218 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13219 if (part->children == NULL)
13220 continue;
13221 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13222 (part->children->type == XML_SCHEMA_TYPE_ANY))
13223 cur = part->maxOccurs;
13224 else
13225 cur = xmlSchemaGetParticleTotalRangeMax(part);
13226 if (cur == UNBOUNDED)
13227 return (UNBOUNDED);
13228 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13229 return (UNBOUNDED);
13230 sum += cur;
13231 }
13232 /* TODO: Handle overflows? */
13233 return (particle->maxOccurs * sum);
13234 }
13235}
13236
13237/**
13238 * xmlSchemaIsParticleEmptiable:
13239 * @particle: the particle
13240 *
13241 * Schema Component Constraint: Particle Emptiable
13242 * Checks whether the given particle is emptiable.
13243 *
13244 * Returns 1 if emptiable, 0 otherwise.
13245 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013246static int
13247xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13248{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013249 /*
13250 * SPEC (1) "Its {min occurs} is 0."
13251 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013252 if ((particle == NULL) || (particle->minOccurs == 0) ||
13253 (particle->children == NULL))
13254 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013255 /*
13256 * SPEC (2) "Its {term} is a group and the minimum part of the
13257 * effective total range of that group, [...] is 0."
13258 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013259 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013260 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013261 return (1);
13262 }
13263 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013264}
13265
13266/**
13267 * xmlSchemaCheckCOSSTDerivedOK:
13268 * @type: the derived simple type definition
13269 * @baseType: the base type definition
13270 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013271 * Schema Component Constraint:
13272 * Type Derivation OK (Simple) (cos-st-derived-OK)
13273 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013274 * Checks wheter @type can be validly
13275 * derived from @baseType.
13276 *
13277 * Returns 0 on success, an positive error code otherwise.
13278 */
13279static int
13280xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
13281 xmlSchemaTypePtr type,
13282 xmlSchemaTypePtr baseType,
13283 int subset)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013284{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013285 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013286 * 1 They are the same type definition.
13287 * TODO: The identy check might have to be more complex than this.
13288 */
13289 if (type == baseType)
13290 return (0);
13291 /*
13292 * 2.1 restriction is not in the subset, or in the {final}
13293 * of its own {base type definition};
13294 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013295 if ((subset & SUBSET_RESTRICTION) ||
Daniel Veillard01fa6152004-06-29 17:04:39 +000013296 (xmlSchemaTypeFinalContains(schema,
13297 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13298 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
13299 }
13300 /* 2.2 */
13301 if (type->baseType == baseType) {
13302 /*
13303 * 2.2.1 D's ·base type definition· is B.
13304 */
13305 return (0);
13306 }
13307 /*
13308 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13309 * and is validly derived from B given the subset, as defined by this
13310 * constraint.
13311 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013312 if ((! IS_ANYTYPE(type->baseType)) &&
13313 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType,
13314 baseType, subset) == 0)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013315 return (0);
13316 }
13317 /*
13318 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
13319 * definition·.
13320 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013321 if (IS_ANY_SIMPLE_TYPE(baseType) &&
13322 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13323 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013324 return (0);
13325 }
13326 /*
13327 * 2.2.4 B's {variety} is union and D is validly derived from a type
13328 * definition in B's {member type definitions} given the subset, as
13329 * defined by this constraint.
13330 *
13331 * NOTE: This seems not to involve built-in types, since there is no
13332 * built-in Union Simple Type.
13333 */
13334 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13335 xmlSchemaTypeLinkPtr cur;
13336
13337 cur = baseType->memberTypes;
13338 while (cur != NULL) {
13339 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
13340 cur->type, subset) == 0)
13341 return (0);
13342 cur = cur->next;
13343 }
13344 }
13345
13346 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13347}
13348
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013349/**
13350 * xmlSchemaCheckTypeDefCircularInternal:
13351 * @pctxt: the schema parser context
13352 * @ctxtType: the type definition
13353 * @ancestor: an ancestor of @ctxtType
13354 *
13355 * Checks st-props-correct (2) + ct-props-correct (3).
13356 * Circular type definitions are not allowed.
13357 *
13358 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13359 * circular, 0 otherwise.
13360 */
13361static int
13362xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13363 xmlSchemaTypePtr ctxtType,
13364 xmlSchemaTypePtr ancestor)
13365{
13366 int ret;
13367
13368 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13369 return (0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013370
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013371 if (ctxtType == ancestor) {
13372 xmlSchemaPCustomErr(pctxt,
13373 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13374 NULL, ctxtType, GET_NODE(ctxtType),
13375 "The definition is circular", NULL);
13376 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13377 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013378 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13379 /*
13380 * Avoid inifinite recursion on circular types not yet checked.
13381 */
13382 return (0);
13383 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013384 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13385 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13386 ancestor->baseType);
13387 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13388 return (ret);
13389}
13390
13391/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013392 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013393 * @item: the complex/simple type definition
13394 * @ctxt: the parser context
13395 * @name: the name
13396 *
13397 * Checks for circular type definitions.
13398 */
13399static void
13400xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
13401 xmlSchemaParserCtxtPtr ctxt,
13402 const xmlChar * name ATTRIBUTE_UNUSED)
13403{
13404 if ((item == NULL) ||
13405 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13406 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13407 return;
13408 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13409
13410}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411
13412/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013413 * xmlSchemaResolveTypeDefs:
13414 * @item: the complex/simple type definition
13415 * @ctxt: the parser context
13416 * @name: the name
13417 *
13418 * Checks for circular type definitions.
13419 */
13420static void
13421xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
13422 xmlSchemaParserCtxtPtr ctxt,
13423 const xmlChar * name ATTRIBUTE_UNUSED)
13424{
13425 if (typeDef == NULL)
13426 return;
13427
13428 if (IS_SIMPLE_TYPE(typeDef)) {
13429 if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13430 /*
13431 * Resolve the memberTypes.
13432 */
13433 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13434 return;
13435 } else if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13436 /*
13437 * Resolve the itemType.
13438 */
13439 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13440 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13441 typeDef->ref, typeDef->refNs);
13442 if ((typeDef->subtypes == NULL) ||
13443 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13444 typeDef->subtypes = NULL;
13445 xmlSchemaPResCompAttrErr(ctxt,
13446 XML_SCHEMAP_SRC_RESOLVE,
13447 NULL, typeDef, typeDef->node,
13448 "itemType", typeDef->ref, typeDef->refNs,
13449 XML_SCHEMA_TYPE_SIMPLE, NULL);
13450 }
13451 }
13452 return;
13453 }
13454 }
13455 /*
13456 * Resolve the base type.
13457 */
13458 if (typeDef->baseType == NULL) {
13459 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13460 typeDef->base, typeDef->baseNs);
13461 if (typeDef->baseType == NULL) {
13462 xmlSchemaPResCompAttrErr(ctxt,
13463 XML_SCHEMAP_SRC_RESOLVE,
13464 NULL, typeDef, typeDef->node,
13465 "base", typeDef->base, typeDef->baseNs,
13466 XML_SCHEMA_TYPE_SIMPLE, NULL);
13467 return;
13468 }
13469 }
13470}
13471
13472
13473
13474/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013475 * xmlSchemaCheckSTPropsCorrect:
13476 * @ctxt: the schema parser context
13477 * @type: the simple type definition
13478 *
13479 * Checks st-props-correct.
13480 *
13481 * Returns 0 if the properties are correct,
13482 * if not, a positive error code and -1 on internal
13483 * errors.
13484 */
13485static int
13486xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13487 xmlSchemaTypePtr type)
13488{
13489 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13490 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013491 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013492
Daniel Veillardc0826a72004-08-10 14:17:33 +000013493 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013494 /*
13495 * Schema Component Constraint: Simple Type Definition Properties Correct
13496 *
13497 * NOTE: This is somehow redundant, since we actually built a simple type
13498 * to have all the needed information; this acts as an self test.
13499 */
13500 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13501 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013502 /* Base type: If the datatype has been ·derived· by ·restriction·
13503 * then the Simple Type Definition component from which it is ·derived·,
13504 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
13505 */
13506 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013507 /*
13508 * TODO: Think about: "modulo the impact of Missing
13509 * Sub-components (§5.3)."
13510 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013511 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013512 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013513 NULL, type, NULL,
13514 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013516
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013518 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013519 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013521 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013522 "The base type '%s' is not a simple type",
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 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013527 if ((baseType->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
13528 ((type->flags &
13529 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13530 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13531 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013532 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013534 NULL, type, NULL,
13535 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013536 "the simple ur-type definition as base type, not '%s'",
13537 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013538 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013539 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13540 }
13541 /*
13542 * Variety: One of {atomic, list, union}.
13543 */
13544 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13545 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
13546 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013547 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013549 NULL, type, NULL,
13550 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013551 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13552 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013553 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013554
13555 /*
13556 * 3 The {final} of the {base type definition} must not contain restriction.
13557 */
13558 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
13559 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13560 xmlSchemaPCustomErr(ctxt,
13561 XML_SCHEMAP_ST_PROPS_CORRECT_3,
13562 NULL, type, NULL,
13563 "The 'final' of its base type '%s' must not contain "
13564 "'restriction'",
13565 xmlSchemaGetComponentQName(&str, baseType));
13566 FREE_AND_NULL(str)
13567 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
13568 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013569
13570 /*
13571 * 2 All simple type definitions must be derived ultimately from the ·simple
13572 * ur-type definition (so· circular definitions are disallowed). That is, it
13573 * must be possible to reach a built-in primitive datatype or the ·simple
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013574 * ur-type definition· by repeatedly following the {base type definition}.
13575 *
13576 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013578 return (0);
13579}
13580
13581/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013582 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 * @ctxt: the schema parser context
13584 * @type: the simple type definition
13585 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013586 * Schema Component Constraint:
13587 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13588
13589 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013590 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 *
13592 * Returns -1 on internal errors, 0 if the type is validly derived,
13593 * a positive error code otherwise.
13594 */
13595static int
13596xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013597 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013598{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013599 xmlChar *str = NULL;
13600
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
13602 xmlSchemaPErr(ctxt, type->node,
13603 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013604 "xmlSchemaCheckCOSSTRestricts: The given "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013605 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013606 type->name, NULL);
13607 return (-1);
13608 }
13609
13610 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13611 xmlSchemaTypePtr primitive;
13612 /*
13613 * 1.1 The {base type definition} must be an atomic simple
13614 * type definition or a built-in primitive datatype.
13615 */
13616 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013617 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013618 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013619 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013620 "The base type '%s' is not an atomic simple type",
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_1);
13624 }
13625 /* 1.2 The {final} of the {base type definition} must not contain
13626 * restriction.
13627 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013628 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13630 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013631 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013632 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013633 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013634 "The final of its base type '%s' must not contain 'restriction'",
13635 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013636 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013637 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13638 }
13639
13640 /*
13641 * 1.3.1 DF must be an allowed constraining facet for the {primitive
13642 * type definition}, as specified in the appropriate subsection of 3.2
13643 * Primitive datatypes.
13644 */
13645 if (type->facets != NULL) {
13646 xmlSchemaFacetPtr facet;
13647 int ok = 1;
13648
13649 primitive = xmlSchemaGetPrimitiveType(type);
13650 if (primitive == NULL) {
13651 xmlSchemaPErr(ctxt, type->node,
13652 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013653 "xmlSchemaCheckCOSSTRestricts: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013654 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013655 type->name, NULL);
13656 return (-1);
13657 }
13658 facet = type->facets;
13659 do {
13660 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013661 ok = 0;
13662 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013663 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013664 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 }
13666 facet = facet->next;
13667 } while (facet != NULL);
13668 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013669 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013670 }
13671 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013672 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13673 * of the {base type definition} (call this BF),then the DF's {value}
13674 * must be a valid restriction of BF's {value} as defined in
13675 * [XML Schemas: Datatypes]."
13676 *
13677 * NOTE (1.3.2) Facet derivation constraints are currently handled in
13678 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013679 */
13680 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13681 xmlSchemaTypePtr itemType = NULL;
13682
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013683 itemType = type->subtypes;
13684 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013685 xmlSchemaPErr(ctxt, type->node,
13686 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013687 "Internal error: xmlSchemaCheckCOSSTRestricts: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013688 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 type->name, NULL);
13690 return (-1);
13691 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013692 if (IS_NOT_TYPEFIXED(itemType))
13693 xmlSchemaTypeFixup(itemType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 /*
13695 * 2.1 The {item type definition} must have a {variety} of atomic or
13696 * union (in which case all the {member type definitions}
13697 * must be atomic).
13698 */
13699 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13700 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 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,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013704 "The item type '%s' does not have a variety of atomic or union",
13705 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013706 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013707 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13708 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13709 xmlSchemaTypeLinkPtr member;
13710
13711 member = itemType->memberTypes;
13712 while (member != NULL) {
13713 if ((member->type->flags &
13714 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013715 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013717 NULL, type, NULL,
13718 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013719 "member type '%s' of this item type is not atomic",
13720 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013721 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013722 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13723 }
13724 member = member->next;
13725 }
13726 }
13727
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013728 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013729 xmlSchemaFacetPtr facet;
13730 /*
13731 * This is the case if we have: <simpleType><list ..
13732 */
13733 /*
13734 * 2.3.1
13735 * 2.3.1.1 The {final} of the {item type definition} must not
13736 * contain list.
13737 */
13738 if (xmlSchemaTypeFinalContains(ctxt->schema,
13739 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013740 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013742 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013743 "The final of its item type '%s' must not contain 'list'",
13744 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013745 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013746 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13747 }
13748 /*
13749 * 2.3.1.2 The {facets} must only contain the whiteSpace
13750 * facet component.
13751 */
13752 if (type->facets != NULL) {
13753 facet = type->facets;
13754 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013755 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13756 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013757 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013758 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13760 }
13761 facet = facet->next;
13762 } while (facet != NULL);
13763 }
13764 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013765 * MABY TODO: (Hmm, not really) Datatypes states:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13767 * whose ·lexical space· allows space (such as string or anyURI)or
13768 * a ·union· datatype any of whose {member type definitions}'s
13769 * ·lexical space· allows space.
13770 */
13771 } else {
13772 /*
13773 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013774 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013775 */
13776 /*
13777 * 2.3.2
13778 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13779 */
13780 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
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_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013783 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013784 "The base type '%s' must be a list type",
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_1);
13788 }
13789 /*
13790 * 2.3.2.2 The {final} of the {base type definition} must not
13791 * contain restriction.
13792 */
13793 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13794 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013795 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013797 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013798 "The 'final' of the base type '%s' must not contain 'restriction'",
13799 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013800 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13802 }
13803 /*
13804 * 2.3.2.3 The {item type definition} must be validly derived
13805 * from the {base type definition}'s {item type definition} given
13806 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13807 */
13808 {
13809 xmlSchemaTypePtr baseItemType;
13810
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013811 baseItemType = type->baseType->subtypes;
13812 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013813 xmlSchemaPErr(ctxt, type->node,
13814 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013815 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013816 "List simple type '%s': Failed to "
13817 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 type->name, type->baseType->name);
13819 return (-1);
13820 }
13821 if ((itemType != baseItemType) &&
13822 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
13823 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013824 xmlChar *strBIT = NULL, *strBT = NULL;
13825 xmlSchemaPCustomErrExt(ctxt,
13826 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
13827 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013828 "The item type '%s' is not validly derived from the "
13829 "item type '%s' of the base type '%s'",
13830 xmlSchemaGetComponentQName(&str, itemType),
13831 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13832 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013833
13834 FREE_AND_NULL(str)
13835 FREE_AND_NULL(strBIT)
13836 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013837 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13838 }
13839 }
13840
13841 if (type->facets != NULL) {
13842 xmlSchemaFacetPtr facet;
13843 int ok = 1;
13844 /*
13845 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
13846 * and enumeration facet components are allowed among the {facets}.
13847 */
13848 facet = type->facets;
13849 do {
13850 switch (facet->type) {
13851 case XML_SCHEMA_FACET_LENGTH:
13852 case XML_SCHEMA_FACET_MINLENGTH:
13853 case XML_SCHEMA_FACET_MAXLENGTH:
13854 case XML_SCHEMA_FACET_WHITESPACE:
13855 /*
13856 * TODO: 2.5.1.2 List datatypes
13857 * The value of ·whiteSpace· is fixed to the value collapse.
13858 */
13859 case XML_SCHEMA_FACET_PATTERN:
13860 case XML_SCHEMA_FACET_ENUMERATION:
13861 break;
13862 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013863 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013865 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013866 /*
13867 * We could return, but it's nicer to report all
13868 * invalid facets.
13869 */
13870 ok = 0;
13871 }
13872 }
13873 facet = facet->next;
13874 } while (facet != NULL);
13875 if (ok == 0)
13876 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13877 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013878 * SPEC (2.3.2.5) (same as 1.3.2)
13879 *
13880 * NOTE (2.3.2.5) This is currently done in
13881 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013882 */
13883 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013884 }
13885 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13886 /*
13887 * 3.1 The {member type definitions} must all have {variety} of
13888 * atomic or list.
13889 */
13890 xmlSchemaTypeLinkPtr member;
13891
13892 member = type->memberTypes;
13893 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013894 if (IS_NOT_TYPEFIXED(member->type))
13895 xmlSchemaTypeFixup(member->type, ctxt, NULL);
13896
Daniel Veillard01fa6152004-06-29 17:04:39 +000013897 if (((member->type->flags &
13898 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13899 ((member->type->flags &
13900 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013901 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013903 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013904 "The member type '%s' is neither an atomic, nor a list type",
13905 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013906 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013907 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13908 }
13909 member = member->next;
13910 }
13911 /*
13912 * 3.3.1 If the {base type definition} is the ·simple ur-type
13913 * definition·
13914 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013915 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 /*
13917 * 3.3.1.1 All of the {member type definitions} must have a
13918 * {final} which does not contain union.
13919 */
13920 member = type->memberTypes;
13921 while (member != NULL) {
13922 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
13923 XML_SCHEMAS_TYPE_FINAL_UNION)) {
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,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013926 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013927 "The 'final' of member type '%s' contains 'union'",
13928 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013929 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013930 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13931 }
13932 member = member->next;
13933 }
13934 /*
13935 * 3.3.1.2 The {facets} must be empty.
13936 */
13937 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013938 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013939 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013940 NULL, type, NULL,
13941 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013942 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13943 }
13944 } else {
13945 /*
13946 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013947 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013948 */
13949 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013950 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013951 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013952 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013953 "The base type '%s' is not a union type",
13954 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013955 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013956 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13957 }
13958 /*
13959 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13960 */
13961 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13962 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013963 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013965 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013966 "The 'final' of its base type '%s' must not contain 'restriction'",
13967 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013968 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013969 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13970 }
13971 /*
13972 * 3.3.2.3 The {member type definitions}, in order, must be validly
13973 * derived from the corresponding type definitions in the {base
13974 * type definition}'s {member type definitions} given the empty set,
13975 * as defined in Type Derivation OK (Simple) (§3.14.6).
13976 */
13977 {
13978 xmlSchemaTypeLinkPtr baseMember;
13979
13980 /*
13981 * OPTIMIZE: if the type is restricting, it has no local defined
13982 * member types and inherits the member types of the base type;
13983 * thus a check for equality can be skipped.
13984 */
13985 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013986 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000013987 * union simple type can have other member types as the member
13988 * types of it's base type. This check seems not necessary with
13989 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013990 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013991 */
13992 if (type->memberTypes != NULL) {
13993 member = type->memberTypes;
13994 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
13995 if ((member == NULL) && (baseMember != NULL)) {
13996 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013997 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013998 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013999 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014000 "of member types in the base type\n",
14001 type->name, NULL);
14002 }
14003 while (member != NULL) {
14004 if (baseMember == NULL) {
14005 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014006 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 "Internal error: "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014008 "xmlSchemaCheckCOSSTRestricts "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014009 "(3.3.2.3), union simple type '%s', unequal number "
14010 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 type->name, NULL);
14012 }
14013 if ((member->type != baseMember->type) &&
14014 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
14015 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014016 xmlChar *strBMT = NULL, *strBT = NULL;
14017
14018 xmlSchemaPCustomErrExt(ctxt,
14019 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
14020 NULL, type, NULL,
14021 "The member type %s is not validly derived from its "
14022 "corresponding member type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014023 xmlSchemaGetComponentQName(&str, member->type),
14024 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
14025 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014026 FREE_AND_NULL(str)
14027 FREE_AND_NULL(strBMT)
14028 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
14030 }
14031 member = member->next;
14032 baseMember = baseMember->next;
14033 }
14034 }
14035 }
14036 /*
14037 * 3.3.2.4 Only pattern and enumeration facet components are
14038 * allowed among the {facets}.
14039 */
14040 if (type->facets != NULL) {
14041 xmlSchemaFacetPtr facet;
14042 int ok = 1;
14043
14044 facet = type->facets;
14045 do {
14046 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
14047 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014048 xmlSchemaPIllegalFacetListUnionErr(ctxt,
14049 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
14050 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014051 ok = 0;
14052 }
14053 facet = facet->next;
14054 } while (facet != NULL);
14055 if (ok == 0)
14056 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
14057
14058 }
14059 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014060 * SPEC (3.3.2.5) (same as 1.3.2)
14061 *
14062 * NOTE (3.3.2.5) This is currently done in
14063 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014064 */
14065 }
14066 }
14067
14068 return (0);
14069}
14070
14071/**
14072 * xmlSchemaCheckSRCSimpleType:
14073 * @ctxt: the schema parser context
14074 * @type: the simple type definition
14075 *
14076 * Checks crc-simple-type constraints.
14077 *
14078 * Returns 0 if the constraints are satisfied,
14079 * if not a positive error code and -1 on internal
14080 * errors.
14081 */
14082static int
14083xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14084 xmlSchemaTypePtr type)
14085{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014086 /*
14087 * src-simple-type.1 The corresponding simple type definition, if any,
14088 * must satisfy the conditions set out in Constraints on Simple Type
14089 * Definition Schema Components (§3.14.6).
14090 */
14091 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
14092 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14093 /*
14094 * TODO: Removed this, since it got annoying to get an
14095 * extra error report, if anything failed until now.
14096 * Enable this if needed.
14097 */
14098 /*
14099 xmlSchemaPErr(ctxt, type->node,
14100 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014101 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014102 "on simple type definitions.\n",
14103 type->name, NULL);
14104 */
14105 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14106 }
14107
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014108 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014109 /*
14110 * src-simple-type.2 If the <restriction> alternative is chosen,
14111 * either it must have a base [attribute] or a <simpleType> among its
14112 * [children], but not both.
14113 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014114 /*
14115 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014116 * NOTE: This is checked in the parse function of <restriction>.
William M. Brack2f2a6632004-08-20 23:09:47 +000014117 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014118 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014119 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14120 * an itemType [attribute] or a <simpleType> among its [children],
14121 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014122 *
14123 * REMOVED: This is checked in the parse function of <list>.
14124 */
14125 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014126 xmlSchemaTypeLinkPtr member;
14127 xmlSchemaTypePtr ancestor, anySimpleType;
14128
14129 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14130
14131 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14132 * the <union> alternative is chosen, there must not be any entries
14133 * in the memberTypes [attribute] at any depth which resolve to the
14134 * component corresponding to the <simpleType>.
14135 */
14136 member = type->memberTypes;
14137 while (member != NULL) {
14138 ancestor = member->type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014139 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
14140 if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014141 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014142 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014143 NULL, type, NULL,
14144 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014145 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014146 }
14147 if (IS_NOT_TYPEFIXED(ancestor))
14148 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
14149 if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014150 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014151 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000014152 * type as item type, which in turn has a list ST as member
14153 * type, we will assume this here as well, since this check
14154 * was not yet performed.
14155 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014156 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014157
Daniel Veillard01fa6152004-06-29 17:04:39 +000014158 ancestor = ancestor->baseType;
14159 }
14160 member = member->next;
14161 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014162 }
14163
14164 return (0);
14165}
14166
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014167#if 0 /* Not yet used code for ST schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000014168static int
14169xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
14170 const xmlChar * value,
14171 xmlSchemaTypePtr type,
14172 int fireErrors)
14173{
14174 int ret;
14175 /*
14176 * 3.14.4 Simple Type Definition Validation Rules
14177 * Validation Rule: String Valid
14178 */
14179 /*
14180 * 1 It is schema-valid with respect to that definition as defined
14181 * by Datatype Valid in [XML Schemas: Datatypes].
14182 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014183 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14184 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000014185 return (ret);
14186 /*
14187 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
14188 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
14189 * the string must be a ·declared entity name·.
14190 */
14191 /*
14192 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
14193 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
14194 * then every whitespace-delimited substring of the string must be a ·declared
14195 * entity name·.
14196 */
14197 /*
14198 * 2.3 otherwise no further condition applies.
14199 */
14200
14201 return (0);
14202}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014203#endif
14204
William M. Brack2f2a6632004-08-20 23:09:47 +000014205
14206static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014207xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
14208{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000014209 if (vctxt->pctxt == NULL) {
14210 if (vctxt->schema != NULL)
14211 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
14212 else
14213 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014214 if (vctxt->pctxt == NULL) {
14215 xmlSchemaVErr(vctxt, NULL,
14216 XML_SCHEMAV_INTERNAL,
14217 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14218 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000014219 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014220 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014221 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014222 /* TODO: Pass user data. */
14223 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
14224 }
14225 return (0);
14226}
14227
14228static int
14229xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14230{
14231 if (ctxt->vctxt == NULL) {
14232 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14233 if (ctxt->vctxt == NULL) {
14234 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014235 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014236 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14237 "failed to create a temp. validation context.\n",
14238 NULL, NULL);
14239 return (-1);
14240 }
14241 /* TODO: Pass user data. */
14242 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
14243 }
14244 return (0);
14245}
14246
14247/**
14248 * xmlSchemaCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014249 * @pctxt: the schema parser context
14250 * @vctxt: the temporary schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014251 * @type: the simple type definition
14252 * @value: the default value
14253 * @node: an optional node (the holder of the value)
14254 *
14255 * Checks the "cos-valid-default" constraints.
14256 *
14257 * Returns 0 if the constraints are satisfied,
14258 * if not, a positive error code and -1 on internal
14259 * errors.
14260 */
14261static int
14262xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14263 xmlSchemaValidCtxtPtr vctxt,
14264 xmlSchemaTypePtr type,
14265 const xmlChar *value,
14266 xmlNodePtr node)
14267{
14268 int ret = 0;
14269
14270 /*
14271 * cos-valid-default:
14272 * Schema Component Constraint: Element Default Valid (Immediate)
14273 * For a string to be a valid default with respect to a type
14274 * definition the appropriate case among the following must be true:
14275 */
14276 /*
14277 * NOTE: This has to work without a given node (the holder of the
14278 * value), since it should work on the component, i.e. an underlying
14279 * DOM must not be mandatory.
14280 */
14281 if ((pctxt == NULL) || (vctxt == NULL)) {
14282 xmlSchemaPErr(pctxt, node,
14283 XML_SCHEMAP_INTERNAL,
14284 "Internal error: xmlSchemaCheckCOSValidDefault, "
14285 "bad arguments: the parser and/or validation context is "
14286 "missing.\n",
14287 NULL, NULL);
14288 return (-1);
14289 }
14290 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014291 /*
14292 * Complex type.
14293 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014294 * SPEC (2.1) "its {content type} must be a simple type definition
14295 * or mixed."
14296 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
14297 * type}'s particle must be ·emptiable· as defined by
14298 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014299 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014300 if ((! HAS_SIMPLE_CONTENT(type)) &&
14301 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14302 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014303 xmlSchemaPSimpleTypeErr(pctxt,
14304 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
14305 NULL, NULL, node,
14306 type, NULL, NULL,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014307 "For a string to be a valid default, the type definition "
14308 "must be a simple type or a complex type with mixed content "
14309 "and a particle emptiable",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014310 NULL, NULL);
14311 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14312 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014313 }
14314 /*
14315 * 1 If the type definition is a simple type definition, then the string
14316 * must be ·valid· with respect to that definition as defined by String
14317 * Valid (§3.14.4).
14318 *
14319 * AND
14320 *
14321 * 2.2.1 If the {content type} is a simple type definition, then the
14322 * string must be ·valid· with respect to that simple type definition
14323 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014324 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014325 vctxt->node = node;
14326 vctxt->cur = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014327 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014328 if (IS_SIMPLE_TYPE(type))
14329 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value,
14330 1, 1, 1, 0);
14331 else if (HAS_SIMPLE_CONTENT(type))
14332 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type->contentTypeDef,
14333 value, 1, 1, 1, 0);
14334 else
14335 return (ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014336 if (ret != 0) {
14337 pctxt->err = vctxt->err;
14338 pctxt->nberrors++;
14339 }
14340
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014341 if (ret < 0) {
14342 xmlSchemaPErr(pctxt, node,
14343 /* NOTNICE: error code: This function will be used during
14344 * schema construction and xsi:type validation.
14345 */
14346 XML_SCHEMAP_INTERNAL,
14347 "Internal error: xmlSchemaCheckCOSValidDefault, "
14348 "while validating a value constaint value.\n",
14349 NULL, NULL);
14350
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014351 }
14352
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014353 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014354}
14355
14356/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014357 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014358 * @ctxt: the schema parser context
14359 * @type: the complex type definition
14360 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014361 *.(4.6) Constraints on Complex Type Definition Schema Components
14362 * Schema Component Constraint:
14363 * Complex Type Definition Properties Correct (ct-props-correct)
14364 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014365 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014366 * Returns 0 if the constraints are satisfied, a positive
14367 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014368 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014369static int
14370xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14371 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014372{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014373 /*
14374 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14375 *
14376 * SPEC (1) "The values of the properties of a complex type definition must
14377 * be as described in the property tableau in The Complex Type Definition
14378 * Schema Component (§3.4.1), modulo the impact of Missing
14379 * Sub-components (§5.3)."
14380 */
14381 if ((type->baseType != NULL) &&
14382 (IS_SIMPLE_TYPE(type->baseType)) &&
14383 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14384 /*
14385 * SPEC (2) "If the {base type definition} is a simple type definition,
14386 * the {derivation method} must be extension."
14387 */
14388 xmlSchemaPCustomErr(pctxt,
14389 XML_SCHEMAP_SRC_CT_1,
14390 NULL, type, NULL,
14391 "If the base type is a simple type, the derivation method must be "
14392 "'extension'", NULL);
14393 return (XML_SCHEMAP_SRC_CT_1);
14394 }
14395 /*
14396 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14397 * definition·. That is, it must be possible to reach the ·ur-type
14398 * definition by repeatedly following the {base type definition}."
14399 *
14400 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14401 *
14402 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
14403 * must not have identical {name}s and {target namespace}s."
14404 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14405 * must not have {type definition}s which are or are derived from ID."
14406 *
14407 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14408 */
14409 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014410}
14411
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014412static int
14413xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14414 xmlSchemaTypePtr typeB)
14415{
14416 /*
14417 * TODO: This should implement component-identity
14418 * in the future.
14419 */
14420 if ((typeA == NULL) || (typeB == NULL))
14421 return (0);
14422 return (typeA == typeB);
14423}
14424
14425/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014426 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014427 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014428 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014429 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014430 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014431 *
14432 * Schema Component Constraint:
14433 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14434 *
14435 * STATUS: completed
14436 *
14437 * Returns 0 if the constraints are satisfied, or 1
14438 * if not.
14439 */
14440static int
14441xmlSchemaCheckCOSCTDerivedOK(xmlSchemaPtr schema,
14442 xmlSchemaTypePtr type,
14443 xmlSchemaTypePtr baseType,
14444 int set)
14445{
14446 int equal = xmlSchemaAreEqualTypes(type, baseType);
14447 /* TODO: Error codes. */
14448 /*
14449 * SPEC "For a complex type definition (call it D, for derived)
14450 * to be validly derived from a type definition (call this
14451 * B, for base) given a subset of {extension, restriction}
14452 * all of the following must be true:"
14453 */
14454 if (! equal) {
14455 /*
14456 * SPEC (1) "If B and D are not the same type definition, then the
14457 * {derivation method} of D must not be in the subset."
14458 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014459 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014460 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014461 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014462 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014463 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014464 } else {
14465 /*
14466 * SPEC (2.1) "B and D must be the same type definition."
14467 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014468 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014469 }
14470 /*
14471 * SPEC (2.2) "B must be D's {base type definition}."
14472 */
14473 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014474 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014475 /*
14476 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14477 * definition·."
14478 */
14479 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014480 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014481
14482 if (IS_COMPLEX_TYPE(type->baseType)) {
14483 /*
14484 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14485 * must be validly derived from B given the subset as defined by this
14486 * constraint."
14487 */
14488 return (xmlSchemaCheckCOSCTDerivedOK(schema, type->baseType,
14489 baseType, set));
14490 } else {
14491 /*
14492 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14493 * must be validly derived from B given the subset as defined in Type
14494 * Derivation OK (Simple) (§3.14.6).
14495 */
14496 return (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType,
14497 set));
14498 }
14499}
14500
14501/**
14502 * xmlSchemaCheckCOSDerivedOK:
14503 * @type: the derived simple type definition
14504 * @baseType: the base type definition
14505 *
14506 * Calls:
14507 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
14508 *
14509 * Checks wheter @type can be validly derived from @baseType.
14510 *
14511 * Returns 0 on success, an positive error code otherwise.
14512 */
14513static int
14514xmlSchemaCheckCOSDerivedOK(xmlSchemaPtr schema,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014515 xmlSchemaTypePtr type,
14516 xmlSchemaTypePtr baseType,
14517 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014518{
14519 if (IS_SIMPLE_TYPE(type))
14520 return (xmlSchemaCheckCOSSTDerivedOK(schema, type, baseType, set));
14521 else
14522 return (xmlSchemaCheckCOSCTDerivedOK(schema, type, baseType, set));
14523}
14524
William M. Brack2f2a6632004-08-20 23:09:47 +000014525/**
14526 * xmlSchemaCheckCOSCTExtends:
14527 * @ctxt: the schema parser context
14528 * @type: the complex type definition
14529 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014530 * (3.4.6) Constraints on Complex Type Definition Schema Components
14531 * Schema Component Constraint:
14532 * Derivation Valid (Extension) (cos-ct-extends)
14533 *
14534 * STATUS:
14535 * missing:
14536 * (1.5)
14537 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014538 *
14539 * Returns 0 if the constraints are satisfied, a positive
14540 * error code if not and -1 if an internal error occured.
14541 */
14542static int
14543xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14544 xmlSchemaTypePtr type)
14545{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014546 xmlSchemaTypePtr base = type->baseType;
14547 /*
14548 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14549 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014550 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014551 /*
14552 * SPEC (1) "If the {base type definition} is a complex type definition,
14553 * then all of the following must be true:"
14554 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014555 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14556 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014557 * SPEC (1.1) "The {final} of the {base type definition} must not
14558 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014559 */
14560 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14561 xmlSchemaPCustomErr(ctxt,
14562 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14563 NULL, type, NULL,
14564 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014565 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014566 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14567 }
14568 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014569 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
14570 * uses}
William M. Brack2f2a6632004-08-20 23:09:47 +000014571 * of the complex type definition itself, that is, for every attribute
14572 * use in the {attribute uses} of the {base type definition}, there
14573 * must be an attribute use in the {attribute uses} of the complex
14574 * type definition itself whose {attribute declaration} has the same
14575 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014576 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014577 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014578 * NOTE (1.2): This will be already satisfied by the way the attribute
14579 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14580 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014581 */
14582
14583 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014584 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14585 * definition must also have one, and the base type definition's
14586 * {attribute wildcard}'s {namespace constraint} must be a subset
14587 * of the complex type definition's {attribute wildcard}'s {namespace
14588 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014589 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014590 * NOTE (1.3) This is already checked in
14591 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014592 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014593 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014594 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014595 if ((type->contentTypeDef != NULL) &&
14596 (type->contentTypeDef == base->contentTypeDef)) {
14597 /*
14598 * SPEC (1.4.1) "The {content type} of the {base type definition}
14599 * and the {content type} of the complex type definition itself
14600 * must be the same simple type definition"
14601 * PASS
14602 */
14603 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14604 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14605 /*
14606 * SPEC (1.4.2) "The {content type} of both the {base type
14607 * definition} and the complex type definition itself must
14608 * be empty."
14609 * PASS
14610 */
14611 } else {
14612 /*
14613 * SPEC (1.4.3) "All of the following must be true:"
14614 */
14615 if (type->subtypes == NULL) {
14616 /*
14617 * SPEC 1.4.3.1 The {content type} of the complex type
14618 * definition itself must specify a particle.
14619 */
14620 xmlSchemaPCustomErr(ctxt,
14621 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14622 NULL, type, NULL,
14623 "The content type must specify a particle", NULL);
14624 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14625 }
14626 /*
14627 * SPEC (1.4.3.2) "One of the following must be true:"
14628 */
14629 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14630 /*
14631 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14632 * definition} must be empty.
14633 * PASS
14634 */
14635 } else {
14636 /*
14637 * SPEC (1.4.3.2.2) "All of the following must be true:"
14638 */
14639 if ((type->contentType != base->contentType) ||
14640 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14641 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14642 /*
14643 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14644 * or both must be element-only."
14645 */
14646 xmlSchemaPCustomErr(ctxt,
14647 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14648 NULL, type, NULL,
14649 "The content type of both, the type and its base "
14650 "type, must either 'mixed' or 'element-only'", NULL);
14651 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14652 }
14653 /*
14654 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14655 * complex type definition must be a ·valid extension·
14656 * of the {base type definition}'s particle, as defined
14657 * in Particle Valid (Extension) (§3.9.6)."
14658 *
14659 * NOTE that we won't check "Particle Valid (Extension)",
14660 * since it is ensured by the derivation process in
14661 * xmlSchemaTypeFixup(). We need to implement this when heading
14662 * for a construction API
14663 */
14664 }
14665 /*
14666 * TODO (1.5)
14667 */
14668 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014669 } else {
14670 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014671 * SPEC (2) "If the {base type definition} is a simple type definition,
14672 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014673 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014674 if (type->contentTypeDef != base) {
14675 /*
14676 * SPEC (2.1) "The {content type} must be the same simple type
14677 * definition."
14678 */
14679 xmlSchemaPCustomErr(ctxt,
14680 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14681 NULL, type, NULL,
14682 "The content type must be the simple base type", NULL);
14683 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14684 }
14685 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14686 /*
14687 * SPEC (2.2) "The {final} of the {base type definition} must not
14688 * contain extension"
14689 * NOTE that this is the same as (1.1).
14690 */
14691 xmlSchemaPCustomErr(ctxt,
14692 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14693 NULL, type, NULL,
14694 "The 'final' of the base type definition "
14695 "contains 'extension'", NULL);
14696 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14697 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014698 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014699 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014700}
14701
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014702/**
14703 * xmlSchemaCheckDerivationOKRestriction:
14704 * @ctxt: the schema parser context
14705 * @type: the complex type definition
14706 *
14707 * (3.4.6) Constraints on Complex Type Definition Schema Components
14708 * Schema Component Constraint:
14709 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14710 *
14711 * STATUS:
14712 * missing:
14713 * (5.4.2), (5.2.2.1)
14714 *
14715 * Returns 0 if the constraints are satisfied, a positive
14716 * error code if not and -1 if an internal error occured.
14717 */
14718static int
14719xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14720 xmlSchemaTypePtr type)
14721{
14722 xmlSchemaTypePtr base;
14723
14724 /*
14725 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14726 * temporarily only.
14727 */
14728 base = type->baseType;
14729 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14730 /*
14731 * SPEC (1) "The {base type definition} must be a complex type
14732 * definition whose {final} does not contain restriction."
14733 */
14734 xmlSchemaPCustomErr(ctxt,
14735 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14736 NULL, type, NULL,
14737 "The 'final' of the base type definition "
14738 "contains 'restriction'", NULL);
14739 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14740 }
14741 /*
14742 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14743 *
14744 * SPEC (5) "One of the following must be true:"
14745 */
14746 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14747 /*
14748 * SPEC (5.1) "The {base type definition} must be the
14749 * ·ur-type definition·."
14750 * PASS
14751 */
14752 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14753 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14754 /*
14755 * SPEC (5.2.1) "The {content type} of the complex type definition
14756 * must be a simple type definition"
14757 *
14758 * SPEC (5.2.2) "One of the following must be true:"
14759 */
14760 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14761 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14762 /*
14763 * SPEC (5.2.2.1) "The {content type} of the {base type
14764 * definition} must be a simple type definition from which
14765 * the {content type} is validly derived given the empty
14766 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14767 * URGENT TODO
14768 */
14769 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14770 (xmlSchemaIsParticleEmptiable(
14771 (xmlSchemaParticlePtr) base->subtypes))) {
14772 /*
14773 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14774 * and have a particle which is ·emptiable· as defined in
14775 * Particle Emptiable (§3.9.6)."
14776 * PASS
14777 */
14778 } else {
14779 xmlSchemaPCustomErr(ctxt,
14780 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14781 NULL, type, NULL,
14782 "The content type of the base type must be either "
14783 "a simple type or 'mixed' and an emptiable particle", NULL);
14784 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14785 }
14786 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14787 /*
14788 * SPEC (5.3.1) "The {content type} of the complex type itself must
14789 * be empty"
14790 */
14791 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14792 /*
14793 * SPEC (5.3.2.1) "The {content type} of the {base type
14794 * definition} must also be empty."
14795 * PASS
14796 */
14797 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14798 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14799 xmlSchemaIsParticleEmptiable(
14800 (xmlSchemaParticlePtr) base->subtypes)) {
14801 /*
14802 * SPEC (5.3.2.2) "The {content type} of the {base type
14803 * definition} must be elementOnly or mixed and have a particle
14804 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14805 * PASS
14806 */
14807 } else {
14808 xmlSchemaPCustomErr(ctxt,
14809 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14810 NULL, type, NULL,
14811 "The content type of the base type must be either "
14812 "empty or 'mixed' (or 'elements-only') and an emptiable "
14813 "particle", NULL);
14814 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14815 }
14816 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14817 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14818 (base->contentType == XML_SCHEMA_CONTENT_MIXED))) {
14819 /*
14820 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14821 * itself must be element-only"
14822 * SPEC (5.4.1.2) "The {content type} of the complex type definition
14823 * itself and of the {base type definition} must be mixed"
14824 */
14825 /*
14826 * SPEC (5.4.2) "The particle of the complex type definition itself
14827 * must be a ·valid restriction· of the particle of the {content
14828 * type} of the {base type definition} as defined in Particle Valid
14829 * (Restriction) (§3.9.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014830 * URGENT TODO: (5.4.2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014831 */
14832 } else {
14833 xmlSchemaPCustomErr(ctxt,
14834 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14835 NULL, type, NULL,
14836 "The type is not a valid restriction of its base type", NULL);
14837 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14838 }
14839 return (0);
14840}
14841
14842/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014843 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014844 * @ctxt: the schema parser context
14845 * @type: the complex type definition
14846 *
14847 * (3.4.6) Constraints on Complex Type Definition Schema Components
14848 *
14849 * Returns 0 if the constraints are satisfied, a positive
14850 * error code if not and -1 if an internal error occured.
14851 */
14852static int
14853xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14854 xmlSchemaTypePtr type)
14855{
14856 int ret;
14857 /*
14858 * Complex Type Definition Properties Correct
14859 */
14860 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14861 if (ret != 0)
14862 return (ret);
14863 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14864 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14865 else
14866 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14867 return (ret);
14868}
14869
14870/**
14871 * xmlSchemaCheckSRCCT:
14872 * @ctxt: the schema parser context
14873 * @type: the complex type definition
14874 *
14875 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
14876 * Schema Representation Constraint:
14877 * Complex Type Definition Representation OK (src-ct)
14878 *
14879 * Returns 0 if the constraints are satisfied, a positive
14880 * error code if not and -1 if an internal error occured.
14881 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014882static int
14883xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
14884 xmlSchemaTypePtr type)
14885{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014886 xmlSchemaTypePtr base;
14887 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014888
14889 /*
14890 * TODO: Adjust the error codes here, as I used
14891 * XML_SCHEMAP_SRC_CT_1 only yet.
14892 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014893 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014894 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014895 /*
14896 * 1 If the <complexContent> alternative is chosen, the type definition
14897 * ·resolved· to by the ·actual value· of the base [attribute]
14898 * must be a complex type definition;
14899 */
14900 if (! IS_COMPLEX_TYPE(base)) {
14901 xmlChar *str = NULL;
14902 xmlSchemaPCustomErr(ctxt,
14903 XML_SCHEMAP_SRC_CT_1,
14904 NULL, type, type->node,
14905 "If using <complexContent>, the base type is expected to be "
14906 "a complex type. The base type '%s' is a simple type",
14907 xmlSchemaFormatQName(&str, base->targetNamespace,
14908 base->name));
14909 FREE_AND_NULL(str)
14910 return (XML_SCHEMAP_SRC_CT_1);
14911 }
14912 } else {
14913 /*
14914 * SPEC
14915 * 2 If the <simpleContent> alternative is chosen, all of the
14916 * following must be true:
14917 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14918 * base [attribute] must be one of the following:
14919 */
14920 if (IS_SIMPLE_TYPE(base)) {
14921 if ((type->flags &
14922 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14923 xmlChar *str = NULL;
14924 /*
14925 * 2.1.3 only if the <extension> alternative is also
14926 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014927 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014928 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014929 xmlSchemaPCustomErr(ctxt,
14930 XML_SCHEMAP_SRC_CT_1,
14931 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014932 "If using <simpleContent> and <restriction>, the base "
14933 "type must be a complex type. The base type '%s' is "
14934 "a simple type",
14935 xmlSchemaFormatQName(&str, base->targetNamespace,
14936 base->name));
14937 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014938 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014939 }
14940 } else {
14941 /* Base type is a complex type. */
14942 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14943 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14944 /*
14945 * 2.1.1 a complex type definition whose {content type} is a
14946 * simple type definition;
14947 * PASS
14948 */
14949 if (base->contentTypeDef == NULL) {
14950 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014951 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014952 "Internal error: xmlSchemaCheckSRCCT, "
14953 "'%s', base type has no content type",
14954 type->name);
14955 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014956 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014957 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14958 (type->flags &
14959 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014960
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014961 /*
14962 * 2.1.2 only if the <restriction> alternative is also
14963 * chosen, a complex type definition whose {content type}
14964 * is mixed and a particle emptiable.
14965 */
14966 if (! xmlSchemaIsParticleEmptiable(
14967 (xmlSchemaParticlePtr) base->subtypes)) {
14968 ret = XML_SCHEMAP_SRC_CT_1;
14969 } else if ((type->contentTypeDef == NULL) ||
14970 (type->contentTypeDef->baseType == NULL)) {
14971 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014972 /*
14973 * 2.2 If clause 2.1.2 above is satisfied, then there
14974 * must be a <simpleType> among the [children] of
14975 * <restriction>.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014976 */
14977 /* TODO: Change error code to ..._SRC_CT_2_2. */
14978 xmlSchemaPCustomErr(ctxt,
14979 XML_SCHEMAP_SRC_CT_1,
14980 NULL, type, NULL,
14981 "A <simpleType> is expected among the children "
14982 "of <restriction>, if <simpleContent> is used and "
14983 "the base type '%s' is a complex type",
14984 xmlSchemaFormatQName(&str, base->targetNamespace,
14985 base->name));
14986 FREE_AND_NULL(str)
14987 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014988 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014989 } else {
14990 ret = XML_SCHEMAP_SRC_CT_1;
14991 }
14992 }
14993 if (ret > 0) {
14994 xmlChar *str = NULL;
14995 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
14996 xmlSchemaPCustomErr(ctxt,
14997 XML_SCHEMAP_SRC_CT_1,
14998 NULL, type, NULL,
14999 "If <simpleContent> and <restriction> is used, the "
15000 "base type must be a simple type or a complex type with "
15001 "mixed content and particle emptiable. The base type "
15002 "'%s' is none of those",
15003 xmlSchemaFormatQName(&str, base->targetNamespace,
15004 base->name));
15005 } else {
15006 xmlSchemaPCustomErr(ctxt,
15007 XML_SCHEMAP_SRC_CT_1,
15008 NULL, type, NULL,
15009 "If <simpleContent> and <extension> is used, the "
15010 "base type must be a simple type. The base type '%s' "
15011 "is a complex type",
15012 xmlSchemaFormatQName(&str, base->targetNamespace,
15013 base->name));
15014 }
15015 FREE_AND_NULL(str)
15016 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015017 }
15018 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015019 * SPEC (3) "The corresponding complex type definition component must
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015020 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015021 * Definition Schema Components (§3.4.6);"
15022 * NOTE (3) will be done in xmlSchemaTypeFixup().
15023 */
15024 /*
15025 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015026 * above for {attribute wildcard} is satisfied, the intensional
15027 * intersection must be expressible, as defined in Attribute Wildcard
15028 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015029 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015030 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015031 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015032}
William M. Brack2f2a6632004-08-20 23:09:47 +000015033
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015034#ifdef ENABLE_PARTICLE_RESTRICTION
15035/**
15036 * xmlSchemaCheckParticleRangeOK:
15037 * @ctxt: the schema parser context
15038 * @type: the complex type definition
15039 *
15040 * (3.9.6) Constraints on Particle Schema Components
15041 * Schema Component Constraint:
15042 * Occurrence Range OK (range-ok)
15043 *
15044 * STATUS: complete
15045 *
15046 * Returns 0 if the constraints are satisfied, a positive
15047 * error code if not and -1 if an internal error occured.
15048 */
15049static int
15050xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
15051 int bmin, int bmax)
15052{
15053 if (rmin < bmin)
15054 return (1);
15055 if ((bmax != UNBOUNDED) &&
15056 (rmax > bmax))
15057 return (1);
15058 return (0);
15059}
15060
15061/**
15062 * xmlSchemaCheckRCaseNameAndTypeOK:
15063 * @ctxt: the schema parser context
15064 * @r: the restricting element declaration particle
15065 * @b: the base element declaration particle
15066 *
15067 * (3.9.6) Constraints on Particle Schema Components
15068 * Schema Component Constraint:
15069 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
15070 * (rcase-NameAndTypeOK)
15071 *
15072 * STATUS:
15073 * MISSING (3.2.3)
15074 * CLARIFY: (3.2.2)
15075 *
15076 * Returns 0 if the constraints are satisfied, a positive
15077 * error code if not and -1 if an internal error occured.
15078 */
15079static int
15080xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
15081 xmlSchemaParticlePtr r,
15082 xmlSchemaParticlePtr b)
15083{
15084 xmlSchemaElementPtr elemR, elemB;
15085
15086 /* TODO: Error codes (rcase-NameAndTypeOK). */
15087 elemR = (xmlSchemaElementPtr) r->children;
15088 elemB = (xmlSchemaElementPtr) b->children;
15089 /*
15090 * SPEC (1) "The declarations' {name}s and {target namespace}s are
15091 * the same."
15092 */
15093 if ((elemR != elemB) &&
15094 ((! xmlStrEqual(elemR->name, elemB->name)) ||
15095 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
15096 return (1);
15097 /*
15098 * SPEC (2) "R's occurrence range is a valid restriction of B's
15099 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15100 */
15101 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15102 b->minOccurs, b->maxOccurs) != 0)
15103 return (1);
15104 /*
15105 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
15106 * {scope} are global."
15107 */
15108 if (elemR == elemB)
15109 return (0);
15110 /*
15111 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
15112 */
15113 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
15114 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
15115 return (1);
15116 /*
15117 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
15118 * or is not fixed, or R's declaration's {value constraint} is fixed
15119 * with the same value."
15120 */
15121 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
15122 ((elemR->value == NULL) ||
15123 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
15124 /* TODO: Equality of the initial value or normalized or canonical? */
15125 (! xmlStrEqual(elemR->value, elemB->value))))
15126 return (1);
15127 /*
15128 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
15129 * definitions} is a subset of B's declaration's {identity-constraint
15130 * definitions}, if any."
15131 */
15132 if (elemB->idcs != NULL) {
15133 /* TODO */
15134 }
15135 /*
15136 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
15137 * superset of B's declaration's {disallowed substitutions}."
15138 */
15139 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
15140 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
15141 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
15142 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
15143 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
15144 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
15145 return (1);
15146 /*
15147 * SPEC (3.2.5) "R's {type definition} is validly derived given
15148 * {extension, list, union} from B's {type definition}"
15149 *
15150 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15151 * set, if the corresponding constraints handle "restriction" and
15152 * "extension" only?
15153 *
15154 */
15155 {
15156 int set = 0;
15157
15158 set |= SUBSET_EXTENSION;
15159 set |= SUBSET_LIST;
15160 set |= SUBSET_UNION;
15161 if (xmlSchemaCheckCOSDerivedOK(ctxt->schema, elemR->subtypes,
15162 elemB->subtypes, set) != 0)
15163 return (1);
15164 }
15165 return (0);
15166}
15167
15168/**
15169 * xmlSchemaCheckRCaseNSCompat:
15170 * @ctxt: the schema parser context
15171 * @r: the restricting element declaration particle
15172 * @b: the base wildcard particle
15173 *
15174 * (3.9.6) Constraints on Particle Schema Components
15175 * Schema Component Constraint:
15176 * Particle Derivation OK (Elt:Any -- NSCompat)
15177 * (rcase-NSCompat)
15178 *
15179 * STATUS: complete
15180 *
15181 * Returns 0 if the constraints are satisfied, a positive
15182 * error code if not and -1 if an internal error occured.
15183 */
15184static int
15185xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15186 xmlSchemaParticlePtr r,
15187 xmlSchemaParticlePtr b)
15188{
15189 /* TODO:Error codes (rcase-NSCompat). */
15190 /*
15191 * SPEC "For an element declaration particle to be a ·valid restriction·
15192 * of a wildcard particle all of the following must be true:"
15193 *
15194 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15195 * with respect to the wildcard's {namespace constraint} as defined by
15196 * Wildcard allows Namespace Name (§3.10.4)."
15197 */
15198 if (xmlSchemaMatchesWildcardNs((xmlSchemaWildcardPtr) b->children,
15199 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15200 return (1);
15201 /*
15202 * SPEC (2) "R's occurrence range is a valid restriction of B's
15203 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15204 */
15205 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15206 b->minOccurs, b->maxOccurs) != 0)
15207 return (1);
15208
15209 return (0);
15210}
15211
15212/**
15213 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15214 * @ctxt: the schema parser context
15215 * @r: the restricting element declaration particle
15216 * @b: the base model group particle
15217 *
15218 * (3.9.6) Constraints on Particle Schema Components
15219 * Schema Component Constraint:
15220 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15221 * (rcase-RecurseAsIfGroup)
15222 *
15223 * STATUS: TODO
15224 *
15225 * Returns 0 if the constraints are satisfied, a positive
15226 * error code if not and -1 if an internal error occured.
15227 */
15228static int
15229xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15230 xmlSchemaParticlePtr r,
15231 xmlSchemaParticlePtr b)
15232{
15233 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15234 TODO
15235 return (0);
15236}
15237
15238/**
15239 * xmlSchemaCheckRCaseNSSubset:
15240 * @ctxt: the schema parser context
15241 * @r: the restricting wildcard particle
15242 * @b: the base wildcard particle
15243 *
15244 * (3.9.6) Constraints on Particle Schema Components
15245 * Schema Component Constraint:
15246 * Particle Derivation OK (Any:Any -- NSSubset)
15247 * (rcase-NSSubset)
15248 *
15249 * STATUS: complete
15250 *
15251 * Returns 0 if the constraints are satisfied, a positive
15252 * error code if not and -1 if an internal error occured.
15253 */
15254static int
15255xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15256 xmlSchemaParticlePtr r,
15257 xmlSchemaParticlePtr b,
15258 int isAnyTypeBase)
15259{
15260 /* TODO: Error codes (rcase-NSSubset). */
15261 /*
15262 * SPEC (1) "R's occurrence range is a valid restriction of B's
15263 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15264 */
15265 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15266 b->minOccurs, b->maxOccurs))
15267 return (1);
15268 /*
15269 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15270 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15271 */
15272 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15273 (xmlSchemaWildcardPtr) b->children))
15274 return (1);
15275 /*
15276 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15277 * definition·, R's {process contents} must be identical to or stronger
15278 * than B's {process contents}, where strict is stronger than lax is
15279 * stronger than skip."
15280 */
15281 if (! isAnyTypeBase) {
15282 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15283 ((xmlSchemaWildcardPtr) b->children)->processContents)
15284 return (1);
15285 }
15286
15287 return (0);
15288}
15289
15290/**
15291 * xmlSchemaCheckCOSParticleRestrict:
15292 * @ctxt: the schema parser context
15293 * @type: the complex type definition
15294 *
15295 * (3.9.6) Constraints on Particle Schema Components
15296 * Schema Component Constraint:
15297 * Particle Valid (Restriction) (cos-particle-restrict)
15298 *
15299 * STATUS: TODO
15300 *
15301 * Returns 0 if the constraints are satisfied, a positive
15302 * error code if not and -1 if an internal error occured.
15303 */
15304static int
15305xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15306 xmlSchemaParticlePtr r,
15307 xmlSchemaParticlePtr b)
15308{
15309 int ret = 0;
15310
15311 /*part = GET_PARTICLE(type);
15312 basePart = GET_PARTICLE(base);
15313 */
15314
15315 TODO
15316
15317 /*
15318 * SPEC (1) "They are the same particle."
15319 */
15320 if (r == b)
15321 return (0);
15322
15323
15324 return (0);
15325}
15326
15327/**
15328 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15329 * @ctxt: the schema parser context
15330 * @r: the model group particle
15331 * @b: the base wildcard particle
15332 *
15333 * (3.9.6) Constraints on Particle Schema Components
15334 * Schema Component Constraint:
15335 * Particle Derivation OK (All/Choice/Sequence:Any --
15336 * NSRecurseCheckCardinality)
15337 * (rcase-NSRecurseCheckCardinality)
15338 *
15339 * STATUS: TODO: subst-groups
15340 *
15341 * Returns 0 if the constraints are satisfied, a positive
15342 * error code if not and -1 if an internal error occured.
15343 */
15344static int
15345xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15346 xmlSchemaParticlePtr r,
15347 xmlSchemaParticlePtr b)
15348{
15349 xmlSchemaParticlePtr part;
15350 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15351 if ((r->children == NULL) || (r->children->children == NULL))
15352 return (-1);
15353 /*
15354 * SPEC "For a group particle to be a ·valid restriction· of a
15355 * wildcard particle..."
15356 *
15357 * SPEC (1) "Every member of the {particles} of the group is a ·valid
15358 * restriction· of the wildcard as defined by
15359 * Particle Valid (Restriction) (§3.9.6)."
15360 */
15361 part = (xmlSchemaParticlePtr) r->children->children;
15362 do {
15363 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15364 return (1);
15365 part = (xmlSchemaParticlePtr) part->next;
15366 } while (part != NULL);
15367 /*
15368 * SPEC (2) "The effective total range of the group [...] is a
15369 * valid restriction of B's occurrence range as defined by
15370 * Occurrence Range OK (§3.9.6)."
15371 */
15372 if (xmlSchemaCheckParticleRangeOK(
15373 xmlSchemaGetParticleTotalRangeMin(r),
15374 xmlSchemaGetParticleTotalRangeMax(r),
15375 b->minOccurs, b->maxOccurs) != 0)
15376 return (1);
15377 return (0);
15378}
15379
15380/**
15381 * xmlSchemaCheckRCaseRecurse:
15382 * @ctxt: the schema parser context
15383 * @r: the <all> or <sequence> model group particle
15384 * @b: the base <all> or <sequence> model group particle
15385 *
15386 * (3.9.6) Constraints on Particle Schema Components
15387 * Schema Component Constraint:
15388 * Particle Derivation OK (All:All,Sequence:Sequence --
15389 Recurse)
15390 * (rcase-Recurse)
15391 *
15392 * STATUS: ?
15393 * TODO: subst-groups
15394 *
15395 * Returns 0 if the constraints are satisfied, a positive
15396 * error code if not and -1 if an internal error occured.
15397 */
15398static int
15399xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15400 xmlSchemaParticlePtr r,
15401 xmlSchemaParticlePtr b)
15402{
15403 /* xmlSchemaParticlePtr part; */
15404 /* TODO: Error codes (rcase-Recurse). */
15405 if ((r->children == NULL) || (b->children == NULL) ||
15406 (r->children->type != b->children->type))
15407 return (-1);
15408 /*
15409 * SPEC "For an all or sequence group particle to be a ·valid
15410 * restriction· of another group particle with the same {compositor}..."
15411 *
15412 * SPEC (1) "R's occurrence range is a valid restriction of B's
15413 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15414 */
15415 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15416 b->minOccurs, b->maxOccurs))
15417 return (1);
15418
15419
15420 return (0);
15421}
15422
15423#endif
15424
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015425#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15426 xmlSchemaPCustomErrExt(pctxt, \
15427 XML_SCHEMAP_INVALID_FACET_VALUE, \
15428 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15429 "It is an error for both '%s' and '%s' to be specified on the "\
15430 "same type definition", \
15431 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15432 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15433
15434#define FACET_RESTR_ERR(fac1, msg) \
15435 xmlSchemaPCustomErr(pctxt, \
15436 XML_SCHEMAP_INVALID_FACET_VALUE, \
15437 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15438 msg, NULL);
15439
15440#define FACET_RESTR_FIXED_ERR(fac) \
15441 xmlSchemaPCustomErr(pctxt, \
15442 XML_SCHEMAP_INVALID_FACET_VALUE, \
15443 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15444 "The base type's facet is 'fixed', thus the value must not " \
15445 "differ", NULL);
15446
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015447static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015448xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15449 xmlSchemaFacetPtr facet1,
15450 xmlSchemaFacetPtr facet2,
15451 int lessGreater,
15452 int orEqual,
15453 int ofBase)
15454{
15455 xmlChar *msg = NULL;
15456
15457 msg = xmlStrdup(BAD_CAST "'");
15458 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15459 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15460 if (lessGreater == 0)
15461 msg = xmlStrcat(msg, BAD_CAST " equal to");
15462 if (lessGreater == 1)
15463 msg = xmlStrcat(msg, BAD_CAST " greater than");
15464 else
15465 msg = xmlStrcat(msg, BAD_CAST " less than");
15466
15467 if (orEqual)
15468 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15469 msg = xmlStrcat(msg, BAD_CAST " '");
15470 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15471 if (ofBase)
15472 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15473 else
15474 msg = xmlStrcat(msg, BAD_CAST "'");
15475
15476 xmlSchemaPCustomErr(pctxt,
15477 XML_SCHEMAP_INVALID_FACET_VALUE,
15478 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
15479 (const char *) msg, NULL);
15480
15481 if (msg != NULL)
15482 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015483}
15484
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015485static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015486xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15487 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015488{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015489 xmlSchemaTypePtr base = type->baseType;
15490 xmlSchemaFacetLinkPtr link, cur, last = NULL;
15491 xmlSchemaFacetPtr facet, bfacet,
15492 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15493 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15494 fmininc = NULL, fmaxinc = NULL,
15495 fminexc = NULL, fmaxexc = NULL,
15496 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15497 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15498 bfmininc = NULL, bfmaxinc = NULL,
15499 bfminexc = NULL, bfmaxexc = NULL;
15500 int res, err = 0, fixedErr;
15501 /*
15502 * 3 The {facets} of R are the union of S and the {facets}
15503 * of B, eliminating duplicates. To eliminate duplicates,
15504 * when a facet of the same kind occurs in both S and the
15505 * {facets} of B, the one in the {facets} of B is not
15506 * included, with the exception of enumeration and pattern
15507 * facets, for which multiple occurrences with distinct values
15508 * are allowed.
15509 */
15510 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15511 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015512
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015513 last = type->facetSet;
15514 if (last != NULL)
15515 while (last->next != NULL)
15516 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015517
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015518 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15519 facet = cur->facet;
15520 switch (facet->type) {
15521 case XML_SCHEMA_FACET_LENGTH:
15522 flength = facet; break;
15523 case XML_SCHEMA_FACET_MINLENGTH:
15524 fminlen = facet; break;
15525 case XML_SCHEMA_FACET_MININCLUSIVE:
15526 fmininc = facet; break;
15527 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15528 fminexc = facet; break;
15529 case XML_SCHEMA_FACET_MAXLENGTH:
15530 fmaxlen = facet; break;
15531 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15532 fmaxinc = facet; break;
15533 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15534 fmaxexc = facet; break;
15535 case XML_SCHEMA_FACET_TOTALDIGITS:
15536 ftotdig = facet; break;
15537 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15538 ffracdig = facet; break;
15539 default:
15540 break;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015541 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015542 }
15543 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15544 facet = cur->facet;
15545 switch (facet->type) {
15546 case XML_SCHEMA_FACET_LENGTH:
15547 bflength = facet; break;
15548 case XML_SCHEMA_FACET_MINLENGTH:
15549 bfminlen = facet; break;
15550 case XML_SCHEMA_FACET_MININCLUSIVE:
15551 bfmininc = facet; break;
15552 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15553 bfminexc = facet; break;
15554 case XML_SCHEMA_FACET_MAXLENGTH:
15555 bfmaxlen = facet; break;
15556 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15557 bfmaxinc = facet; break;
15558 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15559 bfmaxexc = facet; break;
15560 case XML_SCHEMA_FACET_TOTALDIGITS:
15561 bftotdig = facet; break;
15562 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15563 bffracdig = facet; break;
15564 default:
15565 break;
15566 }
15567 }
15568 err = 0;
15569 /*
15570 * length and minLength or maxLength (2.2) + (3.2)
15571 */
15572 if (flength && (fminlen || fmaxlen)) {
15573 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15574 "either of 'minLength' or 'maxLength' to be specified on "
15575 "the same type definition")
15576 }
15577 /*
15578 * Mutual exclusions in the same derivation step.
15579 */
15580 if ((fmaxinc) && (fmaxexc)) {
15581 /*
15582 * SCC "maxInclusive and maxExclusive"
15583 */
15584 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15585 }
15586 if ((fmininc) && (fminexc)) {
15587 /*
15588 * SCC "minInclusive and minExclusive"
15589 */
15590 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015591 }
15592
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015593 if (flength && bflength) {
15594 /*
15595 * SCC "length valid restriction"
15596 * The values have to be equal.
15597 */
15598 res = xmlSchemaCompareValues(flength->val, bflength->val);
15599 if (res == -2)
15600 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015601 if (res != 0)
15602 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15603 if ((res != 0) && (bflength->fixed)) {
15604 FACET_RESTR_FIXED_ERR(flength)
15605 }
15606
15607 }
15608 if (fminlen && bfminlen) {
15609 /*
15610 * SCC "minLength valid restriction"
15611 * minLength >= BASE minLength
15612 */
15613 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15614 if (res == -2)
15615 goto internal_error;
15616 if (res == -1)
15617 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15618 if ((res != 0) && (bfminlen->fixed)) {
15619 FACET_RESTR_FIXED_ERR(fminlen)
15620 }
15621 }
15622 if (fmaxlen && bfmaxlen) {
15623 /*
15624 * SCC "maxLength valid restriction"
15625 * maxLength <= BASE minLength
15626 */
15627 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15628 if (res == -2)
15629 goto internal_error;
15630 if (res == 1)
15631 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15632 if ((res != 0) && (bfmaxlen->fixed)) {
15633 FACET_RESTR_FIXED_ERR(fmaxlen)
15634 }
15635 }
15636 /*
15637 * SCC "length and minLength or maxLength"
15638 */
15639 if (! flength)
15640 flength = bflength;
15641 if (flength) {
15642 if (! fminlen)
15643 flength = bflength;
15644 if (fminlen) {
15645 /* (1.1) length >= minLength */
15646 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15647 if (res == -2)
15648 goto internal_error;
15649 if (res == -1)
15650 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15651 }
15652 if (! fmaxlen)
15653 fmaxlen = bfmaxlen;
15654 if (fmaxlen) {
15655 /* (2.1) length <= maxLength */
15656 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15657 if (res == -2)
15658 goto internal_error;
15659 if (res == 1)
15660 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15661 }
15662 }
15663 if (fmaxinc) {
15664 /*
15665 * "maxInclusive"
15666 */
15667 if (fmininc) {
15668 /* SCC "maxInclusive >= minInclusive" */
15669 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15670 if (res == -2)
15671 goto internal_error;
15672 if (res == -1) {
15673 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15674 }
15675 }
15676 /*
15677 * SCC "maxInclusive valid restriction"
15678 */
15679 if (bfmaxinc) {
15680 /* maxInclusive <= BASE maxInclusive */
15681 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15682 if (res == -2)
15683 goto internal_error;
15684 if (res == 1)
15685 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15686 if ((res != 0) && (bfmaxinc->fixed)) {
15687 FACET_RESTR_FIXED_ERR(fmaxinc)
15688 }
15689 }
15690 if (bfmaxexc) {
15691 /* maxInclusive < BASE maxExclusive */
15692 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15693 if (res == -2)
15694 goto internal_error;
15695 if (res != -1) {
15696 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15697 }
15698 }
15699 if (bfmininc) {
15700 /* maxInclusive >= BASE minInclusive */
15701 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15702 if (res == -2)
15703 goto internal_error;
15704 if (res == -1) {
15705 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15706 }
15707 }
15708 if (bfminexc) {
15709 /* maxInclusive > BASE minExclusive */
15710 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15711 if (res == -2)
15712 goto internal_error;
15713 if (res != 1) {
15714 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15715 }
15716 }
15717 }
15718 if (fmaxexc) {
15719 /*
15720 * "maxExclusive >= minExclusive"
15721 */
15722 if (fminexc) {
15723 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15724 if (res == -2)
15725 goto internal_error;
15726 if (res == -1) {
15727 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15728 }
15729 }
15730 /*
15731 * "maxExclusive valid restriction"
15732 */
15733 if (bfmaxexc) {
15734 /* maxExclusive <= BASE maxExclusive */
15735 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15736 if (res == -2)
15737 goto internal_error;
15738 if (res == 1) {
15739 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15740 }
15741 if ((res != 0) && (bfmaxexc->fixed)) {
15742 FACET_RESTR_FIXED_ERR(fmaxexc)
15743 }
15744 }
15745 if (bfmaxinc) {
15746 /* maxExclusive <= BASE maxInclusive */
15747 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15748 if (res == -2)
15749 goto internal_error;
15750 if (res == 1) {
15751 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15752 }
15753 }
15754 if (bfmininc) {
15755 /* maxExclusive > BASE minInclusive */
15756 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15757 if (res == -2)
15758 goto internal_error;
15759 if (res != 1) {
15760 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15761 }
15762 }
15763 if (bfminexc) {
15764 /* maxExclusive > BASE minExclusive */
15765 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15766 if (res == -2)
15767 goto internal_error;
15768 if (res != 1) {
15769 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15770 }
15771 }
15772 }
15773 if (fminexc) {
15774 /*
15775 * "minExclusive < maxInclusive"
15776 */
15777 if (fmaxinc) {
15778 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15779 if (res == -2)
15780 goto internal_error;
15781 if (res != -1) {
15782 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15783 }
15784 }
15785 /*
15786 * "minExclusive valid restriction"
15787 */
15788 if (bfminexc) {
15789 /* minExclusive >= BASE minExclusive */
15790 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15791 if (res == -2)
15792 goto internal_error;
15793 if (res == -1) {
15794 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15795 }
15796 if ((res != 0) && (bfminexc->fixed)) {
15797 FACET_RESTR_FIXED_ERR(fminexc)
15798 }
15799 }
15800 if (bfmaxinc) {
15801 /* minExclusive <= BASE maxInclusive */
15802 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15803 if (res == -2)
15804 goto internal_error;
15805 if (res == 1) {
15806 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15807 }
15808 }
15809 if (bfmininc) {
15810 /* minExclusive >= BASE minInclusive */
15811 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15812 if (res == -2)
15813 goto internal_error;
15814 if (res == -1) {
15815 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15816 }
15817 }
15818 if (bfmaxexc) {
15819 /* minExclusive < BASE maxExclusive */
15820 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15821 if (res == -2)
15822 goto internal_error;
15823 if (res != -1) {
15824 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15825 }
15826 }
15827 }
15828 if (fmininc) {
15829 /*
15830 * "minInclusive < maxExclusive"
15831 */
15832 if (fmaxexc) {
15833 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15834 if (res == -2)
15835 goto internal_error;
15836 if (res != -1) {
15837 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15838 }
15839 }
15840 /*
15841 * "minExclusive valid restriction"
15842 */
15843 if (bfmininc) {
15844 /* minInclusive >= BASE minInclusive */
15845 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15846 if (res == -2)
15847 goto internal_error;
15848 if (res == -1) {
15849 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15850 }
15851 if ((res != 0) && (bfmininc->fixed)) {
15852 FACET_RESTR_FIXED_ERR(fmininc)
15853 }
15854 }
15855 if (bfmaxinc) {
15856 /* minInclusive <= BASE maxInclusive */
15857 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15858 if (res == -2)
15859 goto internal_error;
15860 if (res == -1) {
15861 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15862 }
15863 }
15864 if (bfminexc) {
15865 /* minInclusive > BASE minExclusive */
15866 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15867 if (res == -2)
15868 goto internal_error;
15869 if (res != 1)
15870 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15871 }
15872 if (bfmaxexc) {
15873 /* minInclusive < BASE maxExclusive */
15874 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15875 if (res == -2)
15876 goto internal_error;
15877 if (res != -1)
15878 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15879 }
15880 }
15881 if (ftotdig && bftotdig) {
15882 /*
15883 * SCC " totalDigits valid restriction"
15884 * totalDigits <= BASE totalDigits
15885 */
15886 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15887 if (res == -2)
15888 goto internal_error;
15889 if (res == 1)
15890 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15891 -1, 1, 1);
15892 if ((res != 0) && (bftotdig->fixed)) {
15893 FACET_RESTR_FIXED_ERR(ftotdig)
15894 }
15895 }
15896 if (ffracdig && bffracdig) {
15897 /*
15898 * SCC "fractionDigits valid restriction"
15899 * fractionDigits <= BASE fractionDigits
15900 */
15901 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15902 if (res == -2)
15903 goto internal_error;
15904 if (res == 1)
15905 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15906 -1, 1, 1);
15907 if ((res != 0) && (bffracdig->fixed)) {
15908 FACET_RESTR_FIXED_ERR(ffracdig)
15909 }
15910 }
15911 /*
15912 * SCC "fractionDigits less than or equal to totalDigits"
15913 */
15914 if (! ftotdig)
15915 ftotdig = bftotdig;
15916 if (! ffracdig)
15917 ffracdig = bffracdig;
15918 if (ftotdig && ffracdig) {
15919 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15920 if (res == -2)
15921 goto internal_error;
15922 if (res == 1)
15923 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15924 -1, 1, 0);
15925 }
15926 /*
15927 * *Enumerations* won' be added here, since only the first set
15928 * of enumerations in the ancestor-or-self axis is used
15929 * for validation, plus we need to use the base type of those
15930 * enumerations for whitespace.
15931 *
15932 * *Patterns*: won't be add here, since they are ORed at
15933 * type level and ANDed at ancestor level. This will
15934 * happed during validation by walking the base axis
15935 * of the type.
15936 */
15937 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15938 bfacet = cur->facet;
15939 /*
15940 * Special handling of enumerations and patterns.
15941 * TODO: hmm, they should not appear in the set, so remove this.
15942 */
15943 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
15944 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
15945 continue;
15946 /*
15947 * Search for a duplicate facet in the current type.
15948 */
15949 link = type->facetSet;
15950 err = 0;
15951 fixedErr = 0;
15952 while (link != NULL) {
15953 facet = link->facet;
15954 if (facet->type == bfacet->type) {
15955 switch (facet->type) {
15956 case XML_SCHEMA_FACET_WHITESPACE:
15957 /*
15958 * The whitespace must be stronger.
15959 */
15960 if (facet->whitespace < bfacet->whitespace) {
15961 FACET_RESTR_ERR(flength,
15962 "The 'whitespace' value has to be equal to "
15963 "or stronger than the 'whitespace' value of "
15964 "the base type")
15965 }
15966 if ((bfacet->fixed) &&
15967 (facet->whitespace != bfacet->whitespace)) {
15968 FACET_RESTR_FIXED_ERR(facet)
15969 }
15970 break;
15971 default:
15972 break;
15973 }
15974 /* Duplicate found. */
15975 break;
15976 }
15977 link = link->next;
15978 }
15979 /*
15980 * If no duplicate was found: add the base types's facet
15981 * to the set.
15982 */
15983 if (link == NULL) {
15984 link = (xmlSchemaFacetLinkPtr)
15985 xmlMalloc(sizeof(xmlSchemaFacetLink));
15986 if (link == NULL) {
15987 xmlSchemaPErrMemory(pctxt,
15988 "deriving facets, creating a facet link", NULL);
15989 return (-1);
15990 }
15991 link->facet = cur->facet;
15992 link->next = NULL;
15993 if (last == NULL)
15994 type->facetSet = link;
15995 else
15996 last->next = link;
15997 last = link;
15998 }
15999
16000 }
16001
16002 return (0);
16003internal_error:
16004 xmlSchemaPCustomErr(pctxt,
16005 XML_SCHEMAP_INVALID_FACET_VALUE,
16006 NULL, type, NULL,
16007 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
16008 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016009}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016010
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016011static int
16012xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
16013 xmlSchemaTypePtr type)
16014{
16015 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
16016 /*
16017 * The actual value is then formed by replacing any union type
16018 * definition in the ·explicit members· with the members of their
16019 * {member type definitions}, in order.
16020 */
16021 link = type->memberTypes;
16022 while (link != NULL) {
16023
16024 if (IS_NOT_TYPEFIXED(link->type))
16025 xmlSchemaTypeFixup(link->type, pctxt, NULL);
16026
16027 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16028 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
16029 if (subLink != NULL) {
16030 link->type = subLink->type;
16031 if (subLink->next != NULL) {
16032 lastLink = link->next;
16033 subLink = subLink->next;
16034 prevLink = link;
16035 while (subLink != NULL) {
16036 newLink = (xmlSchemaTypeLinkPtr)
16037 xmlMalloc(sizeof(xmlSchemaTypeLink));
16038 if (newLink == NULL) {
16039 xmlSchemaPErrMemory(pctxt, "allocating a type link",
16040 NULL);
16041 return (-1);
16042 }
16043 newLink->type = subLink->type;
16044 prevLink->next = newLink;
16045 prevLink = newLink;
16046 newLink->next = lastLink;
16047
16048 subLink = subLink->next;
16049 }
16050 }
16051 }
16052 }
16053 link = link->next;
16054 }
16055 return (0);
16056}
16057
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016058/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016059 * xmlSchemaTypeFixup:
16060 * @typeDecl: the schema type definition
16061 * @ctxt: the schema parser context
16062 *
16063 * Fixes the content model of the type.
16064 */
16065static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016066xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016067 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016068{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016069 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016070 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016071 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16072 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016073 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016074 if (! IS_NOT_TYPEFIXED(type))
16075 return;
16076 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016077 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016078 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016079
16080 if (type->baseType == NULL) {
16081 xmlSchemaPCustomErr(ctxt,
16082 XML_SCHEMAP_INTERNAL,
16083 NULL, type, NULL,
16084 "Internal error: xmlSchemaTypeFixup, "
16085 "baseType is missing on '%s'", type->name);
16086 return;
16087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016088
16089 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016090 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016091
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016092 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016093 * Type-fix the base type.
16094 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016095 if (IS_NOT_TYPEFIXED(baseType))
16096 xmlSchemaTypeFixup(baseType, ctxt, NULL);
16097 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16098 /*
16099 * Skip fixup if the base type is invalid.
16100 * TODO: Generate a warning!
16101 */
16102 return;
16103 }
16104 /*
16105 * This basically checks if the base type can be derived.
16106 */
16107 if (xmlSchemaCheckSRCCT(ctxt, type) != 0) {
16108 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16109 return;
16110 }
16111 /*
16112 * Fixup the content type.
16113 */
16114 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16115 /*
16116 * Corresponds to <complexType><simpleContent>...
16117 */
16118 if ((IS_COMPLEX_TYPE(baseType)) &&
16119 (baseType->contentTypeDef != NULL) &&
16120 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16121 /*
16122 * SPEC (1) If <restriction> + base type is <complexType>,
16123 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016124 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016125 * NOTE (1.1) is handled during parsing of <restriction>.
16126 *
16127 * (1.2) "...otherwise (<restriction> has no <simpleType> among
16128 * its [children]), the simple type definition which is the
16129 * {content type} of the ... base type."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016130 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016131 if (type->contentTypeDef->baseType == NULL) {
16132 /*
16133 * <simpleContent><restriction> has *no* <simpleType>
16134 * child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016135 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016136 type->contentTypeDef->baseType =
16137 baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016138 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016139 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16140 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16141 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16142 /*
16143 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16144 * an emptiable particle, then a simple type definition which
16145 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016146 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016147 if ((type->contentTypeDef == NULL) ||
16148 (type->contentTypeDef->baseType == NULL)) {
16149 /*
16150 * TODO: Check if this ever happens.
16151 */
16152 xmlSchemaPCustomErr(ctxt,
16153 XML_SCHEMAP_INTERNAL,
16154 NULL, type, NULL,
16155 "Internal error: xmlSchemaTypeFixup, "
16156 "complex type '%s': the <simpleContent><restriction> "
16157 "is missing a <simpleType> child, but was not catched "
16158 "by xmlSchemaCheckSRCCT()", type->name);
16159 }
16160 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16161 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16162 /*
16163 * SPEC (3) If <extension> + base is <complexType> with
16164 * <simpleType> content, "...then the {content type} of that
16165 * complex type definition"
16166 */
16167 if (baseType->contentTypeDef == NULL) {
16168 /*
16169 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16170 * should have catched this already.
16171 */
16172 xmlSchemaPCustomErr(ctxt,
16173 XML_SCHEMAP_INTERNAL,
16174 NULL, type, NULL,
16175 "Internal error: xmlSchemaTypeFixup, "
16176 "complex type '%s': the <extension>ed base type is "
16177 "a complex type with no simple content type",
16178 type->name);
16179 }
16180 type->contentTypeDef = baseType->contentTypeDef;
16181 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16182 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16183 /*
16184 * SPEC (4) <extension> + base is <simpleType>
16185 * "... then that simple type definition"
16186 */
16187 type->contentTypeDef = baseType;
16188 } else {
16189 /*
16190 * TODO: Check if this ever happens.
16191 */
16192 xmlSchemaPCustomErr(ctxt,
16193 XML_SCHEMAP_INTERNAL,
16194 NULL, type, NULL,
16195 "Internal error: xmlSchemaTypeFixup, "
16196 "complex type '%s' with <simpleContent>: unhandled "
16197 "derivation case", type->name);
16198 }
16199 } else {
16200 int dummySequence = 0;
16201 xmlSchemaParticlePtr particle =
16202 (xmlSchemaParticlePtr) type->subtypes;
16203 /*
16204 * Corresponds to <complexType><complexContent>...
16205 *
16206 * NOTE that the effective mixed was already set during parsing of
16207 * <complexType> and <complexContent>; its flag value is
16208 * XML_SCHEMAS_TYPE_MIXED.
16209 *
16210 * Compute the "effective content":
16211 * (2.1.1) + (2.1.2) + (2.1.3)
16212 */
16213 if ((particle == NULL) ||
16214 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16215 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16216 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16217 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16218 (particle->minOccurs == 0))) &&
16219 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
16220 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
16221 /*
16222 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16223 * a particle whose properties are as follows:..."
16224 *
16225 * Empty sequence model group with
16226 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16227 * NOTE that we sill assign it the <complexType> node to
16228 * somehow anchor it in the doc.
16229 */
16230 if ((particle == NULL) ||
16231 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016232 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016233 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016234 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016235 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
16236 type->node, 1, 1);
16237 if (particle == NULL)
16238 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016239 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016240 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016241 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016242 particle->children = (xmlSchemaTreeItemPtr)
16243 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
16244 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16245 if (particle->children == NULL)
16246 return;
16247
16248 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016249 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016250 dummySequence = 1;
16251 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16252 } else {
16253 /*
16254 * SPEC (2.1.5) "otherwise empty"
16255 */
16256 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
16257 }
16258 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016259 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 * SPEC (2.2) "otherwise the particle corresponding to the
16261 * <all>, <choice>, <group> or <sequence> among the
16262 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016263 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16265 }
16266 /*
16267 * Compute the "content type".
16268 */
16269 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016270 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016271 * SPEC (3.1) "If <restriction>..."
16272 * (3.1.1) + (3.1.2) */
16273 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16274 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16275 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16276 }
16277 } else {
16278 /*
16279 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016280 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016281 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16282 /*
16283 * SPEC (3.2.1)
16284 */
16285 type->contentType = baseType->contentType;
16286 type->subtypes = baseType->subtypes;
16287 /*
16288 * NOTE that the effective mixed is ignored here.
16289 */
16290 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16291 /*
16292 * SPEC (3.2.2)
16293 */
16294 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16295 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16296 } else {
16297 /*
16298 * SPEC (3.2.3)
16299 */
16300 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16301 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16302 /*
16303 * "A model group whose {compositor} is sequence and whose
16304 * {particles} are..."
16305 */
16306 if (! dummySequence) {
16307 xmlSchemaTreeItemPtr effectiveContent =
16308 (xmlSchemaTreeItemPtr) type->subtypes;
16309 /*
16310 * Create the particle.
16311 */
16312 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
16313 type->node, 1, 1);
16314 if (particle == NULL)
16315 return;
16316 /*
16317 * Create the "sequence" model group.
16318 */
16319 particle->children = (xmlSchemaTreeItemPtr)
16320 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
16321 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16322 if (particle->children == NULL)
16323 return;
16324 type->subtypes = (xmlSchemaTypePtr) particle;
16325 /*
16326 * SPEC "the particle of the {content type} of
16327 * the ... base ..."
16328 * Create a duplicate of the base type's particle
16329 * and assign its "term" to it.
16330 */
16331 particle->children->children =
16332 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(ctxt,
16333 ctxt->schema, type->node,
16334 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
16335 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
16336 if (particle->children->children == NULL)
16337 return;
16338 particle = (xmlSchemaParticlePtr)
16339 particle->children->children;
16340 particle->children =
16341 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16342 /*
16343 * SPEC "followed by the ·effective content·."
16344 */
16345 particle->next = effectiveContent;
16346 } else {
16347 /*
16348 * This is the case when there is already an empty
16349 * <sequence> with minOccurs==maxOccurs==1.
16350 * Just add the base types's content type.
16351 * NOTE that, although we miss to add an intermediate
16352 * <sequence>, this should produce no difference to
16353 * neither the regex compilation of the content model,
16354 * nor to the complex type contraints.
16355 */
16356 particle->children->children =
16357 (xmlSchemaTreeItemPtr) baseType->subtypes;
16358 }
16359 }
16360 }
16361 }
16362 /*
16363 * Apply the complex type component constraints; this will not
16364 * check attributes, since this is done in
16365 * xmlSchemaBuildAttributeValidation().
16366 */
16367 if (xmlSchemaCheckCTComponent(ctxt, type) != 0)
16368 return;
16369 /*
16370 * Inherit & check constraints for attributes.
16371 */
16372 xmlSchemaBuildAttributeValidation(ctxt, type);
16373 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
16374 /*
16375 * Simple Type Definition Schema Component
16376 */
16377 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16378 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16379 /*
16380 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016381 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 if (type->subtypes == NULL) {
16383 /*
16384 * This one is really needed, so get out.
16385 */
16386 return;
16387 }
16388 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016389 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16391 /*
16392 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016393 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 if (type->memberTypes == NULL) {
16395 /*
16396 * This one is really needed, so get out.
16397 */
16398 return;
16399 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016400 if (xmlSchemaFinishMemberTypeDefinitionsProperty(ctxt, type) == -1)
16401 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016402 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016403 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016404 /*
16405 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016406 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016407 if (IS_NOT_TYPEFIXED(baseType))
16408 xmlSchemaTypeFixup(baseType, ctxt, NULL);
16409 /*
16410 * Variety
16411 * If the <restriction> alternative is chosen, then the
16412 * {variety} of the {base type definition}.
16413 */
16414 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
16415 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
16416 else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16417 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16418 /*
16419 * Inherit the itemType.
16420 */
16421 type->subtypes = baseType->subtypes;
16422 } else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16423 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16424 /*
16425 * NOTE that we won't assign the memberTypes of the base,
16426 * since this will make trouble when freeing them; we will
16427 * use a lookup function to access them instead.
16428 */
16429 }
16430
16431 /*
16432 * Some optimization for validation:
16433 * If there are no facets beside the "whitespace" facet,
16434 * then a value needs not to checked against against a
16435 * facet, thus no computed value is needed.
16436 */
16437#if 0
16438 if (baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
16439 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16440 else {
16441 for (cur = type->facetSet; cur != NULL;
16442 cur = cur->next) {
16443 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
16444 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16445 break;
16446 }
16447 }
16448 }
16449#endif
16450 }
16451 /*
16452 * Check constraints.
16453 *
16454 * TODO: Split this somehow, we need to know first if we can derive
16455 * from the base type at all!
16456 */
16457 if (type->baseType != NULL) {
16458 /*
16459 * Schema Component Constraint: Simple Type Restriction
16460 * (Facets)
16461 * NOTE: Satisfaction of 1 and 2 arise from the fixup
16462 * applied beforehand.
16463 */
16464 xmlSchemaCheckSRCSimpleType(ctxt, type);
16465 xmlSchemaCheckFacetValues(type, ctxt);
16466 xmlSchemaDeriveAndValidateFacets(ctxt, type);
16467 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016468 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016469
Daniel Veillard8651f532002-04-17 09:06:27 +000016470#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016471 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016472 xmlGenericError(xmlGenericErrorContext,
16473 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016474 type->node->doc->URL,
16475 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016476 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016477 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016478 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016479 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16480 switch (type->contentType) {
16481 case XML_SCHEMA_CONTENT_SIMPLE:
16482 xmlGenericError(xmlGenericErrorContext, "simple\n");
16483 break;
16484 case XML_SCHEMA_CONTENT_ELEMENTS:
16485 xmlGenericError(xmlGenericErrorContext, "elements\n");
16486 break;
16487 case XML_SCHEMA_CONTENT_UNKNOWN:
16488 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16489 break;
16490 case XML_SCHEMA_CONTENT_EMPTY:
16491 xmlGenericError(xmlGenericErrorContext, "empty\n");
16492 break;
16493 case XML_SCHEMA_CONTENT_MIXED:
16494 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
16495 type->subtypes))
16496 xmlGenericError(xmlGenericErrorContext,
16497 "mixed as emptiable particle\n");
16498 else
16499 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16500 break;
16501 /* Removed, since not used. */
16502 /*
16503 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16504 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16505 break;
16506 */
16507 case XML_SCHEMA_CONTENT_BASIC:
16508 xmlGenericError(xmlGenericErrorContext, "basic\n");
16509 break;
16510 default:
16511 xmlGenericError(xmlGenericErrorContext,
16512 "not registered !!!\n");
16513 break;
16514 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016515 }
16516#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016517}
16518
16519/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016520 * xmlSchemaCheckFacet:
16521 * @facet: the facet
16522 * @typeDecl: the schema type definition
16523 * @ctxt: the schema parser context or NULL
16524 * @name: name of the type
16525 *
16526 * Checks the default values types, especially for facets
16527 *
16528 * Returns 0 if okay or -1 in cae of error
16529 */
16530int
16531xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016532 xmlSchemaTypePtr typeDecl,
16533 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016534{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016535 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016536 int ret = 0, reuseValCtxt = 0;
16537
Daniel Veillardce682bc2004-11-05 17:22:25 +000016538 if ((facet == NULL) || (typeDecl == NULL))
16539 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016540 /*
16541 * TODO: will the parser context be given if used from
16542 * the relaxNG module?
16543 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016544
16545 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016546 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000016547 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016548 }
16549 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016550 case XML_SCHEMA_FACET_MININCLUSIVE:
16551 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16552 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016553 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16554 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016555 /*
16556 * Okay we need to validate the value
16557 * at that point.
16558 */
16559 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016560 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016561
16562 /* 4.3.5.5 Constraints on enumeration Schema Components
16563 * Schema Component Constraint: enumeration valid restriction
16564 * It is an ·error· if any member of {value} is not in the
16565 * ·value space· of {base type definition}.
16566 *
16567 * minInclusive, maxInclusive, minExclusive, maxExclusive:
16568 * The value ·must· be in the
16569 * ·value space· of the ·base type·.
16570 */
16571 /*
16572 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016573 * on the facet. In this implementation of XML Schemata the
16574 * type holding a facet, won't be a built-in type.
16575 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016576 * calls (relaxng) do work, if the given type is a built-in
16577 * type, we will assume that the given built-in type *is
16578 * already* the base type.
16579 */
16580 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16581 base = typeDecl->baseType;
16582 if (base == NULL) {
16583 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016584 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016585 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016586 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016587 typeDecl->name, NULL);
16588 return (-1);
16589 }
16590 } else
16591 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016592 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016593 * This avoids perseverative creation of the
16594 * validation context if a parser context is
16595 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016596 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016597 if (ctxt != NULL) {
16598 reuseValCtxt = 1;
16599 if (ctxt->vctxt == NULL) {
16600 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16601 return (-1);
16602 }
16603 vctxt = ctxt->vctxt;
16604 } else {
16605 vctxt = xmlSchemaNewValidCtxt(NULL);
16606 if (vctxt == NULL) {
16607 xmlSchemaPErr(ctxt, typeDecl->node,
16608 XML_SCHEMAP_INTERNAL,
16609 "Internal error: xmlSchemaCheckFacet, "
16610 "creating a new validation context.\n",
16611 NULL, NULL);
16612 return (-1);
16613 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016614 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016615
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016616 vctxt->node = facet->node;
16617 vctxt->cur = NULL;
16618 /*
16619 * NOTE: This call does not check the content nodes,
16620 * since they are not available:
16621 * facet->node is just the node holding the facet
16622 * definition, *not* the attribute holding the *value*
16623 * of the facet.
16624 */
16625 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016626 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016627 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016628 /* error code */
16629 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016630 xmlChar *str = NULL;
16631
16632 xmlSchemaPCustomErrExt(ctxt,
16633 XML_SCHEMAP_INVALID_FACET_VALUE,
16634 NULL, (xmlSchemaTypePtr) facet, facet->node,
16635 "The value '%s' of the facet does not validate "
16636 "against the base type '%s'",
16637 facet->value,
16638 xmlSchemaFormatQName(&str,
16639 base->targetNamespace, base->name), NULL);
16640 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016641 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016642 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016643 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016644 } else if (ret < 0) {
16645 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016646 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016647 NULL, NULL, NULL,
16648 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016649 "failed to validate the value '%s' name of the "
16650 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016651 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016652 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016653 base->name, NULL, NULL);
16654 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016655 } else {
16656 if (vctxt->value != NULL) {
16657 facet->val = vctxt->value;
16658 vctxt->value = NULL;
16659 } else {
16660 xmlChar *str;
16661 /*
16662 * Ensure computed values even for type string.
16663 * TODO OPTIMIZE MEMORY: The value will be hold twice,
16664 * by the facet->value and by the computed value.
16665 */
16666 str = xmlStrdup(facet->value);
16667 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
16668 BAD_CAST str, &(facet->val)) == -1) {
16669 FREE_AND_NULL(str)
16670 xmlSchemaPErr(ctxt, typeDecl->node,
16671 XML_SCHEMAP_INTERNAL,
16672 "Internal error: xmlSchemaCheckFacet, "
16673 "post-creating a computed value.\n",
16674 NULL, NULL);
16675 /* Note that we don't return a failure yet.*/
16676 }
16677 }
16678 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016679 if (reuseValCtxt == 0)
16680 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016681 break;
16682 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016683 case XML_SCHEMA_FACET_PATTERN:
16684 facet->regexp = xmlRegexpCompile(facet->value);
16685 if (facet->regexp == NULL) {
16686 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016687 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016688 "Type definition '%s': The value '%s' of the "
16689 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016690 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016691 ret = -1;
16692 }
16693 break;
16694 case XML_SCHEMA_FACET_TOTALDIGITS:
16695 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16696 case XML_SCHEMA_FACET_LENGTH:
16697 case XML_SCHEMA_FACET_MAXLENGTH:
16698 case XML_SCHEMA_FACET_MINLENGTH:{
16699 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016700
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016701 tmp =
16702 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
16703 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016704 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016705 if (tmp != 0) {
16706 /* error code */
16707 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016708 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016709 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016710 NULL, (xmlSchemaTypePtr) facet, facet->node,
16711 "The value '%s' of the facet is not a valid "
16712 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016713 }
16714 ret = -1;
16715 }
16716 break;
16717 }
16718 case XML_SCHEMA_FACET_WHITESPACE:{
16719 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16720 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16721 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16722 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16723 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16724 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16725 } else {
16726 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016727 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
16728 xmlSchemaPCustomErr(ctxt,
16729 XML_SCHEMAP_INVALID_FACET_VALUE,
16730 NULL, (xmlSchemaTypePtr) facet, facet->node,
16731 "The value '%s' of the facet is not a valid",
16732 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016733 }
16734 ret = -1;
16735 }
16736 }
16737 default:
16738 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016739 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016740 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016741}
16742
16743/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016744 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016745 * @typeDecl: the schema type definition
16746 * @ctxt: the schema parser context
16747 *
16748 * Checks the default values types, especially for facets
16749 */
16750static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016751xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16752 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016753{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016754 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016755 /*
16756 * NOTE: It is intended to use the facets list, instead
16757 * of facetSet.
16758 */
16759 if (typeDecl->facets != NULL) {
16760 xmlSchemaFacetPtr facet = typeDecl->facets;
16761
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016762 /*
16763 * Temporarily assign the "schema" to the validation context
16764 * of the parser context. This is needed for NOTATION validation.
16765 */
16766 if (ctxt->vctxt == NULL) {
16767 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16768 return;
16769 }
16770 ctxt->vctxt->schema = ctxt->schema;
16771
Daniel Veillard01fa6152004-06-29 17:04:39 +000016772 while (facet != NULL) {
16773 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16774 facet = facet->next;
16775 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016776
16777 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016778 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016779}
16780
16781/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016782 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016783 * @ctxtMGroup: the searched model group
16784 * @selfMGroup: the second searched model group
16785 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016786 *
16787 * This one is intended to be used by
16788 * xmlSchemaCheckGroupDefCircular only.
16789 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016790 * Returns the particle with the circular model group definition reference,
16791 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016792 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016793static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016794xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016795 xmlSchemaTreeItemPtr particle)
16796{
16797 xmlSchemaTreeItemPtr circ = NULL;
16798 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016799 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016800
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016801 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016802 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016803 if (term == NULL)
16804 continue;
16805 switch (term->type) {
16806 case XML_SCHEMA_TYPE_GROUP:
16807 gdef = (xmlSchemaModelGroupDefPtr) term;
16808 if (gdef == groupDef)
16809 return (particle);
16810 /*
16811 * Mark this model group definition to avoid infinite
16812 * recursion on circular references not yet examined.
16813 */
16814 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16815 continue;
16816 if (gdef->children != NULL) {
16817 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16818 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16819 gdef->children->children);
16820 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16821 if (circ != NULL)
16822 return (circ);
16823 }
16824 break;
16825 case XML_SCHEMA_TYPE_SEQUENCE:
16826 case XML_SCHEMA_TYPE_CHOICE:
16827 case XML_SCHEMA_TYPE_ALL:
16828 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16829 if (circ != NULL)
16830 return (circ);
16831 break;
16832 default:
16833 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016834 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016835 }
16836 return (NULL);
16837}
16838
16839/**
16840 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016841 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016842 * @ctxt: the parser context
16843 * @name: the name
16844 *
16845 * Checks for circular references to model group definitions.
16846 */
16847static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016848xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016849 xmlSchemaParserCtxtPtr ctxt,
16850 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016851{
16852 /*
16853 * Schema Component Constraint: Model Group Correct
16854 * 2 Circular groups are disallowed. That is, within the {particles}
16855 * of a group there must not be at any depth a particle whose {term}
16856 * is the group itself.
16857 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016858 if ((item == NULL) ||
16859 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16860 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016861 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016862 {
16863 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016864
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016865 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016866 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016867 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016868 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016869 * TODO: The error report is not adequate: this constraint
16870 * is defined for model groups but not definitions, but since
16871 * there cannot be any circular model groups without a model group
16872 * definition (if not using a construction API), we check those
16873 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016874 */
16875 xmlSchemaPCustomErr(ctxt,
16876 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016877 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016878 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016879 "defined", xmlSchemaFormatQName(&str,
16880 item->targetNamespace, item->name));
16881 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016882 /*
16883 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016884 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016885 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016886 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016887 }
16888 }
16889}
16890
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016891/**
16892 * xmlSchemaGroupDefTermFixup:
16893 * @item: the particle with a model group definition as term
16894 * @ctxt: the parser context
16895 * @name: the name
16896 *
16897 * Checks for circular references to model group definitions.
16898 * Additionally it
16899 */
16900static void
16901xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
16902 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
16903 const xmlChar * name ATTRIBUTE_UNUSED)
16904{
16905 if ((item == NULL) ||
16906 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16907 (item->children == NULL) ||
16908 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16909 (item->children->children == NULL))
16910 return;
16911 item->children = item->children->children;
16912}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016913
16914/**
16915 * xmlSchemaGetCircAttrGrRef:
16916 * @ctxtGr: the searched attribute group
16917 * @attr: the current attribute list to be processed
16918 *
16919 * This one is intended to be used by
16920 * xmlSchemaCheckSRCAttributeGroupCircular only.
16921 *
16922 * Returns the circular attribute grou reference, otherwise NULL.
16923 */
16924static xmlSchemaAttributeGroupPtr
16925xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16926 xmlSchemaAttributePtr attr)
16927{
16928 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16929 int marked;
16930 /*
16931 * We will search for an attribute group reference which
16932 * references the context attribute group.
16933 */
16934 while (attr != NULL) {
16935 marked = 0;
16936 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16937 gr = (xmlSchemaAttributeGroupPtr) attr;
16938 if (gr->refItem != NULL) {
16939 if (gr->refItem == ctxtGr)
16940 return (gr);
16941 else if (gr->refItem->flags &
16942 XML_SCHEMAS_ATTRGROUP_MARKED) {
16943 attr = attr->next;
16944 continue;
16945 } else {
16946 /*
16947 * Mark as visited to avoid infinite recursion on
16948 * circular references not yet examined.
16949 */
16950 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16951 marked = 1;
16952 }
16953 }
16954 if (gr->attributes != NULL)
16955 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16956 /*
16957 * Unmark the visited group's attributes.
16958 */
16959 if (marked)
16960 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16961 if (circ != NULL)
16962 return (circ);
16963 }
16964 attr = attr->next;
16965 }
16966 return (NULL);
16967}
16968
16969/**
16970 * xmlSchemaCheckSRCAttributeGroupCircular:
16971 * attrGr: the attribute group definition
16972 * @ctxt: the parser context
16973 * @name: the name
16974 *
16975 * Checks for circular references of attribute groups.
16976 */
16977static void
16978xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
16979 xmlSchemaParserCtxtPtr ctxt,
16980 const xmlChar * name ATTRIBUTE_UNUSED)
16981{
16982 /*
16983 * Schema Representation Constraint:
16984 * Attribute Group Definition Representation OK
16985 * 3 Circular group reference is disallowed outside <redefine>.
16986 * That is, unless this element information item's parent is
16987 * <redefine>, then among the [children], if any, there must
16988 * not be an <attributeGroup> with ref [attribute] which resolves
16989 * to the component corresponding to this <attributeGroup>. Indirect
16990 * circularity is also ruled out. That is, when QName resolution
16991 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16992 * any <attributeGroup>s with a ref [attribute] among the [children],
16993 * it must not be the case that a ·QName· is encountered at any depth
16994 * which resolves to the component corresponding to this <attributeGroup>.
16995 */
16996 /*
16997 * Only global components can be referenced.
16998 */
16999 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
17000 (attrGr->attributes == NULL))
17001 return;
17002 else {
17003 xmlSchemaAttributeGroupPtr circ;
17004
17005 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
17006 if (circ != NULL) {
17007 /*
17008 * TODO: Report the referenced attr group as QName.
17009 */
17010 xmlSchemaPCustomErr(ctxt,
17011 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17012 NULL, NULL, circ->node,
17013 "Circular reference to the attribute group '%s' "
17014 "defined", attrGr->name);
17015 /*
17016 * NOTE: We will cut the reference to avoid further
17017 * confusion of the processor.
17018 * BADSPEC: The spec should define how to process in this case.
17019 */
17020 circ->attributes = NULL;
17021 circ->refItem = NULL;
17022 }
17023 }
17024}
17025
17026/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017027 * xmlSchemaAttrGrpFixup:
17028 * @attrgrpDecl: the schema attribute definition
17029 * @ctxt: the schema parser context
17030 * @name: the attribute name
17031 *
17032 * Fixes finish doing the computations on the attributes definitions
17033 */
17034static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017035xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017036 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017037{
17038 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017039 name = attrgrp->name;
17040 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017041 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017042 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017043 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017044
Daniel Veillardc0826a72004-08-10 14:17:33 +000017045 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
17046 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017047 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017048 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017049 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017050 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17051 "ref", attrgrp->ref, attrgrp->refNs,
17052 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017053 return;
17054 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017055 attrgrp->refItem = ref;
17056 /*
17057 * Check for self reference!
17058 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017059 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017060 attrgrp->attributes = ref->attributes;
17061 attrgrp->attributeWildcard = ref->attributeWildcard;
17062 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017063}
17064
17065/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017066 * xmlSchemaAttrCheckValConstr:
17067 * @item: an schema attribute declaration/use
17068 * @ctxt: a schema parser context
17069 * @name: the name of the attribute
17070 *
17071 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017072 *
17073 * Fixes finish doing the computations on the attributes definitions
17074 */
17075static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017076xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
17077 xmlSchemaParserCtxtPtr ctxt,
17078 const xmlChar * name ATTRIBUTE_UNUSED)
17079{
17080
17081 /*
17082 * a-props-correct
17083 * Schema Component Constraint: Attribute Declaration Properties Correct
17084 *
17085 * 2 if there is a {value constraint}, the canonical lexical
17086 * representation of its value must be ·valid· with respect
17087 * to the {type definition} as defined in String Valid (§3.14.4).
17088 */
17089
17090 if (item->defValue != NULL) {
17091 int ret;
17092 xmlNodePtr node;
17093 xmlSchemaTypePtr type;
17094
17095 if (item->subtypes == NULL) {
17096 xmlSchemaPErr(ctxt, item->node,
17097 XML_SCHEMAP_INTERNAL,
17098 "Internal error: xmlSchemaCheckAttrValConstr, "
17099 "type is missing... skipping validation of "
17100 "value constraint", NULL, NULL);
17101 return;
17102 }
17103
17104 /*
17105 * TODO: Try to avoid creating a new context.
17106 * TODO: This all is not very performant.
17107 */
17108 type = item->subtypes;
17109 /*
17110 * Ensure there's validation context.
17111 */
17112 if (ctxt->vctxt == NULL) {
17113 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
17114 xmlSchemaPErr(ctxt, item->node,
17115 XML_SCHEMAP_INTERNAL,
17116 "Internal error: xmlSchemaCheckAttrValConstr, "
17117 "creating a new validation context.\n",
17118 NULL, NULL);
17119 return;
17120 }
17121 }
17122
17123 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
17124 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
17125 else
17126 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
17127 ctxt->vctxt->node = node;
17128 ctxt->vctxt->cur = NULL;
17129 /*
17130 * NOTE: This call does not check the content nodes,
17131 * since they are not available:
17132 * facet->node is just the node holding the facet
17133 * definition, *not* the attribute holding the *value*
17134 * of the facet.
17135 */
17136 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
17137 item->defValue, 0, 1, 1, 0);
17138 if (ret == 0) {
17139 /*
17140 * Store the computed value.
17141 */
17142 item->defVal = ctxt->vctxt->value;
17143 ctxt->vctxt->value = NULL;
17144 } else if (ret > 0) {
17145 if (ctxt != NULL) {
17146 xmlSchemaPSimpleTypeErr(ctxt,
17147 XML_SCHEMAP_A_PROPS_CORRECT_2,
17148 NULL, NULL, node,
17149 type, NULL, item->defValue,
17150 NULL, NULL, NULL);
17151 }
17152 } else if (ret < 0) {
17153 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
17154 NULL, NULL, node,
17155 "Internal error: xmlSchemaAttrCheckValConstr, "
17156 "failed to validate the value constraint of the "
17157 "attribute decl/use against the type '%s'",
17158 type->name);
17159 }
17160 }
17161}
17162
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017163static xmlSchemaElementPtr
17164xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17165 xmlSchemaElementPtr ancestor)
17166{
17167 xmlSchemaElementPtr ret;
17168
17169 if (SUBST_GROUP_AFF(ancestor) == NULL)
17170 return (NULL);
17171 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17172 return (ancestor);
17173
17174 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17175 return (NULL);
17176 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17177 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17178 SUBST_GROUP_AFF(ancestor));
17179 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17180
17181 return (ret);
17182}
17183
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017184/**
17185 * xmlSchemaCheckElemPropsCorrect:
17186 * @ctxt: a schema parser context
17187 * @decl: the element declaration
17188 * @name: the name of the attribute
17189 *
17190 * Schema Component Constraint:
17191 * Element Declaration Properties Correct (e-props-correct)
17192 *
17193 * STATUS:
17194 * missing: (6)
17195 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017196static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017197xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17198 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017199{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017200 int ret = 0;
17201 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017202 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017203 * SPEC (1) "The values of the properties of an element declaration
17204 * must be as described in the property tableau in The Element
17205 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17206 * Sub-components (§5.3)."
17207 */
17208 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017209 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017210 /*
17211 * SPEC (3) "If there is a non-·absent· {substitution group
17212 * affiliation}, then {scope} must be global."
17213 */
17214 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17215 xmlSchemaPCustomErr(pctxt,
17216 XML_SCHEMAP_E_PROPS_CORRECT_3,
17217 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17218 "Only global element declarations can have a "
17219 "substitution group affiliation", NULL);
17220 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017221 }
17222 /*
17223 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17224 * That is, it must not be possible to return to an element declaration
17225 * by repeatedly following the {substitution group affiliation}
17226 * property."
17227 */
17228 if (head == elemDecl)
17229 circ = head;
17230 else if (SUBST_GROUP_AFF(head) != NULL)
17231 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17232 else
17233 circ = NULL;
17234 if (circ != NULL) {
17235 xmlChar *strA = NULL, *strB = NULL;
17236
17237 xmlSchemaPCustomErrExt(pctxt,
17238 XML_SCHEMAP_E_PROPS_CORRECT_6,
17239 NULL, (xmlSchemaTypePtr) circ, circ->node,
17240 "The element declaration '%s' defines a circular "
17241 "substitution group to element declaration '%s'",
17242 xmlSchemaGetComponentQName(&strA, circ),
17243 xmlSchemaGetComponentQName(&strB, head),
17244 NULL);
17245 FREE_AND_NULL(strA)
17246 FREE_AND_NULL(strB)
17247 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17248 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017249 /*
17250 * SPEC (4) "If there is a {substitution group affiliation},
17251 * the {type definition}
17252 * of the element declaration must be validly derived from the {type
17253 * definition} of the {substitution group affiliation}, given the value
17254 * of the {substitution group exclusions} of the {substitution group
17255 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17256 * (if the {type definition} is complex) or as defined in
17257 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
17258 * simple)."
17259 *
17260 * NOTE: {substitution group exclusions} means the values of the
17261 * attribute "final".
17262 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017263
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017264 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
17265 int set = 0;
17266
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017267 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017268 set |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017269 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017270 set |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
17271
17272 if (xmlSchemaCheckCOSDerivedOK(pctxt->schema, typeDef,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017273 ELEM_TYPE(head), set) != 0) {
17274 xmlChar *strA = NULL, *strB = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017275
17276 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
17277 xmlSchemaPCustomErrExt(pctxt,
17278 XML_SCHEMAP_E_PROPS_CORRECT_4,
17279 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017280 "The type definition of element declaration '%s' is not "
17281 "validly derived from the type definition of its "
17282 "substitution group affiliation '%s'",
17283 xmlSchemaGetComponentQName(&strA, elemDecl),
17284 xmlSchemaGetComponentQName(&strB, head),
17285 NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017286 FREE_AND_NULL(strA)
17287 FREE_AND_NULL(strB)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017288 }
17289 }
17290 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017291 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017292 * SPEC (5) "If the {type definition} or {type definition}'s
17293 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017294 * is or is derived from ID then there must not be a {value constraint}.
17295 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017296 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017297 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017298 if ((elemDecl->value != NULL) &&
17299 ((IS_SIMPLE_TYPE(typeDef) &&
17300 xmlSchemaIsDerivedFromBuiltInType(pctxt,
17301 ELEM_TYPE(elemDecl), XML_SCHEMAS_ID)) ||
17302 (IS_COMPLEX_TYPE(typeDef) &&
17303 HAS_SIMPLE_CONTENT(typeDef) &&
17304 xmlSchemaIsDerivedFromBuiltInType(pctxt,
17305 typeDef->contentTypeDef, XML_SCHEMAS_ID)))) {
17306
17307 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17308 xmlSchemaPCustomErr(pctxt,
17309 XML_SCHEMAP_E_PROPS_CORRECT_5,
17310 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17311 "The type definition (or type definition's content type) is or "
17312 "is derived from ID; value constraints are not allowed in "
17313 "conjunction with such a type definition", NULL);
17314 } else if (elemDecl->value != NULL) {
17315 int vcret;
17316 xmlNodePtr node = NULL;
17317
17318 /*
17319 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17320 * representation of its value must be ·valid· with respect to the
17321 * {type definition} as defined in Element Default Valid (Immediate)
17322 * (§3.3.6)."
17323 */
17324 if (typeDef == NULL) {
17325 xmlSchemaPErr(pctxt, elemDecl->node,
17326 XML_SCHEMAP_INTERNAL,
17327 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17328 "type is missing... skipping validation of "
17329 "the value constraint", NULL, NULL);
17330 return (-1);
17331 }
17332 /*
17333 * Ensure there's a validation context.
17334 */
17335 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
17336 return (-1);
17337 if (elemDecl->node != NULL) {
17338 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17339 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17340 BAD_CAST "fixed");
17341 else
17342 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17343 BAD_CAST "default");
17344 }
17345 pctxt->vctxt->node = node;
17346 pctxt->vctxt->cur = NULL;
17347 vcret = xmlSchemaCheckCOSValidDefault(pctxt, pctxt->vctxt, typeDef,
17348 elemDecl->value, node);
17349 if (vcret == 0) {
17350 /*
17351 * Consume the computed value.
17352 */
17353 elemDecl->defVal = pctxt->vctxt->value;
17354 pctxt->vctxt->value = NULL;
17355 } else if (vcret < 0) {
17356 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_INTERNAL,
17357 NULL, NULL, node,
17358 "Internal error: xmlSchemaElemCheckValConstr, "
17359 "failed to validate the value constraint of the "
17360 "element declaration '%s'",
17361 elemDecl->name);
17362 ret = vcret;
17363 } else
17364 ret = vcret;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017365 }
17366
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017367 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017368}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017369
17370/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017371 * xmlSchemaCheckElemSubstGroup:
17372 * @ctxt: a schema parser context
17373 * @decl: the element declaration
17374 * @name: the name of the attribute
17375 *
17376 * Schema Component Constraint:
17377 * Substitution Group (cos-equiv-class)
17378 *
17379 * In Libxml2 the subst. groups will be precomputed, in terms of that
17380 * a list will be built for each subst. group head, holding all direct
17381 * referents to this head.
17382 * NOTE that this function needs:
17383 * 1. circular subst. groups to be checked beforehand
17384 * 2. the declaration's type to be derived from the head's type
17385 *
17386 * STATUS:
17387 *
17388 */
17389static void
17390xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17391 xmlSchemaElementPtr elemDecl)
17392{
17393 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17394 /* SPEC (1) "Its {abstract} is false." */
17395 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17396 return;
17397 {
17398 xmlSchemaElementPtr head;
17399 xmlSchemaTypePtr headType, type;
17400 int set, methSet;
17401 /*
17402 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17403 * {disallowed substitutions} as the blocking constraint, as defined in
17404 * Substitution Group OK (Transitive) (§3.3.6)."
17405 */
17406 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17407 head = SUBST_GROUP_AFF(head)) {
17408 set = 0;
17409 methSet = 0;
17410 /*
17411 * The blocking constraints.
17412 */
17413 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17414 continue;
17415 headType = head->subtypes;
17416 type = elemDecl->subtypes;
17417 if (headType == type)
17418 goto add_member;
17419 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17420 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17421 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17422 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17423 /*
17424 * SPEC: Substitution Group OK (Transitive) (2.3)
17425 * "The set of all {derivation method}s involved in the
17426 * derivation of D's {type definition} from C's {type definition}
17427 * does not intersect with the union of the blocking constraint,
17428 * C's {prohibited substitutions} (if C is complex, otherwise the
17429 * empty set) and the {prohibited substitutions} (respectively the
17430 * empty set) of any intermediate {type definition}s in the
17431 * derivation of D's {type definition} from C's {type definition}."
17432 */
17433 /*
17434 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17435 * subst.head axis, the methSet does not need to be computed for
17436 * the full depth over and over.
17437 */
17438 /*
17439 * The set of all {derivation method}s involved in the derivation
17440 */
17441 while ((type != NULL) && (type != headType)) {
17442 if ((type->flags &
17443 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17444 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17445 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17446
17447 if ((type->flags &
17448 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17449 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17450 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17451
17452 type = type->baseType;
17453 }
17454 /*
17455 * The {prohibited substitutions} of all intermediate types +
17456 * the head's type.
17457 */
17458 type = elemDecl->subtypes->baseType;
17459 while (type != NULL) {
17460 if (IS_COMPLEX_TYPE(type)) {
17461 if ((type->flags &
17462 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17463 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17464 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17465 if ((type->flags &
17466 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17467 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17468 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17469 } else
17470 break;
17471 if (type == headType)
17472 break;
17473 type = type->baseType;
17474 }
17475 if ((set != 0) &&
17476 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17477 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17478 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17479 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17480 continue;
17481 }
17482add_member:
17483 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17484 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17485 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17486 }
17487 }
17488}
17489
17490/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017491 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017492 * @item: an schema element declaration/particle
17493 * @ctxt: a schema parser context
17494 * @name: the name of the attribute
17495 *
17496 * Validates the value constraints of an element declaration.
17497 *
17498 * Fixes finish doing the computations on the element declarations.
17499 */
17500static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017501xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
17502 xmlSchemaParserCtxtPtr ctxt,
17503 const xmlChar * name ATTRIBUTE_UNUSED)
17504{
17505 if (elemDecl == NULL)
17506 return;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017507 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17508 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017509}
17510
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017511/**
17512 * xmlSchemaMiscRefFixup:
17513 * @item: an schema component
17514 * @ctxt: a schema parser context
17515 * @name: the internal name of the component
17516 *
17517 * Resolves references of misc. schema components.
17518 */
17519static void
17520xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
17521 xmlSchemaParserCtxtPtr ctxt,
17522 const xmlChar * name ATTRIBUTE_UNUSED)
17523{
17524 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
17525 if ((item->children != NULL) &&
17526 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17527 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17528 xmlSchemaTreeItemPtr refItem;
17529 /*
17530 * Resolve the reference.
17531 */
17532 item->children = NULL;
17533 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17534 ref->itemType, ref->name, ref->targetNamespace);
17535 if (refItem == NULL) {
17536 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
17537 NULL, NULL, GET_NODE(item), "ref", ref->name,
17538 ref->targetNamespace, ref->itemType, NULL);
17539 } else {
17540 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17541 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017542 * NOTE that we will assign the model group definition
17543 * itself to the "term" of the particle. This will ease
17544 * the check for circular model group definitions. After
17545 * that the "term" will be assigned the model group of the
17546 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017547 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017548 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017549 } else
17550 item->children = refItem;
17551 }
17552 }
17553 }
17554}
17555
17556
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017557/**
17558 * xmlSchemaAttrFixup:
17559 * @item: an schema attribute declaration/use.
17560 * @ctxt: a schema parser context
17561 * @name: the name of the attribute
17562 *
17563 * Fixes finish doing the computations on attribute declarations/uses.
17564 */
17565static void
17566xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
17567 xmlSchemaParserCtxtPtr ctxt,
17568 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017569{
Daniel Veillardc0826a72004-08-10 14:17:33 +000017570 /*
17571 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017572 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017573 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017574 /*
17575 * The simple type definition corresponding to the <simpleType> element
17576 * information item in the [children], if present, otherwise the simple
17577 * type definition ·resolved· to by the ·actual value· of the type
17578 * [attribute], if present, otherwise the ·simple ur-type definition·.
17579 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017580 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017581 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017582 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17583 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017584 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017585 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017586 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017587
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017588 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17589 item->typeNs);
17590 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017591 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017592 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017593 NULL, (xmlSchemaTypePtr) item, item->node,
17594 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017595 XML_SCHEMA_TYPE_SIMPLE, NULL);
17596 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017597 item->subtypes = type;
17598
17599 } else if (item->ref != NULL) {
17600 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017601
Daniel Veillardc0826a72004-08-10 14:17:33 +000017602 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017603 * We have an attribute use here; assign the referenced
17604 * attribute declaration.
17605 */
17606 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017607 * TODO: Evaluate, what errors could occur if the declaration is not
17608 * found. It might be possible that the "typefixup" might crash if
17609 * no ref declaration was found.
17610 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017611 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
17612 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017613 xmlSchemaPResCompAttrErr(ctxt,
17614 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017615 NULL, (xmlSchemaTypePtr) item, item->node,
17616 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017617 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017618 return;
17619 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017620 item->refDecl = decl;
17621 xmlSchemaAttrFixup(decl, ctxt, NULL);
17622
17623 item->subtypes = decl->subtypes;
17624 /*
17625 * Attribute Use Correct
17626 * au-props-correct.2: If the {attribute declaration} has a fixed
17627 * {value constraint}, then if the attribute use itself has a
17628 * {value constraint}, it must also be fixed and its value must match
17629 * that of the {attribute declaration}'s {value constraint}.
17630 */
17631 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
17632 (item->defValue != NULL)) {
17633 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
17634 (!xmlStrEqual(item->defValue, decl->defValue))) {
17635 xmlSchemaPCustomErr(ctxt,
17636 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17637 NULL, NULL, item->node,
17638 "The value constraint must be fixed "
17639 "and match the referenced attribute "
17640 "declarations's value constraint '%s'",
17641 decl->defValue);
17642 }
17643 /*
17644 * FUTURE: One should change the values of the attr. use
17645 * if ever validation should be attempted even if the
17646 * schema itself was not fully valid.
17647 */
17648 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017649 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017650 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17651 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017652}
17653
17654/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017655 * xmlSchemaResolveIDCKeyRef:
17656 * @idc: the identity-constraint definition
17657 * @ctxt: the schema parser context
17658 * @name: the attribute name
17659 *
17660 * Resolve keyRef references to key/unique IDCs.
17661 */
17662static void
17663xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
17664 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017665 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017666{
17667 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17668 return;
17669 if (idc->ref->name != NULL) {
17670 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
17671 ctxt->schema->idcDef,
17672 idc->ref->name,
17673 idc->ref->targetNamespace);
17674 if (idc->ref->item == NULL) {
17675 /*
17676 * TODO: It is actually not an error to fail to resolve.
17677 */
17678 xmlSchemaPResCompAttrErr(ctxt,
17679 XML_SCHEMAP_SRC_RESOLVE,
17680 NULL, (xmlSchemaTypePtr) idc, idc->node,
17681 "refer", idc->ref->name,
17682 idc->ref->targetNamespace,
17683 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17684 return;
17685 }
17686 }
17687}
17688
17689/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017690 * xmlSchemaParse:
17691 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017692 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017693 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017694 * XML Shema struture which can be used to validate instances.
17695 * *WARNING* this interface is highly subject to change
17696 *
17697 * Returns the internal XML Schema structure built from the resource or
17698 * NULL in case of error
17699 */
17700xmlSchemaPtr
17701xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17702{
17703 xmlSchemaPtr ret = NULL;
17704 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017705 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017706 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017707
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017708 /*
17709 * This one is used if the schema to be parsed was specified via
17710 * the API; i.e. not automatically by the validated instance document.
17711 */
17712
Daniel Veillard4255d502002-04-16 15:50:10 +000017713 xmlSchemaInitTypes();
17714
Daniel Veillard6045c902002-10-09 21:13:59 +000017715 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017716 return (NULL);
17717
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017718 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017719 ctxt->counter = 0;
17720 ctxt->container = NULL;
17721
17722 /*
17723 * First step is to parse the input document into an DOM/Infoset
17724 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017725 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017726 doc = xmlReadFile((const char *) ctxt->URL, NULL,
17727 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017728 if (doc == NULL) {
17729 xmlSchemaPErr(ctxt, NULL,
17730 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017731 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017732 ctxt->URL, NULL);
17733 return (NULL);
17734 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017735 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017736 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17737 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017738 if (doc == NULL) {
17739 xmlSchemaPErr(ctxt, NULL,
17740 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017741 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017742 NULL, NULL);
17743 return (NULL);
17744 }
17745 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017746 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017747 } else if (ctxt->doc != NULL) {
17748 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017749 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017750 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017751 xmlSchemaPErr(ctxt, NULL,
17752 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017753 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017754 NULL, NULL);
17755 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017756 }
17757
17758 /*
17759 * Then extract the root and Schema parse it
17760 */
17761 root = xmlDocGetRootElement(doc);
17762 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017763 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17764 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017765 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017766 if (!preserve) {
17767 xmlFreeDoc(doc);
17768 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017769 return (NULL);
17770 }
17771
17772 /*
17773 * Remove all the blank text nodes
17774 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017775 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017776
17777 /*
17778 * Then do the parsing for good
17779 */
17780 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017781 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017782 if (!preserve) {
17783 xmlFreeDoc(doc);
17784 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017785 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017786 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017787 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017788 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017789 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017790 ctxt->ctxtType = NULL;
17791 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017792
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017793 /*
17794 * Resolve base types of simple/complex types.
17795 */
17796 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
17797
17798 if (ctxt->nberrors != 0)
17799 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017800
17801 if (ret->volatiles != NULL) {
17802 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17803 int i;
17804 xmlSchemaTreeItemPtr item;
17805
17806 for (i = 0; i < list->nbItems; i++) {
17807 item = (xmlSchemaTreeItemPtr) list->items[i];
17808 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17809 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017810 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017811 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017812 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017813 * Then fixup all attributes declarations
17814 */
17815 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017816 /*
17817 * Then fixup all attributes group declarations
17818 */
17819 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17820 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017821 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017822 * Resolve identity-constraint keyRefs.
17823 */
17824 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017825 /*
17826 * Check type defnitions for circular references.
17827 */
17828 xmlHashScan(ret->typeDecl, (xmlHashScanner)
17829 xmlSchemaCheckTypeDefCircular, ctxt);
17830 /*
17831 * Check model groups defnitions for circular references.
17832 */
17833 xmlHashScan(ret->groupDecl, (xmlHashScanner)
17834 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017835 /*
17836 * Set the "term" of particles pointing to model group definitions
17837 * to the contained model group.
17838 */
17839 if (ret->volatiles != NULL) {
17840 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17841 int i;
17842 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017843
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017844 for (i = 0; i < list->nbItems; i++) {
17845 item = (xmlSchemaParticlePtr) list->items[i];
17846 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17847 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17848 }
17849 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017850 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017851 * Check attribute groups for circular references.
17852 */
17853 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017854 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017855 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017856 * Then fix references of element declaration; apply constraints.
17857 */
17858 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017859 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017860 /*
17861 * We will stop here if the schema was not valid to avoid internal errors
17862 * on missing sub-components. This is not conforming to the spec, since it
17863 * allows missing components, but it might make further processing crash.
17864 * So see it as a very strict handling, which might be made more lax in the
17865 * future.
17866 */
17867 if (ctxt->nberrors != 0)
17868 goto exit;
17869 /*
17870 * Then fixup all types properties
17871 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017872 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017873 /*
17874 * Validate the value constraint of attribute declarations/uses.
17875 */
17876 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017877 /*
17878 * Validate the value constraint of element declarations.
17879 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017880 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017881 /*
17882 * Then build the content model for all complex types
17883 */
17884 xmlHashScan(ret->typeDecl,
17885 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017886
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017887exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017888 if (ctxt->nberrors != 0) {
17889 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017890 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017891 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017892 return (ret);
17893}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017894
Daniel Veillard4255d502002-04-16 15:50:10 +000017895/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017896 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017897 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017898 * @err: the error callback
17899 * @warn: the warning callback
17900 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017901 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017902 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017903 */
17904void
17905xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017906 xmlSchemaValidityErrorFunc err,
17907 xmlSchemaValidityWarningFunc warn, void *ctx)
17908{
Daniel Veillard4255d502002-04-16 15:50:10 +000017909 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017910 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017911 ctxt->error = err;
17912 ctxt->warning = warn;
17913 ctxt->userData = ctx;
17914}
17915
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017916/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017917 * xmlSchemaGetParserErrors:
17918 * @ctxt: a XMl-Schema parser context
17919 * @err: the error callback result
17920 * @warn: the warning callback result
17921 * @ctx: contextual data for the callbacks result
17922 *
17923 * Get the callback information used to handle errors for a parser context
17924 *
17925 * Returns -1 in case of failure, 0 otherwise
17926 */
17927int
17928xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17929 xmlSchemaValidityErrorFunc * err,
17930 xmlSchemaValidityWarningFunc * warn, void **ctx)
17931{
17932 if (ctxt == NULL)
17933 return(-1);
17934 if (err != NULL)
17935 *err = ctxt->error;
17936 if (warn != NULL)
17937 *warn = ctxt->warning;
17938 if (ctx != NULL)
17939 *ctx = ctxt->userData;
17940 return(0);
17941}
17942
17943/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017944 * xmlSchemaFacetTypeToString:
17945 * @type: the facet type
17946 *
17947 * Convert the xmlSchemaTypeType to a char string.
17948 *
17949 * Returns the char string representation of the facet type if the
17950 * type is a facet and an "Internal Error" string otherwise.
17951 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017952static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017953xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17954{
17955 switch (type) {
17956 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017957 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017958 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017959 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017960 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017961 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017962 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017963 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017964 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017965 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017966 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017967 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017968 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017969 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017970 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017971 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017972 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017973 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017974 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017975 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017976 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017977 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017978 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017979 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017980 default:
17981 break;
17982 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017983 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017984}
17985
Daniel Veillardc0826a72004-08-10 14:17:33 +000017986static int
17987xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17988{
17989 xmlSchemaTypePtr anc;
17990
17991 /*
17992 * The normalization type can be changed only for types which are derived
17993 * from xsd:string.
17994 */
17995 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017996 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017997 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017998 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017999 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018000 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
18001 /*
18002 * Note that we assume a whitespace of preserve for anySimpleType.
18003 */
18004 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018005 else {
18006 /*
18007 * For all ·atomic· datatypes other than string (and types ·derived·
18008 * by ·restriction· from it) the value of whiteSpace is fixed to
18009 * collapse
18010 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018011 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018012 }
18013 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18014 /*
18015 * For list types the facet "whiteSpace" is fixed to "collapse".
18016 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018017 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018018 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018019 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018020 } else if (type->facetSet != NULL) {
18021 xmlSchemaTypePtr anyST;
18022 xmlSchemaFacetLinkPtr lin;
18023
18024 /*
18025 * Atomic types.
18026 */
18027 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
18028 anc = type->baseType;
18029 do {
18030 /*
18031 * For all ·atomic· datatypes other than string (and types ·derived·
18032 * by ·restriction· from it) the value of whiteSpace is fixed to
18033 * collapse
18034 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018035 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18036 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018037
18038 lin = type->facetSet;
18039 do {
18040 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018041 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018042 }
18043 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018044 } while (lin != NULL);
18045 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
18046 return (XML_SCHEMAS_FACET_REPLACE);
18047 else
18048 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018049 }
18050 anc = anc->baseType;
18051 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018052 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018053 }
18054 return (-1);
18055}
18056
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018057/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000018058 * xmlSchemaValidateFacetsInternal:
18059 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000018060 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000018061 * @facets: the list of facets to check
18062 * @value: the lexical repr of the value to validate
18063 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000018064 * @fireErrors: if 0, only internal errors will be fired;
18065 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000018066 *
18067 * Check a value against all facet conditions
18068 *
18069 * Returns 0 if the element is schemas valid, a positive error code
18070 * number otherwise and -1 in case of internal or API error.
18071 */
18072static int
18073xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018074 xmlSchemaTypePtr type,
18075 const xmlChar * value,
18076 unsigned long length,
18077 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000018078{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018079 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018080 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018081 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018082 xmlSchemaTypePtr tmpType;
18083 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000018084 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018085 xmlSchemaFacetPtr facet;
18086 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018087 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018088
18089 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018090
Daniel Veillardc0826a72004-08-10 14:17:33 +000018091#ifdef DEBUG_UNION_VALIDATION
18092 printf("Facets of type: '%s'\n", (const char *) type->name);
18093 printf(" fireErrors: %d\n", fireErrors);
18094#endif
18095
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018096 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018097 /*
18098 * NOTE: Do not jump away, if the facetSet of the given type is
18099 * empty: until now, "pattern" facets of the *base types* need to
18100 * be checked as well.
18101 */
18102 biType = type->baseType;
18103 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
18104 biType = biType->baseType;
18105 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018106 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018107 "Internal error: xmlSchemaValidateFacetsInternal, "
18108 "the base type axis of the given type '%s' does not resolve to "
18109 "a built-in type.\n",
18110 type->name, NULL);
18111 return (-1);
18112 }
18113
18114 if (type->facetSet != NULL) {
18115 facetLink = type->facetSet;
18116 while (facetLink != NULL) {
18117 facet = facetLink->facet;
18118 /*
18119 * Skip the pattern "whiteSpace": it is used to
18120 * format the character content beforehand.
18121 */
18122 switch (facet->type) {
18123 case XML_SCHEMA_FACET_WHITESPACE:
18124 case XML_SCHEMA_FACET_PATTERN:
18125 case XML_SCHEMA_FACET_ENUMERATION:
18126 break;
18127 case XML_SCHEMA_FACET_LENGTH:
18128 case XML_SCHEMA_FACET_MINLENGTH:
18129 case XML_SCHEMA_FACET_MAXLENGTH:
18130 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18131 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018132 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018133 len = length;
18134 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018135 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
18136 (xmlSchemaValType) biType->builtInType,
18137 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018138 break;
18139 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018140 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
18141 biType->builtInType, value, ctxt->value, ws);
18142 /*
18143 * ret = xmlSchemaValidateFacet(biType, facet, value,
18144 * ctxt->value);
18145 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018146 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018147 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018148 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018149 "Internal error: xmlSchemaValidateFacetsInternal, "
18150 "validating facet of type '%s'.\n",
18151 type->name, NULL);
18152 break;
18153 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018154 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018155 type, facet, NULL, NULL, NULL, NULL);
18156 }
18157
18158 facetLink = facetLink->next;
18159 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018160
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018161 }
18162
Daniel Veillardc0826a72004-08-10 14:17:33 +000018163 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018164 xmlSchemaWhitespaceValueType fws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018165 int found = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018166 /*
18167 * Process enumerations. Facet values are in the value space
18168 * of the defining type's base type. This seems to be a bug in the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018169 * XML Schema 1.0 spec. Use the whitespace type of the base type.
18170 * Only the first set of enumerations in the ancestor-or-self axis
18171 * is used for validation.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018172 */
18173 tmpType = type;
18174 do {
18175 /*
18176 * Use the whitespace type of the base type.
18177 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018178 fws = (xmlSchemaWhitespaceValueType)
18179 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018180 retFacet = 0;
18181 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
18182 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018183 continue;
18184 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018185 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
18186 biType->builtInType, value, ctxt->value, ws);
18187 if (retFacet == 0)
18188 break;
18189 else if (retFacet < 0) {
18190 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
18191 "Internal error: xmlSchemaValidateFacetsInternal, "
18192 "validating enumeration facet '%s' of type '%s'.\n",
18193 facet->value, tmpType->name);
18194 ret = -1;
18195 break;
18196 }
18197 }
18198 if (retFacet <= 0)
18199 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018200 tmpType = tmpType->baseType;
18201 } while ((! found) && (tmpType != NULL) &&
18202 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018203 if (retFacet > 0) {
Kasimier T. Buchcik53b5e052005-03-24 11:05:13 +000018204 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018205 if (fireErrors) {
18206 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
18207 NULL, NULL, NULL, NULL);
18208 }
18209 }
18210 }
18211
18212 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018213 /*
18214 * Process patters. Pattern facets are ORed at type level
18215 * and ANDed if derived. Walk the base type axis.
18216 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018217 tmpType = type;
18218 facet = NULL;
18219 do {
18220 retFacet = 0;
18221 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018222 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018223 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
18224 continue;
18225 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
18226 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018227 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018228 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018229 else if (retFacet < 0) {
18230 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
18231 "Internal error: xmlSchemaValidateFacetsInternal, "
18232 "validating 'pattern' facet '%s' of type '%s'.\n",
18233 facetLink->facet->value, tmpType->name);
18234 ret = -1;
18235 break;
18236 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000018237 /* Save the last non-validating facet. */
18238 facet = facetLink->facet;
18239 }
18240 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018241 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018242 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018243 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018244 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018245 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
18246 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018247 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018248 NULL, NULL, NULL, NULL);
18249 }
18250 }
18251 }
18252
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018253 return (ret);
18254}
18255
Daniel Veillard4255d502002-04-16 15:50:10 +000018256/************************************************************************
18257 * *
18258 * Simple type validation *
18259 * *
18260 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018261
Daniel Veillard4255d502002-04-16 15:50:10 +000018262
18263/************************************************************************
18264 * *
18265 * DOM Validation code *
18266 * *
18267 ************************************************************************/
18268
Daniel Veillard4255d502002-04-16 15:50:10 +000018269static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018270 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000018271 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018272static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018273 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018274 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018275 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000018276
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018277static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018278static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018279
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018280/**
18281 * xmlSchemaGetFreshElemInfo:
18282 * @vctxt: the schema validation context
18283 *
18284 * Creates/reuses and initializes the element info item for
18285 * the currect tree depth.
18286 *
18287 * Returns the element info item or NULL on API or internal errors.
18288 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018289static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018290xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
18291 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018292{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018293 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018294
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018295 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018296 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018297 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018298 "an inconsistent depth encountered.\n",
18299 NULL, NULL);
18300 return (NULL);
18301 }
18302 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018303 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
18304 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018305 if (vctxt->elemInfos == NULL) {
18306 xmlSchemaVErrMemory(vctxt,
18307 "allocating the element info array", NULL);
18308 return (NULL);
18309 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018310 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018311 vctxt->sizeElemInfos = 10;
18312 } else if (vctxt->sizeElemInfos == vctxt->depth) {
18313 int i = vctxt->sizeElemInfos;
18314
18315 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018316 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018317 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018318 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018319 if (vctxt->elemInfos == NULL) {
18320 xmlSchemaVErrMemory(vctxt,
18321 "re-allocating the element info array", NULL);
18322 return (NULL);
18323 }
18324 /*
18325 * We need the new memory to be NULLed.
18326 * TODO: Use memset instead?
18327 */
18328 for (; i < vctxt->sizeElemInfos; i++)
18329 vctxt->elemInfos[i] = NULL;
18330 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018331 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018332
18333 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018334 info = (xmlSchemaNodeInfoPtr)
18335 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018336 if (info == NULL) {
18337 xmlSchemaVErrMemory(vctxt,
18338 "allocating an element info", NULL);
18339 return (NULL);
18340 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018341 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018342 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018343 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018344 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018345
18346 return (info);
18347}
Daniel Veillard3646d642004-06-02 19:19:14 +000018348
18349/**
18350 * xmlSchemaFreeAttrStates:
18351 * @state: a list of attribute states
18352 *
18353 * Free the given list of attribute states
18354 *
18355 */
18356static void
18357xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
18358{
18359 xmlSchemaAttrStatePtr tmp;
18360 while (state != NULL) {
18361 tmp = state;
18362 state = state->next;
18363 xmlFree(tmp);
18364 }
18365}
18366
Daniel Veillard4255d502002-04-16 15:50:10 +000018367/**
18368 * xmlSchemaRegisterAttributes:
18369 * @ctxt: a schema validation context
18370 * @attrs: a list of attributes
18371 *
18372 * Register the list of attributes as the set to be validated on that element
18373 *
18374 * Returns -1 in case of error, 0 otherwise
18375 */
18376static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018377xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
18378{
Daniel Veillard3646d642004-06-02 19:19:14 +000018379 xmlSchemaAttrStatePtr tmp;
18380
18381 ctxt->attr = NULL;
18382 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000018383 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018384 if ((attrs->ns != NULL) &&
18385 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
18386 attrs = attrs->next;
18387 continue;
18388 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018389 tmp = (xmlSchemaAttrStatePtr)
18390 xmlMalloc(sizeof(xmlSchemaAttrState));
18391 if (tmp == NULL) {
18392 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
18393 return (-1);
18394 }
Daniel Veillard3646d642004-06-02 19:19:14 +000018395 tmp->attr = attrs;
18396 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
18397 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018398 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018399 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018400 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000018401 else
18402 ctxt->attrTop->next = tmp;
18403 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018404 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000018405 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018406 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018407}
18408
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018409#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000018410/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018411 * xmlSchemaValidateCheckNodeList
18412 * @nodelist: the list of nodes
18413 *
18414 * Check the node list is only made of text nodes and entities pointing
18415 * to text nodes
18416 *
18417 * Returns 1 if true, 0 if false and -1 in case of error
18418 */
18419static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018420xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
18421{
Daniel Veillard4255d502002-04-16 15:50:10 +000018422 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018423 if (nodelist->type == XML_ENTITY_REF_NODE) {
18424 TODO /* implement recursion in the entity content */
18425 }
18426 if ((nodelist->type != XML_TEXT_NODE) &&
18427 (nodelist->type != XML_COMMENT_NODE) &&
18428 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000018429 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018430 return (0);
18431 }
18432 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000018433 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018434 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018435}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018436#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000018437
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018438static void
18439xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18440{
18441 int i, nbItems;
18442 xmlSchemaTypePtr item, *items;
18443
18444
18445 /*
18446 * During the Assemble of the schema ctxt->curItems has
18447 * been filled with the relevant new items. Fix those up.
18448 */
18449 nbItems = ctxt->assemble->nbItems;
18450 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
18451
18452 for (i = 0; i < nbItems; i++) {
18453 item = items[i];
18454 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018455 case XML_SCHEMA_TYPE_COMPLEX:
18456 case XML_SCHEMA_TYPE_SIMPLE:
18457 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18458 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018459 case XML_SCHEMA_TYPE_ATTRIBUTE:
18460 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18461 break;
18462 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018463 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018464 NULL, NULL, NULL);
18465 break;
18466 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18467 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
18468 ctxt, NULL);
18469 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018470 case XML_SCHEMA_TYPE_PARTICLE:
18471 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018472 default:
18473 break;
18474 }
18475 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018476 if (ctxt->nberrors != 0)
18477 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018478 /*
18479 * Circularity checks.
18480 */
18481 for (i = 0; i < nbItems; i++) {
18482 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018483 switch (item->type) {
18484 case XML_SCHEMA_TYPE_COMPLEX:
18485 case XML_SCHEMA_TYPE_SIMPLE:
18486 xmlSchemaCheckTypeDefCircular(
18487 (xmlSchemaTypePtr) item, ctxt, NULL);
18488 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018489 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018490 xmlSchemaCheckGroupDefCircular(
18491 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018492 break;
18493 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18494 xmlSchemaCheckAttributeGroupCircular(
18495 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18496 break;
18497 default:
18498 break;
18499 }
18500 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018501 if (ctxt->nberrors != 0)
18502 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018503 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018504 * Set the "term" of particles pointing to model group definitions
18505 * to the contained model group.
18506 */
18507 for (i = 0; i < nbItems; i++) {
18508 item = items[i];
18509 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18510 (((xmlSchemaParticlePtr) item)->children != NULL) &&
18511 (((xmlSchemaParticlePtr) item)->children->type ==
18512 XML_SCHEMA_TYPE_GROUP)) {
18513 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18514 ctxt, NULL);
18515 }
18516 }
18517 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018518 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018519 */
18520 for (i = 0; i < nbItems; i++) {
18521 item = items[i];
18522 switch (item->type) {
18523 case XML_SCHEMA_TYPE_SIMPLE:
18524 case XML_SCHEMA_TYPE_COMPLEX:
18525 xmlSchemaTypeFixup(item, ctxt, NULL);
18526 break;
18527 default:
18528 break;
18529 }
18530 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018531 if (ctxt->nberrors != 0)
18532 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018533 /*
18534 * Validate value contraint values.
18535 */
18536 for (i = 0; i < nbItems; i++) {
18537 item = items[i];
18538 switch (item->type) {
18539 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018540 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18541 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018542 break;
18543 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018544 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018545 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018546 break;
18547 default:
18548 break;
18549 }
18550 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018551 if (ctxt->nberrors != 0)
18552 return;
18553 /*
18554 * Build the content model for complex types.
18555 */
18556 for (i = 0; i < nbItems; i++) {
18557 item = items[i];
18558 switch (item->type) {
18559 case XML_SCHEMA_TYPE_COMPLEX:
18560 xmlSchemaBuildContentModel(item, ctxt, NULL);
18561 break;
18562 default:
18563 break;
18564 }
18565 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018566}
18567
18568/**
18569 * xmlSchemaAssembleByLocation:
18570 * @pctxt: a schema parser context
18571 * @vctxt: a schema validation context
18572 * @schema: the existing schema
18573 * @node: the node that fired the assembling
18574 * @nsName: the namespace name of the new schema
18575 * @location: the location of the schema
18576 *
18577 * Expands an existing schema by an additional schema.
18578 *
18579 * Returns 0 if the new schema is correct, a positive error code
18580 * number otherwise and -1 in case of an internal or API error.
18581 */
18582static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018583xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
18584 xmlSchemaPtr schema,
18585 xmlNodePtr node,
18586 const xmlChar *nsName,
18587 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018588{
18589 const xmlChar *targetNs, *oldtns;
18590 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018591 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018592 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018593 xmlSchemaParserCtxtPtr pctxt;
18594
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018595 /*
18596 * This should be used:
18597 * 1. on <import>(s)
18598 * 2. if requested by the validated instance
18599 * 3. if requested via the API
18600 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018601 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018602 return (-1);
18603 /*
18604 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018605 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018606 if ((vctxt->pctxt == NULL) &&
18607 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
18608 xmlSchemaVErr(vctxt, node,
18609 XML_SCHEMAV_INTERNAL,
18610 "Internal error: xmlSchemaAssembleByLocation, "
18611 "failed to create a temp. parser context.\n",
18612 NULL, NULL);
18613 return (-1);
18614 }
18615 pctxt = vctxt->pctxt;
18616 /*
18617 * Set the counter to produce unique names for anonymous items.
18618 */
18619 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018620 /*
18621 * Acquire the schema document.
18622 */
18623 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
18624 nsName, location, &doc, &targetNs, 0);
18625 if (ret != 0) {
18626 if (doc != NULL)
18627 xmlFreeDoc(doc);
18628 } else if (doc != NULL) {
18629 docElem = xmlDocGetRootElement(doc);
18630 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018631 * Create new assemble info.
18632 */
18633 if (pctxt->assemble == NULL) {
18634 pctxt->assemble = xmlSchemaNewAssemble();
18635 if (pctxt->assemble == NULL) {
18636 xmlSchemaVErrMemory(vctxt,
18637 "Memory error: xmlSchemaAssembleByLocation, "
18638 "allocating assemble info", NULL);
18639 xmlFreeDoc(doc);
18640 return (-1);
18641 }
18642 }
18643 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018644 * Save and reset the context & schema.
18645 */
18646 oldflags = schema->flags;
18647 oldtns = schema->targetNamespace;
18648 olddoc = schema->doc;
18649
18650 xmlSchemaClearSchemaDefaults(schema);
18651 schema->targetNamespace = targetNs;
18652 /* schema->nbCurItems = 0; */
18653 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018654 pctxt->ctxtType = NULL;
18655 pctxt->parentItem = NULL;
18656
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018657 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18658 if (pctxt->nberrors != 0) {
18659 vctxt->nberrors += pctxt->nberrors;
18660 goto finally;
18661 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018662 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018663 if (pctxt->nberrors != 0) {
18664 vctxt->nberrors += pctxt->nberrors;
18665 goto finally;
18666 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018667 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018668 if (pctxt->nberrors != 0)
18669 vctxt->nberrors += pctxt->nberrors;
18670finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018671 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018672 * Set the counter of items.
18673 */
18674 schema->counter = pctxt->counter;
18675 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018676 * Free the list of assembled components.
18677 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018678 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018679 /*
18680 * Restore the context & schema.
18681 */
18682 schema->flags = oldflags;
18683 schema->targetNamespace = oldtns;
18684 schema->doc = olddoc;
18685 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018686 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018687 return (ret);
18688}
18689
18690/**
18691 * xmlSchemaAssembleByXSIAttr:
18692 * @vctxt: a schema validation context
18693 * @xsiAttr: an xsi attribute
18694 * @noNamespace: whether a schema with no target namespace is exptected
18695 *
18696 * Expands an existing schema by an additional schema using
18697 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18698 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18699 * must be set to 1.
18700 *
18701 * Returns 0 if the new schema is correct, a positive error code
18702 * number otherwise and -1 in case of an internal or API error.
18703 */
18704static int
18705xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
18706 xmlAttrPtr xsiAttr,
18707 int noNamespace)
18708{
18709 xmlChar *value;
18710 const xmlChar *cur, *end;
18711 const xmlChar *nsname = NULL, *location;
18712 int count = 0;
18713 int ret = 0;
18714
18715 if (xsiAttr == NULL) {
18716 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
18717 NULL, NULL,
18718 "Internal error: xmlSchemaAssembleByXSIAttr, "
18719 "bad arguments", NULL);
18720 return (-1);
18721 }
18722 /*
18723 * Parse the value; we will assume an even number of values
18724 * to be given (this is how Xerces and XSV work).
18725 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018726 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018727 cur = value;
18728 do {
18729 if (noNamespace != 1) {
18730 /*
18731 * Get the namespace name.
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 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
18742 cur = end;
18743 }
18744 /*
18745 * Get the URI.
18746 */
18747 while (IS_BLANK_CH(*cur))
18748 cur++;
18749 end = cur;
18750 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18751 end++;
18752 if (end == cur)
18753 break;
18754 count++;
18755 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018756 cur = end;
18757 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018758 xsiAttr->parent, nsname, location);
18759 if (ret == -1) {
18760 xmlSchemaVCustomErr(vctxt,
18761 XML_SCHEMAV_INTERNAL,
18762 (xmlNodePtr) xsiAttr, NULL,
18763 "Internal error: xmlSchemaAssembleByXSIAttr, "
18764 "assembling schemata", NULL);
18765 if (value != NULL)
18766 xmlFree(value);
18767 return (-1);
18768 }
18769 } while (*cur != 0);
18770 if (value != NULL)
18771 xmlFree(value);
18772 return (ret);
18773}
18774
18775/**
18776 * xmlSchemaAssembleByXSIElem:
18777 * @vctxt: a schema validation context
18778 * @elem: an element node possibly holding xsi attributes
18779 * @noNamespace: whether a schema with no target namespace is exptected
18780 *
18781 * Assembles an existing schema by an additional schema using
18782 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
18783 * of the given @elem.
18784 *
18785 * Returns 0 if the new schema is correct, a positive error code
18786 * number otherwise and -1 in case of an internal or API error.
18787 */
18788static int
18789xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
18790 xmlNodePtr elem)
18791{
18792 int ret = 0, retNs = 0;
18793 xmlAttrPtr attr;
18794
18795 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
18796 if (attr != NULL) {
18797 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
18798 if (retNs == -1)
18799 return (-1);
18800 }
18801 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
18802 if (attr != NULL) {
18803 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
18804 if (ret == -1)
18805 return (-1);
18806 }
18807 if (retNs != 0)
18808 return (retNs);
18809 else
18810 return (ret);
18811}
18812
Daniel Veillard4255d502002-04-16 15:50:10 +000018813/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018814 * xmlSchemaValidateCallback:
18815 * @ctxt: a schema validation context
18816 * @name: the name of the element detected (might be NULL)
18817 * @type: the type
18818 *
18819 * A transition has been made in the automata associated to an element
18820 * content model
18821 */
18822static void
18823xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018824 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018825 xmlSchemaBasicItemPtr item, xmlNodePtr node)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018826{
Daniel Veillard4255d502002-04-16 15:50:10 +000018827 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018828
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018829 /*
18830 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
18831 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018832 ctxt->node = node;
18833 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018834
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018835 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018836
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018837 /*
18838 * Assemble new schemata using xsi.
18839 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018840 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018841 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018842
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018843 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18844 if (ret == -1) {
18845 xmlSchemaVCustomErr(ctxt,
18846 XML_SCHEMAV_INTERNAL,
18847 ctxt->node, NULL,
18848 "Internal error: xmlSchemaValidateElement, "
18849 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018850 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018851 }
18852 /*
18853 * NOTE: We won't react on schema parser errors here.
18854 * TODO: But a warning would be nice.
18855 */
18856 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018857 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018858 case XML_SCHEMA_TYPE_ELEMENT: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018859#ifdef DEBUG_CONTENT
18860 xmlGenericError(xmlGenericErrorContext,
18861 "xmlSchemaValidateCallback: %s, %s, %s\n",
18862 name, ((xmlSchemaElementPtr) item)->name, node->name);
18863#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018864 xmlSchemaValidateElementByDeclaration(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018865 (xmlSchemaElementPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018866 break;
18867 }
18868 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018869#ifdef DEBUG_CONTENT
18870 xmlGenericError(xmlGenericErrorContext,
18871 "xmlSchemaValidateCallback: %s, <any>, %s\n",
18872 name, node->name);
18873#endif
18874 xmlSchemaValidateElementByWildcard(ctxt,
18875 (xmlSchemaWildcardPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018876 break;
18877 default:
18878 break;
18879 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018880leave:
18881
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018882 xmlSchemaEndElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000018883 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018884}
Daniel Veillard4255d502002-04-16 15:50:10 +000018885
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018886static int
18887xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18888 const xmlChar *value,
18889 xmlSchemaValPtr *val,
18890 xmlNodePtr node)
18891{
18892 int ret;
18893
18894 ret = xmlValidateQName(value, 1);
18895 if (ret != 0)
18896 return (ret);
18897
18898 {
18899 xmlChar *uri = NULL;
18900 xmlChar *local = NULL;
18901 xmlChar *prefix;
18902
18903 local = xmlSplitQName2(value, &prefix);
18904 if (prefix != NULL) {
18905 xmlNsPtr ns;
18906
18907 /*
18908 * TODO: Make this streamable.
18909 */
18910 if ((node == NULL) || (node->doc == NULL)) {
18911 xmlFree(prefix);
18912 xmlFree(local);
18913 return (3);
18914 }
18915
18916 ns = xmlSearchNs(node->doc, node, prefix);
18917 if (ns == NULL) {
18918 xmlFree(prefix);
18919 xmlFree(local);
18920 return (1);
18921 }
18922 }
18923 if (prefix != NULL) {
18924 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
18925 ret = 1;
18926 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
18927 NULL) == NULL)
18928 ret = 1;
18929
18930 if ((ret == 0) && (val != NULL)) {
18931 if (prefix != NULL) {
18932 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
18933 BAD_CAST xmlStrdup(uri));
18934 local = NULL;
18935 } else
18936 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
18937 NULL);
18938 if (*val == NULL)
18939 ret = -1;
18940 }
18941 if (local != NULL)
18942 xmlFree(local);
18943 }
18944
18945 return (ret);
18946}
18947
Daniel Veillard01fa6152004-06-29 17:04:39 +000018948/**
18949 * xmlSchemaValidateSimpleTypeValue:
18950 * @ctxt: a schema validation context
18951 * @value: the value to be validated
18952 * @fireErrors: shall errors be reported?
18953 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018954 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018955 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000018956 *
18957 * Validates a value by the given type (user derived or built-in).
18958 *
18959 * Returns 0 if the value is valid, a positive error code
18960 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000018961 */
18962static int
18963xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018964 xmlSchemaTypePtr type,
18965 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018966 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018967 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018968 int normalize,
18969 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018970{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018971 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018972 int ret = 0;
18973 xmlChar *normValue = NULL;
18974 int wtsp;
18975
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018976 node = ctxt->node;
18977 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018978 wtsp = ctxt->valueWS;
18979 /*
18980 * Normalize the value.
18981 */
18982 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018983 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018984 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
18985
18986 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018987 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018988 normValue = xmlSchemaCollapseString(value);
18989 else
18990 normValue = xmlSchemaWhiteSpaceReplace(value);
18991 ctxt->valueWS = norm;
18992 if (normValue != NULL)
18993 value = (const xmlChar *) normValue;
18994 }
18995 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018996 /*
18997 * The nodes of a content must be checked only once,
18998 * this is not working since list types will fire this
18999 * multiple times.
19000 */
19001 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
19002 xmlNodePtr cur = ctxt->cur;
19003
19004 do {
19005 switch (cur->type) {
19006 case XML_TEXT_NODE:
19007 case XML_CDATA_SECTION_NODE:
19008 case XML_PI_NODE:
19009 case XML_COMMENT_NODE:
19010 case XML_XINCLUDE_START:
19011 case XML_XINCLUDE_END:
19012 break;
19013 case XML_ENTITY_REF_NODE:
19014 case XML_ENTITY_NODE:
19015 /* TODO: Scour the entities for illegal nodes. */
19016 TODO break;
19017 case XML_ELEMENT_NODE: {
19018 /* NOTE: Changed to an internal error, since the
19019 * existence of an element node will be already checked in
19020 * xmlSchemaValidateElementBySimpleType and in
19021 * xmlSchemaValidateElementByComplexType.
19022 */
19023 xmlSchemaVCustomErr(ctxt,
19024 XML_SCHEMAV_INTERNAL,
19025 /* XML_SCHEMAS_ERR_INVALIDELEM, */
19026 node, type,
19027 "Element '%s' found in simple type content",
19028 cur->name);
19029 return (XML_SCHEMAV_INTERNAL);
19030 }
19031 case XML_ATTRIBUTE_NODE:
19032 case XML_DOCUMENT_NODE:
19033 case XML_DOCUMENT_TYPE_NODE:
19034 case XML_DOCUMENT_FRAG_NODE:
19035 case XML_NOTATION_NODE:
19036 case XML_HTML_DOCUMENT_NODE:
19037 case XML_DTD_NODE:
19038 case XML_ELEMENT_DECL:
19039 case XML_ATTRIBUTE_DECL:
19040 case XML_ENTITY_DECL:
19041 case XML_NAMESPACE_DECL:
19042#ifdef LIBXML_DOCB_ENABLED
19043 case XML_DOCB_DOCUMENT_NODE:
19044#endif
19045 xmlSchemaVCustomErr(ctxt,
19046 XML_SCHEMAV_INTERNAL,
19047 /* XML_SCHEMAS_ERR_INVALIDELEM, */
19048 node, NULL,
19049 "Node of unexpected type found in simple type content",
19050 NULL);
19051 return (XML_SCHEMAV_INTERNAL);
19052 }
19053 cur = cur->next;
19054 } while (cur != NULL);
19055 }
19056
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019057 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019058
19059 if (ctxt->value != NULL) {
19060 xmlSchemaFreeValue(ctxt->value);
19061 ctxt->value = NULL;
19062 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019063 /*
19064 * STREAM-READ-CHILDREN.
19065 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019066 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
19067 (ctxt->schema != NULL)) {
19068 /*
19069 * NOTATIONs need to be processed here, since they need
19070 * to lookup in the hashtable of NOTATION declarations.
19071 */
19072 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
19073 } else
19074 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019075 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019076 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
19077 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
19078 else
19079 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019080 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019081 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019082 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019083 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019084 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019085 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019086 } else if ((ctxt->value == NULL) &&
19087 (type->builtInType == XML_SCHEMAS_STRING) &&
19088 (ctxt->nodeInfo != NULL) &&
19089 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019090 xmlChar *valdup;
19091 /*
19092 * Create a precomputed string value for "string" as well if
19093 * requested.
19094 */
19095 valdup = xmlStrdup(value);
19096 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19097 BAD_CAST valdup);
19098 if ((valdup != NULL) && (ctxt->value == NULL))
19099 xmlFree(valdup);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019100 }
19101 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
19102 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
19103 * a literal in the ·lexical space· of {base type definition}
19104 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019105 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019106 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019107 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019108 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019109 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019110 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019111 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019112 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019113 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019114 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019115 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019116 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000019117 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019118 */
19119 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019120 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019121 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019122 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019123 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019124 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019125 type->name, NULL);
19126 } else if (ret > 0) {
19127 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019128 /*
19129 Disabled, since the facet validation already reports errors.
19130 if (fireErrors)
19131 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
19132 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019133 }
19134 }
19135 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
19136
19137 xmlSchemaTypePtr tmpType;
19138 const xmlChar *cur, *end;
19139 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019140 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019141
19142 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
19143 * of white space separated tokens, each of which ·match·es a literal
19144 * in the ·lexical space· of {item type definition}
19145 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000019146
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000019147 if (value == NULL)
19148 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000019149 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019150 cur = value;
19151 do {
19152 while (IS_BLANK_CH(*cur))
19153 cur++;
19154 end = cur;
19155 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
19156 end++;
19157 if (end == cur)
19158 break;
19159 tmp = xmlStrndup(cur, end - cur);
19160 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019161 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019162 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019163 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019164 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019165 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19166 "validating an item of list simple type '%s'\n",
19167 type->name, NULL);
19168 break;
19169 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019170 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019171 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019172 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019173 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019174 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019175 cur = end;
19176 } while (*cur != 0);
19177 /*
19178 * Check facets.
19179 */
19180 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019181 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019182 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019183 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019184 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019185 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019186 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019187 value, len, fireErrors);
19188 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019189 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019190 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19191 "validating facets of list simple type '%s'\n",
19192 type->name, NULL);
19193 } else if (ret > 0) {
19194 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019195 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000019196 Disabled, since the facet validation already reports errors.
19197 if (fireErrors)
19198 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019199 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019200 }
19201
Daniel Veillard01fa6152004-06-29 17:04:39 +000019202 }
19203 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
19204 xmlSchemaTypeLinkPtr memberLink;
19205
19206 /*
19207 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
19208 * not apply directly; however, the normalization behavior of ·union·
19209 * types is controlled by the value of whiteSpace on that one of the
19210 * ·memberTypes· against which the ·union· is successfully validated.
19211 *
19212 * This means that the value is normalized by the first validating
19213 * member type, then the facets of the union type are applied. This
19214 * needs changing of the value!
19215 */
19216
19217 /*
19218 * 1.2.3 if {variety} is ·union· then the string must ·match· a
19219 * literal in the ·lexical space· of at least one member of
19220 * {member type definitions}
19221 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019222#ifdef DEBUG_UNION_VALIDATION
19223 printf("Union ST : '%s'\n", (const char *) type->name);
19224 printf(" fireErrors : %d\n", fireErrors);
19225 printf(" applyFacets: %d\n", applyFacets);
19226#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000019227 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
19228 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019229 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019230 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019231 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019232 type->name, NULL);
19233 ret = -1;
19234 }
19235 if (ret == 0) {
19236 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019237 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
19238 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019239 if ((ret <= 0) || (ret == 0))
19240 break;
19241 memberLink = memberLink->next;
19242 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019243 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019244 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019245 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019246 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000019247 type->name, NULL);
19248 } else if (ret > 0) {
19249 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019250 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019251 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019252 }
19253 }
19254 /*
19255 * Apply facets (pattern, enumeration).
19256 */
19257 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
19258 int mws;
19259 /*
19260 * The normalization behavior of ·union· types is controlled by
19261 * the value of whiteSpace on that one of the ·memberTypes·
19262 * against which the ·union· is successfully validated.
19263 */
19264 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019265 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019266 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19267 "the value was already normalized for the union simple "
19268 "type '%s'.\n", type->name, NULL);
19269 }
19270 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
19271 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019272 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019273 normValue = xmlSchemaCollapseString(value);
19274 else
19275 normValue = xmlSchemaWhiteSpaceReplace(value);
19276 if (normValue != NULL)
19277 value = (const xmlChar *) normValue;
19278 }
19279
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019280 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019281 value, 0, fireErrors);
19282 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019283 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019284 "Internal error: xmlSchemaValidateSimpleTypeValue, "
19285 "validating facets of union simple type '%s'\n",
19286 type->name, NULL);
19287 } else if (ret > 0) {
19288 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
19289 /*
19290 if (fireErrors)
19291 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
19292 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019293 }
19294 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019295 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019296 ctxt->valueWS = wtsp;
19297 if (normValue != NULL)
19298 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019299 return (ret);
19300}
19301
19302/**
19303 * xmlSchemaValidateSimpleTypeElement:
19304 * @ctxt: a schema validation context
19305 * @node: the element node to be validated.
19306 *
19307 * Validate the element against a simple type.
19308 *
19309 * Returns 0 if the element is valid, a positive error code
19310 * number otherwise and -1 in case of an internal or API error.
19311 */
19312static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019313xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019314 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019315 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019316 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019317{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019318 xmlSchemaTypePtr oldtype;
19319 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019320 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019321 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019322 int ret = 0, retval = 0;
19323
Daniel Veillard01fa6152004-06-29 17:04:39 +000019324 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019325 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19326 "Internal error: xmlSchemaValidateElementBySimpleType, "
19327 "bad arguments", NULL);
19328 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019329 }
19330
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019331 oldtype = ctxt->type;
19332 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019333 /*
19334 * cvc-type: 3.1.2 The element information item must have no element
19335 * information item [children].
19336 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019337 /*
19338 * STREAM: Child nodes are processed.
19339 */
19340 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019341 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019342 /*
19343 * TODO: Entities, will they produce elements as well?
19344 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019345 if (cur->type == XML_ELEMENT_NODE) {
19346 xmlSchemaVCustomErr(ctxt,
19347 XML_SCHEMAV_CVC_TYPE_3_1_2,
19348 node, type,
19349 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019350 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019351 }
19352 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019353 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019354
Daniel Veillard01fa6152004-06-29 17:04:39 +000019355 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019356 * cvc-type 3.1.1:
19357 *
19358 * The attributes of must be empty, excepting those whose namespace name
19359 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
19360 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019361 */
19362 /*
19363 * STREAM: Attribute nodes are processed.
19364 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019365 attr = node->properties;
19366 while (attr != NULL) {
19367 if ((attr->ns == NULL) ||
19368 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
19369 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
19370 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
19371 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
19372 (!xmlStrEqual
19373 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019374 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019375 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
19376 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019377 }
19378 attr = attr->next;
19379 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019380 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019381 * This will skip validation if the type is 'anySimpleType' and
19382 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019383 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019384 if ((! isNil) &&
19385 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019386 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
19387 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019388 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019389
19390 value = xmlNodeGetContent(node);
19391 /*
19392 * NOTE: This call will not check the content nodes, since
19393 * this should be checked here already.
19394 */
19395 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
19396 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019397 if (value != NULL)
19398 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019399 if (retval != 0)
19400 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000019401 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019402 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019403 return (ret);
19404}
Daniel Veillard4255d502002-04-16 15:50:10 +000019405
19406/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019407 * xmlSchemaValQNameAcquire:
19408 * @value: the lexical represantation of the QName value
19409 * @node: the node to search for the corresponding namespace declaration
19410 * @nsName: the resulting namespace name if found
19411 *
19412 * Checks that a value conforms to the lexical space of the type QName;
19413 * if valid, the corresponding namespace name is searched and retured
19414 * as a copy in @nsName. The local name is returned in @localName as
19415 * a copy.
19416 *
19417 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
19418 * namespace declaration was found in scope; -1 in case of an internal or
19419 * API error.
19420 */
19421static int
19422xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
19423 xmlChar **nsName, xmlChar **localName)
19424{
19425 int ret;
19426 xmlChar *local = NULL;
19427
19428 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
19429 return (-1);
19430 *nsName = NULL;
19431 *localName = NULL;
19432 ret = xmlValidateQName(value, 1);
19433 if (ret == 0) {
19434 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019435 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019436
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019437 /*
19438 * NOTE: xmlSplitQName2 will return a duplicated
19439 * string.
19440 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019441 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019442 if (local == NULL)
19443 local = xmlStrdup(value);
19444 ns = xmlSearchNs(node->doc, node, prefix);
19445 /*
19446 * A namespace need not to be found if the prefix is NULL.
19447 */
19448 if (ns != NULL) {
19449 /*
19450 * TODO: Is it necessary to duplicate the URI here?
19451 */
19452 *nsName = xmlStrdup(ns->href);
19453 } else if (prefix != NULL) {
19454 xmlFree(prefix);
19455 if (local != NULL)
19456 xmlFree(local);
19457 return (2);
19458 }
19459 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019460 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019461 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019462 } else
19463 return (1);
19464 return (ret);
19465}
19466
19467/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019468 * xmlSchemaHasElemContent:
19469 * @node: the node
19470 *
19471 * Scours the content of the given node for element
19472 * nodes.
19473 *
19474 * Returns 1 if an element node is found,
19475 * 0 otherwise.
19476 */
19477static int
19478xmlSchemaHasElemContent(xmlNodePtr node)
19479{
19480 if (node == NULL)
19481 return (0);
19482 node = node->children;
19483 while (node != NULL) {
19484 if (node->type == XML_ELEMENT_NODE)
19485 return (1);
19486 node = node->next;
19487 }
19488 return (0);
19489}
19490/**
19491 * xmlSchemaHasElemOrCharContent:
19492 * @node: the node
19493 *
19494 * Scours the content of the given node for element
19495 * and character nodes.
19496 *
19497 * Returns 1 if an element or character node is found,
19498 * 0 otherwise.
19499 */
19500static int
19501xmlSchemaHasElemOrCharContent(xmlNodePtr node)
19502{
19503 if (node == NULL)
19504 return (0);
19505 node = node->children;
19506 while (node != NULL) {
19507 switch (node->type) {
19508 case XML_ELEMENT_NODE:
19509 /*
19510 * TODO: Ask Daniel if these are all character nodes.
19511 */
19512 case XML_TEXT_NODE:
19513 case XML_CDATA_SECTION_NODE:
19514 /*
19515 * TODO: How XML_ENTITY_NODEs evaluated?
19516 */
19517 case XML_ENTITY_REF_NODE:
19518 case XML_ENTITY_NODE:
19519 return (1);
19520 break;
19521 default:
19522 break;
19523 }
19524 node = node->next;
19525 }
19526 return (0);
19527}
19528
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019529/************************************************************************
19530 * *
19531 * Identity-constraints (IDC) *
19532 * *
19533 ************************************************************************/
19534
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019535/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019536 * xmlSchemaAugmentIDC:
19537 * @idcDef: the IDC definition
19538 *
19539 * Creates an augmented IDC definition item.
19540 *
19541 * Returns the item, or NULL on internal errors.
19542 */
19543static void
19544xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
19545 xmlSchemaValidCtxtPtr vctxt)
19546{
19547 xmlSchemaIDCAugPtr aidc;
19548
19549 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
19550 if (aidc == NULL) {
19551 xmlSchemaVErrMemory(vctxt,
19552 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
19553 NULL);
19554 return;
19555 }
19556 aidc->bubbleDepth = -1;
19557 aidc->def = idcDef;
19558 aidc->next = NULL;
19559 if (vctxt->aidcs == NULL)
19560 vctxt->aidcs = aidc;
19561 else {
19562 aidc->next = vctxt->aidcs;
19563 vctxt->aidcs = aidc;
19564 }
19565}
19566
19567/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019568 * xmlSchemaIDCNewBinding:
19569 * @idcDef: the IDC definition of this binding
19570 *
19571 * Creates a new IDC binding.
19572 *
19573 * Returns the new binding in case of succeeded, NULL on internal errors.
19574 */
19575static xmlSchemaPSVIIDCBindingPtr
19576xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
19577{
19578 xmlSchemaPSVIIDCBindingPtr ret;
19579
19580 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
19581 sizeof(xmlSchemaPSVIIDCBinding));
19582 if (ret == NULL) {
19583 xmlSchemaVErrMemory(NULL,
19584 "allocating a PSVI IDC binding item", NULL);
19585 return (NULL);
19586 }
19587 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
19588 ret->definition = idcDef;
19589 return (ret);
19590}
19591
19592/**
19593 * xmlSchemaIDCStoreNodeTableItem:
19594 * @vctxt: the WXS validation context
19595 * @item: the IDC node table item
19596 *
19597 * The validation context is used to store an IDC node table items.
19598 * They are stored to avoid copying them if IDC node-tables are merged
19599 * with corresponding parent IDC node-tables (bubbling).
19600 *
19601 * Returns 0 if succeeded, -1 on internal errors.
19602 */
19603static int
19604xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
19605 xmlSchemaPSVIIDCNodePtr item)
19606{
19607 /*
19608 * Add to gobal list.
19609 */
19610 if (vctxt->idcNodes == NULL) {
19611 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19612 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
19613 if (vctxt->idcNodes == NULL) {
19614 xmlSchemaVErrMemory(vctxt,
19615 "allocating the IDC node table item list", NULL);
19616 return (-1);
19617 }
19618 vctxt->sizeIdcNodes = 20;
19619 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
19620 vctxt->sizeIdcNodes *= 2;
19621 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19622 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
19623 sizeof(xmlSchemaPSVIIDCNodePtr));
19624 if (vctxt->idcNodes == NULL) {
19625 xmlSchemaVErrMemory(vctxt,
19626 "re-allocating the IDC node table item list", NULL);
19627 return (-1);
19628 }
19629 }
19630 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
19631
19632 return (0);
19633}
19634
19635/**
19636 * xmlSchemaIDCStoreKey:
19637 * @vctxt: the WXS validation context
19638 * @item: the IDC key
19639 *
19640 * The validation context is used to store an IDC key.
19641 *
19642 * Returns 0 if succeeded, -1 on internal errors.
19643 */
19644static int
19645xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
19646 xmlSchemaPSVIIDCKeyPtr key)
19647{
19648 /*
19649 * Add to gobal list.
19650 */
19651 if (vctxt->idcKeys == NULL) {
19652 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19653 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
19654 if (vctxt->idcKeys == NULL) {
19655 xmlSchemaVErrMemory(vctxt,
19656 "allocating the IDC key storage list", NULL);
19657 return (-1);
19658 }
19659 vctxt->sizeIdcKeys = 40;
19660 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
19661 vctxt->sizeIdcKeys *= 2;
19662 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19663 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
19664 sizeof(xmlSchemaPSVIIDCKeyPtr));
19665 if (vctxt->idcKeys == NULL) {
19666 xmlSchemaVErrMemory(vctxt,
19667 "re-allocating the IDC key storage list", NULL);
19668 return (-1);
19669 }
19670 }
19671 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
19672
19673 return (0);
19674}
19675
19676/**
19677 * xmlSchemaIDCAppendNodeTableItem:
19678 * @bind: the IDC binding
19679 * @ntItem: the node-table item
19680 *
19681 * Appends the IDC node-table item to the binding.
19682 *
19683 * Returns 0 on success and -1 on internal errors.
19684 */
19685static int
19686xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19687 xmlSchemaPSVIIDCNodePtr ntItem)
19688{
19689 if (bind->nodeTable == NULL) {
19690 bind->sizeNodes = 10;
19691 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19692 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19693 if (bind->nodeTable == NULL) {
19694 xmlSchemaVErrMemory(NULL,
19695 "allocating an array of IDC node-table items", NULL);
19696 return(-1);
19697 }
19698 } else if (bind->sizeNodes <= bind->nbNodes) {
19699 bind->sizeNodes *= 2;
19700 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19701 xmlRealloc(bind->nodeTable, bind->sizeNodes *
19702 sizeof(xmlSchemaPSVIIDCNodePtr));
19703 if (bind->nodeTable == NULL) {
19704 xmlSchemaVErrMemory(NULL,
19705 "re-allocating an array of IDC node-table items", NULL);
19706 return(-1);
19707 }
19708 }
19709 bind->nodeTable[bind->nbNodes++] = ntItem;
19710 return(0);
19711}
19712
19713/**
19714 * xmlSchemaIDCAquireBinding:
19715 * @vctxt: the WXS validation context
19716 * @matcher: the IDC matcher
19717 *
19718 * Looks up an PSVI IDC binding, for the IDC definition and
19719 * of the given matcher. If none found, a new one is created
19720 * and added to the IDC table.
19721 *
19722 * Returns an IDC binding or NULL on internal errors.
19723 */
19724static xmlSchemaPSVIIDCBindingPtr
19725xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19726 xmlSchemaIDCMatcherPtr matcher)
19727{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019728 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019729
19730 info = vctxt->elemInfos[matcher->depth];
19731
19732 if (info->idcTable == NULL) {
19733 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19734 if (info->idcTable == NULL)
19735 return (NULL);
19736 return(info->idcTable);
19737 } else {
19738 xmlSchemaPSVIIDCBindingPtr bind = NULL;
19739
19740 bind = info->idcTable;
19741 do {
19742 if (bind->definition == matcher->aidc->def)
19743 return(bind);
19744 if (bind->next == NULL) {
19745 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19746 if (bind->next == NULL)
19747 return (NULL);
19748 return(bind->next);
19749 }
19750 bind = bind->next;
19751 } while (bind != NULL);
19752 }
19753 return (NULL);
19754}
19755
19756/**
19757 * xmlSchemaIDCFreeKey:
19758 * @key: the IDC key
19759 *
19760 * Frees an IDC key together with its compiled value.
19761 */
19762static void
19763xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19764{
19765 if (key->compValue != NULL)
19766 xmlSchemaFreeValue(key->compValue);
19767 xmlFree(key);
19768}
19769
19770/**
19771 * xmlSchemaIDCFreeBinding:
19772 *
19773 * Frees an IDC binding. Note that the node table-items
19774 * are not freed.
19775 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019776static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019777xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19778{
19779 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019780 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19781 int i;
19782 /*
19783 * Node-table items for keyrefs are not stored globally
19784 * to the validation context, since they are not bubbled.
19785 * We need to free them here.
19786 */
19787 for (i = 0; i < bind->nbNodes; i++) {
19788 xmlFree(bind->nodeTable[i]->keys);
19789 xmlFree(bind->nodeTable[i]);
19790 }
19791 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019792 xmlFree(bind->nodeTable);
19793 }
19794 xmlFree(bind);
19795}
19796
19797/**
19798 * xmlSchemaIDCFreeIDCTable:
19799 * @bind: the first IDC binding in the list
19800 *
19801 * Frees an IDC table, i.e. all the IDC bindings in the list.
19802 */
19803static void
19804xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19805{
19806 xmlSchemaPSVIIDCBindingPtr prev;
19807
19808 while (bind != NULL) {
19809 prev = bind;
19810 bind = bind->next;
19811 xmlSchemaIDCFreeBinding(prev);
19812 }
19813}
19814
19815/**
19816 * xmlSchemaIDCFreeMatcherList:
19817 * @matcher: the first IDC matcher in the list
19818 *
19819 * Frees a list of IDC matchers.
19820 */
19821static void
19822xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19823{
19824 xmlSchemaIDCMatcherPtr next;
19825
19826 while (matcher != NULL) {
19827 next = matcher->next;
19828 if (matcher->keySeqs != NULL) {
19829 int i;
19830 for (i = 0; i < matcher->sizeKeySeqs; i++)
19831 if (matcher->keySeqs[i] != NULL)
19832 xmlFree(matcher->keySeqs[i]);
19833 xmlFree(matcher->keySeqs);
19834 }
19835 xmlFree(matcher);
19836 matcher = next;
19837 }
19838}
19839
19840/**
19841 * xmlSchemaAreValuesEqual:
19842 * @ta: the first type
19843 * @a: the first value
19844 * @tb: the second type
19845 * @b: the second value
19846 *
19847 * Compares two values.
19848 *
19849 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
19850 */
19851static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019852xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
19853 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019854 xmlSchemaValPtr a,
19855 xmlSchemaTypePtr tb,
19856 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019857{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019858 /* Same user derived/built-in derived/built-in primitive types. */
19859 if (ta == tb)
19860 goto compareValue;
19861
19862 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019863 * Note that comparison with anySimpleTypes with be supported for
19864 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019865 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019866#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019867 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
19868 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19869 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019870#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019871
19872 /*
19873 * 4.2.1 equal (data-types)
19874 *
19875 * the ·value space·s of all ·primitive· datatypes are disjoint
19876 * (they do not share any values)
19877 */
19878 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
19879 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
19880 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
19881 return(0);
19882
19883 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19884 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
19885 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19886 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
19887 TODO
19888 return(0);
19889 }
19890 /*
19891 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
19892 * T then the ·value space· of T' is a subset of the ·value space· of T.
19893 */
19894 /*
19895 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
19896 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
19897 */
19898
19899 {
19900 xmlSchemaTypePtr pta = ta, ptb = tb;
19901
19902 /* Note that we will compare the primitives here. */
19903 while ((pta->builtInType == 0) ||
19904 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19905 pta = pta->baseType;
19906 while ((ptb->builtInType == 0) ||
19907 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19908 ptb = ptb->baseType;
19909 if (pta == ptb)
19910 goto compareValue;
19911 return(0);
19912 }
19913compareValue:
19914 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019915 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019916 int aws, bws;
19917
19918 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
19919 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
19920
19921 ret = xmlSchemaCompareValuesWhtsp(
19922 a, (xmlSchemaWhitespaceValueType) aws,
19923 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019924 if (ret == 0)
19925 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019926 else if (ret == -2) {
19927 xmlSchemaVErr(vctxt, vctxt->node,
19928 XML_SCHEMAV_INTERNAL,
19929 "Internal error: xmlSchemaAreValuesEqual, "
19930 "failed to compare the values.\n",
19931 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019932 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019933 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019934 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019935 }
19936}
19937
19938/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019939 * xmlSchemaIDCAddStateObject:
19940 * @vctxt: the WXS validation context
19941 * @matcher: the IDC matcher
19942 * @sel: the XPath information
19943 * @parent: the parent "selector" state object if any
19944 * @type: "selector" or "field"
19945 *
19946 * Creates/reuses and activates state objects for the given
19947 * XPath information; if the XPath expression consists of unions,
19948 * multiple state objects are created for every unioned expression.
19949 *
19950 * Returns 0 on success and -1 on internal errors.
19951 */
19952static int
19953xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19954 xmlSchemaIDCMatcherPtr matcher,
19955 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019956 int type)
19957{
19958 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019959
19960 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019961 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019962 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019963 if (vctxt->xpathStatePool != NULL) {
19964 sto = vctxt->xpathStatePool;
19965 vctxt->xpathStatePool = sto->next;
19966 sto->next = NULL;
19967 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019968 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019969 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019970 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019971 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19972 if (sto == NULL) {
19973 xmlSchemaVErrMemory(NULL,
19974 "allocating an IDC state object", NULL);
19975 return (-1);
19976 }
19977 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19978 }
19979 /*
19980 * Add to global list.
19981 */
19982 if (vctxt->xpathStates != NULL)
19983 sto->next = vctxt->xpathStates;
19984 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019985
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019986 /*
19987 * Free the old xpath validation context.
19988 */
19989 if (sto->xpathCtxt != NULL)
19990 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19991
19992 /*
19993 * Create a new XPath (pattern) validation context.
19994 */
19995 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19996 (xmlPatternPtr) sel->xpathComp);
19997 if (sto->xpathCtxt == NULL) {
19998 xmlSchemaVErr(vctxt, vctxt->node,
19999 XML_SCHEMAV_INTERNAL,
20000 "Internal error: xmlSchemaIDCAddStateObject, "
20001 "failed to create the XPath validation context.\n",
20002 NULL, NULL);
20003 return (-1);
20004 }
20005 sto->type = type;
20006 sto->depth = vctxt->depth;
20007 sto->matcher = matcher;
20008 sto->sel = sel;
20009 sto->nbHistory = 0;
20010
20011#if DEBUG_IDC
20012 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
20013 sto->sel->xpath);
20014#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020015 return (0);
20016}
20017
20018/**
20019 * xmlSchemaXPathEvaluate:
20020 * @vctxt: the WXS validation context
20021 * @nodeType: the nodeType of the current node
20022 *
20023 * Evaluates all active XPath state objects.
20024 *
20025 * Returns the number of IC "field" state objects which resolved to
20026 * this node, 0 if none resolved and -1 on internal errors.
20027 */
20028static int
20029xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020030 xmlElementType nodeType)
20031{
20032 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020033 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020034
20035 if (vctxt->xpathStates == NULL)
20036 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020037
20038 if (nodeType == XML_ATTRIBUTE_NODE)
20039 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020040#if DEBUG_IDC
20041 {
20042 xmlChar *str = NULL;
20043 xmlGenericError(xmlGenericErrorContext,
20044 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020045 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20046 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020047 FREE_AND_NULL(str)
20048 }
20049#endif
20050 /*
20051 * Process all active XPath state objects.
20052 */
20053 first = vctxt->xpathStates;
20054 sto = first;
20055 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020056#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020057 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020058 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
20059 sto->matcher->aidc->def->name, sto->sel->xpath);
20060 else
20061 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
20062 sto->matcher->aidc->def->name, sto->sel->xpath);
20063#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020064 if (nodeType == XML_ELEMENT_NODE)
20065 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
20066 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
20067 else
20068 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
20069 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
20070
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020071 if (res == -1) {
20072 xmlSchemaVErr(vctxt, vctxt->node,
20073 XML_SCHEMAV_INTERNAL,
20074 "Internal error: xmlSchemaXPathEvaluate, "
20075 "failed to evaluate a node.\n",
20076 NULL, NULL);
20077 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020078 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020079 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020080 goto next_sto;
20081 /*
20082 * Full match.
20083 */
20084#if DEBUG_IDC
20085 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020086 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020087#endif
20088 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020089 * Register a match in the state object history.
20090 */
20091 if (sto->history == NULL) {
20092 sto->history = (int *) xmlMalloc(5 * sizeof(int));
20093 if (sto->history == NULL) {
20094 xmlSchemaVErrMemory(NULL,
20095 "allocating the state object history", NULL);
20096 return(-1);
20097 }
20098 sto->sizeHistory = 10;
20099 } else if (sto->sizeHistory <= sto->nbHistory) {
20100 sto->sizeHistory *= 2;
20101 sto->history = (int *) xmlRealloc(sto->history,
20102 sto->sizeHistory * sizeof(int));
20103 if (sto->history == NULL) {
20104 xmlSchemaVErrMemory(NULL,
20105 "re-allocating the state object history", NULL);
20106 return(-1);
20107 }
20108 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020109 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020110
20111#ifdef DEBUG_IDC
20112 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
20113 vctxt->depth);
20114#endif
20115
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020116 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
20117 xmlSchemaIDCSelectPtr sel;
20118 /*
20119 * Activate state objects for the IDC fields of
20120 * the IDC selector.
20121 */
20122#if DEBUG_IDC
20123 xmlGenericError(xmlGenericErrorContext, "IDC: "
20124 "activating field states\n");
20125#endif
20126 sel = sto->matcher->aidc->def->fields;
20127 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020128 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
20129 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
20130 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020131 sel = sel->next;
20132 }
20133 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
20134 /*
20135 * An IDC key node was found.
20136 */
20137#if DEBUG_IDC
20138 xmlGenericError(xmlGenericErrorContext,
20139 "IDC: key found\n");
20140#endif
20141 /*
20142 * Notify that the character value of this node is
20143 * needed.
20144 */
20145 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020146 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020147 resolved++;
20148 }
20149next_sto:
20150 if (sto->next == NULL) {
20151 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020152 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020153 */
20154 head = first;
20155 sto = vctxt->xpathStates;
20156 } else
20157 sto = sto->next;
20158 }
20159 return (resolved);
20160}
20161
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020162static const xmlChar *
20163xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr ctxt,
20164 xmlChar **buf,
20165 xmlSchemaPSVIIDCKeyPtr *seq,
20166 int count)
20167{
20168 int i, res;
20169 const xmlChar *value = NULL;
20170
20171 *buf = xmlStrdup(BAD_CAST "[");
20172 for (i = 0; i < count; i++) {
20173 *buf = xmlStrcat(*buf, BAD_CAST "'");
20174 res = xmlSchemaGetCanonValueWhtsp(seq[i]->compValue, &value,
20175 (xmlSchemaWhitespaceValueType)
20176 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
20177 if (res == 0)
20178 *buf = xmlStrcat(*buf, value);
20179 else {
20180 xmlSchemaVErr(ctxt, ctxt->node,
20181 XML_SCHEMAV_INTERNAL,
20182 "Internal error: xmlSchemaFormatIDCKeySequence, "
20183 "failed to compute canonical value.\n",
20184 NULL, NULL);
20185 *buf = xmlStrcat(*buf, BAD_CAST "???");
20186 }
20187 if (i < count -1)
20188 *buf = xmlStrcat(*buf, BAD_CAST "', ");
20189 else
20190 *buf = xmlStrcat(*buf, BAD_CAST "'");
20191 if (value != NULL) {
20192 xmlFree((xmlChar *) value);
20193 value = NULL;
20194 }
20195 }
20196 *buf = xmlStrcat(*buf, BAD_CAST "]");
20197
20198 return (BAD_CAST *buf);
20199}
20200
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020201/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020202 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020203 * @vctxt: the WXS validation context
20204 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020205 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020206 *
20207 * Processes and pops the history items of the IDC state objects.
20208 * IDC key-sequences are validated/created on IDC bindings.
20209 *
20210 * Returns 0 on success and -1 on internal errors.
20211 */
20212static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020213xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020214 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020215{
20216 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020217 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020218 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020219 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020220
20221 if (vctxt->xpathStates == NULL)
20222 return (0);
20223 sto = vctxt->xpathStates;
20224
20225#if DEBUG_IDC
20226 {
20227 xmlChar *str = NULL;
20228 xmlGenericError(xmlGenericErrorContext,
20229 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020230 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20231 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020232 FREE_AND_NULL(str)
20233 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020234#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020235 /*
20236 * Evaluate the state objects.
20237 */
20238 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020239 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020240#if DEBUG_IDC
20241 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
20242 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020243#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020244 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020245 goto deregister_check;
20246
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020247 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020248
20249 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020250 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020251 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020252 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020253 sto = sto->next;
20254 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020255 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020256 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
20257 if (! IS_SIMPLE_TYPE(type)) {
20258 /*
20259 * Not qualified if the field resolves to a node of non
20260 * simple type.
20261 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020262 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020263 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020264 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020265 (xmlSchemaTypePtr) sto->matcher->aidc->def,
20266 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020267 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020268
20269 sto->nbHistory--;
20270 goto deregister_check;
20271 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020272 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020273 /*
20274 * Failed to provide the normalized value; maby
20275 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020276 */
20277 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020278 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020279 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020280 (xmlSchemaTypePtr) sto->matcher->aidc->def,
20281 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020282 "was either invalid or something strange happend",
20283 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020284 /*
20285 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020286 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020287 "Internal error: xmlSchemaXPathProcessHistory, "
20288 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020289 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020290 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020291 sto->nbHistory--;
20292 goto deregister_check;
20293 } else {
20294 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
20295 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020296 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020297
20298 /*
20299 * The key will be anchored on the matcher's list of
20300 * key-sequences. The position in this list is determined
20301 * by the target node's depth relative to the matcher's
20302 * depth of creation (i.e. the depth of the scope element).
20303 */
20304 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020305 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020306
20307 /*
20308 * Create/grow the array of key-sequences.
20309 */
20310 if (matcher->keySeqs == NULL) {
20311 if (pos > 9)
20312 matcher->sizeKeySeqs = pos * 2;
20313 else
20314 matcher->sizeKeySeqs = 10;
20315 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
20316 xmlMalloc(matcher->sizeKeySeqs *
20317 sizeof(xmlSchemaPSVIIDCKeyPtr *));
20318 if (matcher->keySeqs == NULL) {
20319 xmlSchemaVErrMemory(NULL,
20320 "allocating an array of key-sequences",
20321 NULL);
20322 return(-1);
20323 }
20324 memset(matcher->keySeqs, 0,
20325 matcher->sizeKeySeqs *
20326 sizeof(xmlSchemaPSVIIDCKeyPtr *));
20327 } else if (pos >= matcher->sizeKeySeqs) {
20328 int i = matcher->sizeKeySeqs;
20329
20330 matcher->sizeKeySeqs *= 2;
20331 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
20332 xmlRealloc(matcher->keySeqs,
20333 matcher->sizeKeySeqs *
20334 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020335 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020336 xmlSchemaVErrMemory(NULL,
20337 "reallocating an array of key-sequences",
20338 NULL);
20339 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020340 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020341 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020342 * The array needs to be NULLed.
20343 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020344 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020345 for (; i < matcher->sizeKeySeqs; i++)
20346 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020347 }
20348
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020349 /*
20350 * Get/create the key-sequence.
20351 */
20352 keySeq = matcher->keySeqs[pos];
20353 if (keySeq == NULL) {
20354 goto create_sequence;
20355 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020356 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020357 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020358 * cvc-identity-constraint:
20359 * 3 For each node in the ·target node set· all
20360 * of the {fields}, with that node as the context
20361 * node, evaluate to either an empty node-set or
20362 * a node-set with exactly one member, which must
20363 * have a simple type.
20364 *
20365 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020366 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020367 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020368 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020369 vctxt->nodeInfo,
20370 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020371 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020372 "with more than one member",
20373 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020374 sto->nbHistory--;
20375 goto deregister_check;
20376 } else {
20377 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020378 }
20379 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020380
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020381create_sequence:
20382 /*
20383 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020384 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020385 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
20386 matcher->aidc->def->nbFields *
20387 sizeof(xmlSchemaPSVIIDCKeyPtr));
20388 if (keySeq == NULL) {
20389 xmlSchemaVErrMemory(NULL,
20390 "allocating an IDC key-sequence", NULL);
20391 return(-1);
20392 }
20393 memset(keySeq, 0, matcher->aidc->def->nbFields *
20394 sizeof(xmlSchemaPSVIIDCKeyPtr));
20395 matcher->keySeqs[pos] = keySeq;
20396create_key:
20397 /*
20398 * Created a key once per node only.
20399 */
20400 if (key == NULL) {
20401 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
20402 sizeof(xmlSchemaPSVIIDCKey));
20403 if (key == NULL) {
20404 xmlSchemaVErrMemory(NULL,
20405 "allocating a IDC key", NULL);
20406 xmlFree(keySeq);
20407 matcher->keySeqs[pos] = NULL;
20408 return(-1);
20409 }
20410 /*
20411 * Consume the compiled value.
20412 */
20413 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020414 key->compValue = vctxt->nodeInfo->value;
20415 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020416 /*
20417 * Store the key in a global list.
20418 */
20419 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
20420 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020421 return (-1);
20422 }
20423 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020424 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020425 }
20426 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020427
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020428 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
20429 xmlSchemaPSVIIDCBindingPtr bind;
20430 xmlSchemaPSVIIDCNodePtr ntItem;
20431 xmlSchemaIDCMatcherPtr matcher;
20432 xmlSchemaIDCPtr idc;
20433 int pos, i, j, nbKeys;
20434 /*
20435 * Here we have the following scenario:
20436 * An IDC 'selector' state object resolved to a target node,
20437 * during the time this target node was in the
20438 * ancestor-or-self axis, the 'field' state object(s) looked
20439 * out for matching nodes to create a key-sequence for this
20440 * target node. Now we are back to this target node and need
20441 * to put the key-sequence, together with the target node
20442 * itself, into the node-table of the corresponding IDC
20443 * binding.
20444 */
20445 matcher = sto->matcher;
20446 idc = matcher->aidc->def;
20447 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020448 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020449 /*
20450 * Check if the matcher has any key-sequences at all, plus
20451 * if it has a key-sequence for the current target node.
20452 */
20453 if ((matcher->keySeqs == NULL) ||
20454 (matcher->sizeKeySeqs <= pos)) {
20455 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
20456 goto selector_key_error;
20457 else
20458 goto selector_leave;
20459 }
20460
20461 keySeq = &(matcher->keySeqs[pos]);
20462 if (*keySeq == NULL) {
20463 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
20464 goto selector_key_error;
20465 else
20466 goto selector_leave;
20467 }
20468
20469 for (i = 0; i < nbKeys; i++) {
20470 if ((*keySeq)[i] == NULL) {
20471 /*
20472 * Not qualified, if not all fields did resolve.
20473 */
20474 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
20475 /*
20476 * All fields of a "key" IDC must resolve.
20477 */
20478 goto selector_key_error;
20479 }
20480 goto selector_leave;
20481 }
20482 }
20483 /*
20484 * All fields did resolve.
20485 */
20486
20487 /*
20488 * 4.1 If the {identity-constraint category} is unique(/key),
20489 * then no two members of the ·qualified node set· have
20490 * ·key-sequences· whose members are pairwise equal, as
20491 * defined by Equal in [XML Schemas: Datatypes].
20492 *
20493 * Get the IDC binding from the matcher and check for
20494 * duplicate key-sequences.
20495 */
20496 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
20497 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
20498 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020499 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020500
20501 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020502 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020503 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020504 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020505 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020506 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020507 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020508 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020509 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020510 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020511 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
20512 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020513 if (res == -1) {
20514 return (-1);
20515 } else if (res == 0)
20516 break;
20517 }
20518 if (res == 1) {
20519 /*
20520 * Duplicate found.
20521 */
20522 break;
20523 }
20524 i++;
20525 } while (i < bind->nbNodes);
20526 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020527 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020528 /*
20529 * TODO: Try to report the key-sequence.
20530 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020531 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020532 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020533 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020534 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020535 "Duplicate key-sequence %s",
20536 xmlSchemaFormatIDCKeySequence(vctxt, &str,
20537 (*keySeq), nbKeys), NULL);
20538 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020539 goto selector_leave;
20540 }
20541 }
20542 /*
20543 * Add a node-table item to the IDC binding.
20544 */
20545 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
20546 sizeof(xmlSchemaPSVIIDCNode));
20547 if (ntItem == NULL) {
20548 xmlSchemaVErrMemory(NULL,
20549 "allocating an IDC node-table item", NULL);
20550 xmlFree(*keySeq);
20551 *keySeq = NULL;
20552 return(-1);
20553 }
20554 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
20555
20556 /*
20557 * Store the node-table item on global list.
20558 */
20559 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
20560 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
20561 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020562 xmlFree(*keySeq);
20563 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020564 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020565 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020566 }
20567 /*
20568 * Init the node-table item. Consume the key-sequence.
20569 */
20570 ntItem->node = vctxt->node;
20571 ntItem->keys = *keySeq;
20572 *keySeq = NULL;
20573 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
20574 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20575 /*
20576 * Free the item, since keyref items won't be
20577 * put on a global list.
20578 */
20579 xmlFree(ntItem->keys);
20580 xmlFree(ntItem);
20581 }
20582 return (-1);
20583 }
20584
20585 goto selector_leave;
20586selector_key_error:
20587 /*
20588 * 4.2.1 (KEY) The ·target node set· and the
20589 * ·qualified node set· are equal, that is, every
20590 * member of the ·target node set· is also a member
20591 * of the ·qualified node set· and vice versa.
20592 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020593 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020594 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020595 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020596 (xmlSchemaTypePtr) idc,
20597 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020598 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020599selector_leave:
20600 /*
20601 * Free the key-sequence if not added to the IDC table.
20602 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020603 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020604 xmlFree(*keySeq);
20605 *keySeq = NULL;
20606 }
20607 } /* if selector */
20608
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020609 sto->nbHistory--;
20610
20611deregister_check:
20612 /*
20613 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020614 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020615 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020616#if DEBUG_IDC
20617 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
20618 sto->sel->xpath);
20619#endif
20620 if (vctxt->xpathStates != sto) {
20621 xmlSchemaVErr(vctxt, vctxt->node,
20622 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020623 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020624 "The state object to be removed is not the first "
20625 "in the list.\n",
20626 NULL, NULL);
20627 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020628 nextsto = sto->next;
20629 /*
20630 * Unlink from the list of active XPath state objects.
20631 */
20632 vctxt->xpathStates = sto->next;
20633 sto->next = vctxt->xpathStatePool;
20634 /*
20635 * Link it to the pool of reusable state objects.
20636 */
20637 vctxt->xpathStatePool = sto;
20638 sto = nextsto;
20639 } else
20640 sto = sto->next;
20641 } /* while (sto != NULL) */
20642 return (0);
20643}
20644
20645/**
20646 * xmlSchemaIDCRegisterMatchers:
20647 * @vctxt: the WXS validation context
20648 * @elemDecl: the element declaration
20649 *
20650 * Creates helper objects to evaluate IDC selectors/fields
20651 * successively.
20652 *
20653 * Returns 0 if OK and -1 on internal errors.
20654 */
20655static int
20656xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
20657 xmlSchemaElementPtr elemDecl)
20658{
20659 xmlSchemaIDCMatcherPtr matcher, last = NULL;
20660 xmlSchemaIDCPtr idc, refIdc;
20661 xmlSchemaIDCAugPtr aidc;
20662
20663 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
20664 if (idc == NULL)
20665 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020666
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020667#if DEBUG_IDC
20668 {
20669 xmlChar *str = NULL;
20670 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020671 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020672 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
20673 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020674 FREE_AND_NULL(str)
20675 }
20676#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020677 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020678 xmlSchemaVErr(vctxt, vctxt->node,
20679 XML_SCHEMAV_INTERNAL,
20680 "Internal error: xmlSchemaIDCRegisterMatchers: "
20681 "The chain of IDC matchers is expected to be empty.\n",
20682 NULL, NULL);
20683 return (-1);
20684 }
20685 do {
20686 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20687 /*
20688 * Since IDCs bubbles are expensive we need to know the
20689 * depth at which the bubbles should stop; this will be
20690 * the depth of the top-most keyref IDC. If no keyref
20691 * references a key/unique IDC, the bubbleDepth will
20692 * be -1, indicating that no bubbles are needed.
20693 */
20694 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
20695 if (refIdc != NULL) {
20696 /*
20697 * Lookup the augmented IDC.
20698 */
20699 aidc = vctxt->aidcs;
20700 while (aidc != NULL) {
20701 if (aidc->def == refIdc)
20702 break;
20703 aidc = aidc->next;
20704 }
20705 if (aidc == NULL) {
20706 xmlSchemaVErr(vctxt, vctxt->node,
20707 XML_SCHEMAV_INTERNAL,
20708 "Internal error: xmlSchemaIDCRegisterMatchers: "
20709 "Could not find an augmented IDC item for an IDC "
20710 "definition.\n",
20711 NULL, NULL);
20712 return (-1);
20713 }
20714 if ((aidc->bubbleDepth == -1) ||
20715 (vctxt->depth < aidc->bubbleDepth))
20716 aidc->bubbleDepth = vctxt->depth;
20717 }
20718 }
20719 /*
20720 * Lookup the augmented IDC item for the IDC definition.
20721 */
20722 aidc = vctxt->aidcs;
20723 while (aidc != NULL) {
20724 if (aidc->def == idc)
20725 break;
20726 aidc = aidc->next;
20727 }
20728 if (aidc == NULL) {
20729 xmlSchemaVErr(vctxt, vctxt->node,
20730 XML_SCHEMAV_INTERNAL,
20731 "Internal error: xmlSchemaIDCRegisterMatchers: "
20732 "Could not find an augmented IDC item for an IDC definition.\n",
20733 NULL, NULL);
20734 return (-1);
20735 }
20736 /*
20737 * Create an IDC matcher for every IDC definition.
20738 */
20739 matcher = (xmlSchemaIDCMatcherPtr)
20740 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20741 if (matcher == NULL) {
20742 xmlSchemaVErrMemory(vctxt,
20743 "allocating an IDC matcher", NULL);
20744 return (-1);
20745 }
20746 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20747 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020748 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020749 else
20750 last->next = matcher;
20751 last = matcher;
20752
20753 matcher->type = IDC_MATCHER;
20754 matcher->depth = vctxt->depth;
20755 matcher->aidc = aidc;
20756#if DEBUG_IDC
20757 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20758#endif
20759 /*
20760 * Init the automaton state object.
20761 */
20762 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020763 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020764 return (-1);
20765
20766 idc = idc->next;
20767 } while (idc != NULL);
20768 return (0);
20769}
20770
20771/**
20772 * xmlSchemaBubbleIDCNodeTables:
20773 * @depth: the current tree depth
20774 *
20775 * Merges IDC bindings of an element at @depth into the corresponding IDC
20776 * bindings of its parent element. If a duplicate note-table entry is found,
20777 * both, the parent node-table entry and child entry are discarded from the
20778 * node-table of the parent.
20779 *
20780 * Returns 0 if OK and -1 on internal errors.
20781 */
20782static int
20783xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20784{
20785 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020786 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20787 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020788 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20789 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020790 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020791 int duplTop;
20792
20793 /*
20794 * The node table has the following sections:
20795 *
20796 * O --> old node-table entries (first)
20797 * O
20798 * + --> new node-table entries
20799 * +
20800 * % --> new duplicate node-table entries
20801 * %
20802 * # --> old duplicate node-table entries
20803 * # (last)
20804 *
20805 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020806 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020807 if (bind == NULL) {
20808 /* Fine, no table, no bubbles. */
20809 return (0);
20810 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020811
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020812 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20813 /*
20814 * Walk all bindings; create new or add to existing bindings.
20815 * Remove duplicate key-sequences.
20816 */
20817start_binding:
20818 while (bind != NULL) {
20819 /*
20820 * Skip keyref IDCs.
20821 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020822 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20823 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020824 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020825 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020826 /*
20827 * Check if the key/unique IDC table needs to be bubbled.
20828 */
20829 aidc = vctxt->aidcs;
20830 do {
20831 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020832 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020833 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020834 bind = bind->next;
20835 goto start_binding;
20836 }
20837 break;
20838 }
20839 aidc = aidc->next;
20840 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020841
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020842 if (parTable != NULL)
20843 parBind = *parTable;
20844 while (parBind != NULL) {
20845 /*
20846 * Search a matching parent binding for the
20847 * IDC definition.
20848 */
20849 if (parBind->definition == bind->definition) {
20850
20851 /*
20852 * Compare every node-table entry of the child node,
20853 * i.e. the key-sequence within, ...
20854 */
20855 oldNum = parBind->nbNodes; /* Skip newly added items. */
20856 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020857 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020858
20859 for (i = 0; i < bind->nbNodes; i++) {
20860 node = bind->nodeTable[i];
20861 if (node == NULL)
20862 continue;
20863 /*
20864 * ...with every key-sequence of the parent node, already
20865 * evaluated to be a duplicate key-sequence.
20866 */
20867 if (parBind->nbDupls != 0) {
20868 j = bind->nbNodes + newDupls;
20869 while (j < duplTop) {
20870 parNode = parBind->nodeTable[j];
20871 for (k = 0; k < bind->definition->nbFields; k++) {
20872 key = node->keys[k];
20873 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020874 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020875 key->compValue,
20876 parKey->type, parKey->compValue);
20877 if (ret == -1) {
20878 /* TODO: Internal error */
20879 return(-1);
20880 } else if (ret == 0)
20881 break;
20882
20883 }
20884 if (ret == 1)
20885 /* Duplicate found. */
20886 break;
20887 j++;
20888 }
20889 if (j != duplTop) {
20890 /* Duplicate found. */
20891 continue;
20892 }
20893 }
20894 /*
20895 * ... and with every key-sequence of the parent node.
20896 */
20897 j = 0;
20898 while (j < oldNum) {
20899 parNode = parBind->nodeTable[j];
20900 /*
20901 * Compare key by key.
20902 */
20903 for (k = 0; k < parBind->definition->nbFields; k++) {
20904 key = node->keys[k];
20905 parKey = parNode->keys[k];
20906
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020907 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020908 key->compValue,
20909 parKey->type, parKey->compValue);
20910 if (ret == -1) {
20911 /* TODO: Internal error */
20912 } else if (ret == 0)
20913 break;
20914
20915 }
20916 if (ret == 1)
20917 /*
20918 * The key-sequences are equal.
20919 */
20920 break;
20921 j++;
20922 }
20923 if (j != oldNum) {
20924 /*
20925 * Handle duplicates.
20926 */
20927 newDupls++;
20928 oldNum--;
20929 parBind->nbNodes--;
20930 /*
20931 * Move last old item to pos of duplicate.
20932 */
20933 parBind->nodeTable[j] =
20934 parBind->nodeTable[oldNum];
20935
20936 if (parBind->nbNodes != oldNum) {
20937 /*
20938 * If new items exist, move last new item to
20939 * last of old items.
20940 */
20941 parBind->nodeTable[oldNum] =
20942 parBind->nodeTable[parBind->nbNodes];
20943 }
20944 /*
20945 * Move duplicate to last pos of new/old items.
20946 */
20947 parBind->nodeTable[parBind->nbNodes] = parNode;
20948
20949 } else {
20950 /*
20951 * Add the node-table entry (node and key-sequence) of
20952 * the child node to the node table of the parent node.
20953 */
20954 if (parBind->nodeTable == NULL) {
20955 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020956 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020957 if (parBind->nodeTable == NULL) {
20958 xmlSchemaVErrMemory(NULL,
20959 "allocating IDC list of node-table items", NULL);
20960 return(-1);
20961 }
20962 parBind->sizeNodes = 1;
20963 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020964 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020965 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20966 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20967 sizeof(xmlSchemaPSVIIDCNodePtr));
20968 if (parBind->nodeTable == NULL) {
20969 xmlSchemaVErrMemory(NULL,
20970 "re-allocating IDC list of node-table items", NULL);
20971 return(-1);
20972 }
20973 }
20974
20975 /*
20976 * Move first old duplicate to last position
20977 * of old duplicates +1.
20978 */
20979 if (parBind->nbDupls != 0) {
20980 parBind->nodeTable[duplTop] =
20981 parBind->nodeTable[parBind->nbNodes + newDupls];
20982 }
20983 /*
20984 * Move first new duplicate to last position of
20985 * new duplicates +1.
20986 */
20987 if (newDupls != 0) {
20988 parBind->nodeTable[parBind->nbNodes + newDupls] =
20989 parBind->nodeTable[parBind->nbNodes];
20990 }
20991 /*
20992 * Append the new node-table entry to the 'new node-table
20993 * entries' section.
20994 */
20995 parBind->nodeTable[parBind->nbNodes] = node;
20996 parBind->nbNodes++;
20997 duplTop++;
20998 }
20999 }
21000 parBind->nbDupls += newDupls;
21001 break;
21002 }
21003 if (parBind->next == NULL)
21004 lastParBind = parBind;
21005 parBind = parBind->next;
21006 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000021007 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021008 /*
21009 * No binding for the IDC was found: create a new one and
21010 * copy all node-tables.
21011 */
21012 parBind = xmlSchemaIDCNewBinding(bind->definition);
21013 if (parBind == NULL)
21014 return(-1);
21015
21016 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21017 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
21018 if (parBind->nodeTable == NULL) {
21019 xmlSchemaVErrMemory(NULL,
21020 "allocating an array of IDC node-table items", NULL);
21021 xmlSchemaIDCFreeBinding(parBind);
21022 return(-1);
21023 }
21024 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021025 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021026 memcpy(parBind->nodeTable, bind->nodeTable,
21027 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021028 if (*parTable == NULL)
21029 *parTable = parBind;
21030 else
21031 lastParBind->next = parBind;
21032 }
21033 bind = bind->next;
21034 }
21035 return (0);
21036}
21037
21038/**
21039 * xmlSchemaCheckCVCIDCKeyRef:
21040 * @vctxt: the WXS validation context
21041 * @elemDecl: the element declaration
21042 *
21043 * Check the cvc-idc-keyref constraints.
21044 */
21045static int
21046xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
21047{
21048 xmlSchemaPSVIIDCBindingPtr refbind, bind;
21049
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021050 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021051 /*
21052 * Find a keyref.
21053 */
21054 while (refbind != NULL) {
21055 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
21056 int i, j, k, res;
21057 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
21058 xmlSchemaPSVIIDCKeyPtr refKey, key;
21059
21060 /*
21061 * Find the referred key/unique.
21062 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021063 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021064 do {
21065 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
21066 bind->definition)
21067 break;
21068 bind = bind->next;
21069 } while (bind != NULL);
21070
21071 /*
21072 * Search for a matching key-sequences.
21073 */
21074 for (i = 0; i < refbind->nbNodes; i++) {
21075 res = 0;
21076 if (bind != NULL) {
21077 refKeys = refbind->nodeTable[i]->keys;
21078 for (j = 0; j < bind->nbNodes; j++) {
21079 keys = bind->nodeTable[j]->keys;
21080 for (k = 0; k < bind->definition->nbFields; k++) {
21081 refKey = refKeys[k];
21082 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021083 res = xmlSchemaAreValuesEqual(vctxt,
21084 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021085 refKey->type, refKey->compValue);
21086 if (res == 0)
21087 break;
21088 else if (res == -1) {
21089 return (-1);
21090 }
21091 }
21092 if (res == 1) {
21093 /*
21094 * Match found.
21095 */
21096 break;
21097 }
21098 }
21099 }
21100 if (res == 0) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000021101 xmlChar *str = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021102 /* TODO: Report the key-sequence. */
21103 xmlSchemaVCustomErr(vctxt,
21104 XML_SCHEMAV_CVC_IDC,
21105 refbind->nodeTable[i]->node,
21106 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000021107 "No match found for key reference %s",
21108 xmlSchemaFormatIDCKeySequence(vctxt, &str,
21109 refbind->nodeTable[i]->keys,
21110 refbind->definition->nbFields));
21111 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021112 }
21113 }
21114 }
21115 refbind = refbind->next;
21116 }
21117 return (0);
21118}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021119
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021120/**
21121 * xmlSchemaBeginElement:
21122 * @vctxt: the WXS validation context
21123 *
21124 * Just a temporary workaround to simulate streaming validation
21125 * a bit.
21126 */
21127static void
21128xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
21129{
21130 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021131 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
21132 vctxt->nodeInfo->node = vctxt->node;
21133 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021134 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021135 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021136 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021137 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021138}
21139
21140/**
21141 * xmlSchemaEndElement:
21142 * @vctxt: the WXS validation context
21143 *
21144 * Just a temporary workaround to simulate streaming validation
21145 * a bit.
21146 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021147static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021148xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
21149{
21150 if (vctxt->depth < 0) {
21151 /* TODO: raise error? */
21152 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021153 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021154 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021155 /*
21156 * Evaluate the history of changes of active state objects.
21157 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021158 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
21159 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021160
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021161 if (vctxt->nodeInfo->value != NULL) {
21162 xmlSchemaFreeValue(vctxt->nodeInfo->value);
21163 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021164 }
21165 /*
21166 * TODO: 6 The element information item must be ·valid· with respect to each of
21167 * the {identity-constraint definitions} as per Identity-constraint
21168 * Satisfied (§3.11.4).
21169 */
21170 /*
21171 * Validate IDC keyrefs.
21172 */
21173 xmlSchemaCheckCVCIDCKeyRef(vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021174
21175 /*
21176 * Merge/free the IDC table.
21177 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021178 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021179#ifdef DEBUG_IDC
21180 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021181 vctxt->nodeInfo->namespaceName,
21182 vctxt->nodeInfo->localName,
21183 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021184#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021185 if (vctxt->depth > 0) {
21186 /*
21187 * Merge the IDC node table with the table of the parent node.
21188 */
21189 xmlSchemaBubbleIDCNodeTables(vctxt);
21190 }
21191 /*
21192 * TODO: Don't free the PSVI IDC tables if they are
21193 * requested for the PSVI.
21194 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021195 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021196 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021197 }
21198
21199 /*
21200 * Cleanup IDC matchers.
21201 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021202 if (vctxt->nodeInfo->idcMatchers != NULL) {
21203 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
21204 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021205 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021206
21207 /*
21208 * Skip further processing if we are on the validation root.
21209 */
21210 if (vctxt->depth == 0) {
21211 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021212 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021213 }
21214
21215 /*
21216 * Reset the bubbleDepth if needed.
21217 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021218 if (vctxt->aidcs != NULL) {
21219 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
21220 do {
21221 if (aidc->bubbleDepth == vctxt->depth) {
21222 /*
21223 * A bubbleDepth of a key/unique IDC matches the current
21224 * depth, this means that we are leaving the scope of the
21225 * top-most keyref IDC.
21226 */
21227 aidc->bubbleDepth = -1;
21228 }
21229 aidc = aidc->next;
21230 } while (aidc != NULL);
21231 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021232 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021233 /*
21234 * Clear the current elemInfo.
21235 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021236 if (vctxt->nodeInfo->value != NULL) {
21237 xmlSchemaFreeValue(vctxt->nodeInfo->value);
21238 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021239 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021240 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
21241 vctxt->node = vctxt->nodeInfo->node;
21242
21243 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021244}
21245
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021246/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021247 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000021248 * @ctxt: a schema validation context
21249 * @node: the top node.
21250 *
21251 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021252 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000021253 *
21254 * Returns 0 if the element is schemas valid, a positive error code
21255 * number otherwise and -1 in case of internal or API error.
21256 */
21257static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021258xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
21259 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021260{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021261 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021262 int ret = 0;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021263 xmlSchemaTypePtr actualType = NULL, localType = NULL, type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021264 xmlAttrPtr attr;
21265 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021266 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000021267
21268 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021269 * This one is called by xmlSchemaValidateElementByWildcardInternal,
21270 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021271 * Note that @elemDecl will be the declaration and never the
21272 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021273 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021274
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021275 if (ctxt == NULL) {
21276 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
21277 "Internal error: xmlSchemaValidateElementByDeclaration, "
21278 "bad arguments.\n",
21279 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021280 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021281 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021282
21283 elem = ctxt->node;
21284
21285 /*
21286 * cvc-elt (3.3.4) : 1
21287 */
21288 if (elemDecl == NULL) {
21289 xmlSchemaVCustomErr(ctxt,
21290 XML_SCHEMAV_CVC_ELT_1,
21291 elem, NULL,
21292 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021293 /*
21294 * Evaluate IDCs even if an error occured.
21295 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021296 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021297 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021298 return (ctxt->err);
21299 }
21300 /*
21301 * cvc-elt (3.3.4) : 2
21302 */
21303 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21304 xmlSchemaVCustomErr(ctxt,
21305 XML_SCHEMAV_CVC_ELT_2,
21306 elem, NULL,
21307 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021308 /*
21309 * Evaluate IDCs even if an error occured.
21310 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021311 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021312 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021313 return (ctxt->err);
21314 }
21315
21316 /*
21317 * cvc-elt (3.3.4) : 3
21318 * Handle 'xsi:nil'.
21319 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021320
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021321 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021322 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021323 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
21324 ctxt->node = (xmlNodePtr) attr;
21325 ctxt->cur = attr->children;
21326 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
21327 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21328 BAD_CAST attrValue, 1, 1, 1, 1);
21329 ctxt->node = elem;
21330 ctxt->type = (xmlSchemaTypePtr) elemDecl;
21331 if (ret < 0) {
21332 xmlSchemaVCustomErr(ctxt,
21333 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021334 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021335 "Internal error: xmlSchemaValidateElementByDeclaration, "
21336 "validating the attribute 'xsi:nil'", NULL);
21337 if (attrValue != NULL)
21338 xmlFree(attrValue);
21339 return (-1);
21340 }
21341 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021342 /*
21343 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021344 */
21345 xmlSchemaVCustomErr(ctxt,
21346 XML_SCHEMAV_CVC_ELT_3_1,
21347 elem, NULL,
21348 "The element is not 'nillable'", NULL);
21349 } else {
21350 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021351 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021352 ret = 0;
21353 /*
21354 * cvc-elt (3.3.4) : 3.2.1
21355 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021356 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
21357 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021358 xmlSchemaVCustomErr(ctxt,
21359 XML_SCHEMAV_CVC_ELT_3_2_1,
21360 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021361 elem, (xmlSchemaTypePtr) elemDecl,
21362 "The 'nilled' element must have no character or "
21363 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021364 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
21365 }
21366 /*
21367 * cvc-elt (3.3.4) : 3.2.2
21368 */
21369 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21370 (elemDecl->value != NULL)) {
21371 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
21372 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021373 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021374 "There is a fixed value constraint defined for "
21375 "the 'nilled' element", NULL);
21376 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
21377 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021378 if (ret == 0)
21379 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021380 }
21381 }
21382 if (attrValue != NULL)
21383 xmlFree(attrValue);
21384 }
21385
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021386 type = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021387 actualType = type;
21388
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021389 /*
21390 * cvc-elt (3.3.4) : 4
21391 * Handle 'xsi:type'.
21392 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021393
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021394 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
21395 if (attr != NULL) {
21396 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021397
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021398 /*
21399 * TODO: We should report a *warning* that the type was overriden
21400 * by the instance.
21401 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021402
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021403 /*
21404 * cvc-elt (3.3.4) : 4.1
21405 */
21406 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
21407 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
21408 &nsName, &local);
21409 if (ret < 0) {
21410 xmlSchemaVCustomErr(ctxt,
21411 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021412 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021413 "Internal error: xmlSchemaValidateElementByDeclaration, "
21414 "validating the attribute 'xsi:type'", NULL);;
21415 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021416 FREE_AND_NULL(nsName)
21417 FREE_AND_NULL(local)
21418 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021419 } else if (ret == 1) {
21420 xmlSchemaVSimpleTypeErr(ctxt,
21421 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
21422 (xmlNodePtr) attr, attrValue,
21423 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
21424 } else if (ret == 2) {
21425 xmlSchemaVCustomErr(ctxt,
21426 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
21427 (xmlNodePtr) attr,
21428 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21429 "The QName value '%s' has no "
21430 "corresponding namespace declaration in scope",
21431 attrValue);
21432 } else {
21433 /*
21434 * cvc-elt (3.3.4) : 4.2
21435 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021436 localType = xmlSchemaGetType(ctxt->schema, local, nsName);
21437 if (localType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021438 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021439
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021440 xmlSchemaVCustomErr(ctxt,
21441 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021442 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021443 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021444 "The value '%s' of the xsi:type attribute does not "
21445 "resolve to a type definition",
21446 xmlSchemaFormatQName(&strA, nsName, local));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021447 FREE_AND_NULL(strA);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021448 } else {
21449 int set = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021450 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021451 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21452 * "The ·local type definition· must be validly
21453 * derived from the {type definition} given the union of
21454 * the {disallowed substitutions} and the {type definition}'s
21455 * {prohibited substitutions}, as defined in
21456 * Type Derivation OK (Complex) (§3.4.6)
21457 * (if it is a complex type definition),
21458 * or given {disallowed substitutions} as defined in Type
21459 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21460 * definition)."
21461 *
21462 * {disallowed substitutions}: the "block" on the element decl.
21463 * {prohibited substitutions}: the "block" on the type def.
21464 */
21465 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21466 (type->flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21467 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
21468
21469 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21470 (type->flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21471 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
21472
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021473 if (xmlSchemaCheckCOSDerivedOK(ctxt->schema, localType,
21474 type, set) != 0) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021475 xmlChar *strA = NULL, *strB = NULL;
21476
21477 xmlSchemaVCustomErrExt(ctxt,
21478 /* TODO: Error code */
21479 XML_SCHEMAV_CVC_ELT_4_2, elem, localType,
21480 "The xsi:type definition '%s' is not validly derived from "
21481 "the type definition '%s'",
21482 xmlSchemaFormatQName(&strA,
21483 localType->targetNamespace,
21484 localType->name),
21485 xmlSchemaFormatQName(&strB,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021486 ELEM_TYPE(elemDecl)->targetNamespace,
21487 ELEM_TYPE(elemDecl)->name), NULL);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021488 FREE_AND_NULL(strA)
21489 FREE_AND_NULL(strB)
21490 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021491 }
21492 }
21493 FREE_AND_NULL(attrValue)
21494 FREE_AND_NULL(nsName)
21495 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021496 }
21497 /* TODO: Change the handling of missing types according to
21498 * the spec.
21499 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000021500 if (localType != NULL)
21501 actualType = localType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021502 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021503 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021504 XML_SCHEMAV_CVC_TYPE_1,
21505 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021506 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021507 /*
21508 * Evaluate IDCs even if an error occured.
21509 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021510 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021511 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021512 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021513 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021514
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021515 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021516 * Remember the actual-type definition.
21517 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021518 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021519
21520 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021521 * TODO: Since this should be already checked by the content model automaton,
21522 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
21523 * has been changed to XML_SCHEMAV_INTERNAL.
21524 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021525 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000021526 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021527 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021528 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021529 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021530 "Element %s: missing child %s\n",
21531 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021532 }
21533 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021534 }
21535 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021536 /*
21537 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021538 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021539 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000021540 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021541 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021542 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021543 "Element %s: missing child %s found %s\n",
21544 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021545 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021546 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021547 */
21548 if (elemHasContent == -1)
21549 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021550
21551 /*
21552 * IDC: Register identity-constraint XPath matchers.
21553 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021554 if (elemDecl->idcs != NULL)
21555 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
21556 /*
21557 * Evaluate IDCs.
21558 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021559 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021560 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021561 /*
21562 * cvc-elt (3.3.4) : 5
21563 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021564 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021565 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021566 * cvc-elt (3.3.4) : 5.1
21567 * If the declaration has a {value constraint},
21568 * the item has neither element nor character [children] and
21569 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021570 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021571 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
21572 /*
21573 * cvc-elt (3.3.4) : 5.1.1
21574 * If the ·actual type definition· is a ·local type definition·
21575 * then the canonical lexical representation of the {value constraint}
21576 * value must be a valid default for the ·actual type definition· as
21577 * defined in Element Default Valid (Immediate) (§3.3.6).
21578 */
21579 /*
21580 * NOTE: 'local' above means types aquired by xsi:type.
21581 */
21582 ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021583 if (actualType != ELEM_TYPE(elemDecl)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021584 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
21585 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021586 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021587 if (ret < 0) {
21588 xmlSchemaVCustomErr(ctxt,
21589 XML_SCHEMAV_INTERNAL,
21590 elem, actualType,
21591 "Internal error: xmlSchemaValidateElementByDeclaration, "
21592 "validating a default value", NULL);
21593 return (-1);
21594 }
21595 }
21596 /*
21597 * cvc-elt (3.3.4) : 5.1.2
21598 * The element information item with the canonical lexical
21599 * representation of the {value constraint} value used as its
21600 * ·normalized value· must be ·valid· with respect to the
21601 * ·actual type definition· as defined by Element Locally Valid (Type)
21602 * (§3.3.4).
21603 */
21604 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021605 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021606 * done above.
21607 */
21608 if (ret == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021609 if (actualType != ELEM_TYPE(elemDecl))
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021610 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021611 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021612 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021613 ctxt->node = elem;
21614 if (ret < 0) {
21615 xmlSchemaVCustomErr(ctxt,
21616 XML_SCHEMAV_INTERNAL,
21617 elem, actualType,
21618 "Internal error: xmlSchemaValidateElementByDeclaration, "
21619 "validating against the type", NULL);
21620 return (-1);
21621 }
21622 /*
21623 * PSVI: Create a text node on the instance element.
21624 */
21625 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
21626 xmlNodePtr textChild;
21627
21628 textChild = xmlNewText(elemDecl->value);
21629 if (textChild == NULL) {
21630 xmlSchemaVCustomErr(ctxt,
21631 XML_SCHEMAV_INTERNAL,
21632 elem, actualType,
21633 "Internal error: xmlSchemaValidateElementByDeclaration, "
21634 "could not create a default text node for the instance",
21635 NULL);
21636 } else
21637 xmlAddChild(elem, textChild);
21638 }
21639 }
21640
21641 } else {
21642 /*
21643 * 5.2.1 The element information item must be ·valid· with respect
21644 * to the ·actual type definition· as defined by Element Locally
21645 * Valid (Type) (§3.3.4).
21646 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021647 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
21648 /*
21649 * Consume the computed value for IDCs, ect. Note that default
21650 * values are not supported yet.
21651 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021652 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021653 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021654 ctxt->value = NULL;
21655 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021656 ctxt->node = elem;
21657 if (ret < 0) {
21658 xmlSchemaVCustomErr(ctxt,
21659 XML_SCHEMAV_INTERNAL,
21660 elem, actualType,
21661 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021662 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021663 return (-1);
21664 }
21665 /*
21666 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
21667 * not applied, all of the following must be true:
21668 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021669 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
21670 /*
21671 * 5.2.2.1 The element information item must have no element
21672 * information item [children].
21673 *
21674 * TODO REDUNDANT: If the actual type exists, the above call to
21675 * xmlSchemaValidateElementByType will already check for element
21676 * nodes.
21677 */
21678 if (xmlSchemaHasElemContent(elem)) {
21679 xmlSchemaVCustomErr(ctxt,
21680 XML_SCHEMAV_CVC_ELT_5_2_2_1,
21681 elem, (xmlSchemaTypePtr) elemDecl,
21682 "Elements in the content are not allowed if it is "
21683 "constrained by a fixed value", NULL);
21684 } else {
21685 /*
21686 * 5.2.2.2 The appropriate case among the following must
21687 * be true:
21688 */
21689
21690 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
21691 xmlChar *value;
21692 /*
21693 * 5.2.2.2.1 If the {content type} of the ·actual type
21694 * definition· is mixed, then the *initial value* of the
21695 * item must match the canonical lexical representation
21696 * of the {value constraint} value.
21697 *
21698 * ... the *initial value* of an element information
21699 * item is the string composed of, in order, the
21700 * [character code] of each character information item in
21701 * the [children] of that element information item.
21702 */
21703 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21704 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21705 /*
21706 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021707 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021708 */
21709 xmlSchemaVCustomErr(ctxt,
21710 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
21711 elem, (xmlSchemaTypePtr) elemDecl,
21712 "The value does not match the cononical "
21713 "lexical representation of the fixed constraint",
21714 NULL);
21715 }
21716 if (value != NULL)
21717 xmlFree(value);
21718 } else if ((actualType->contentType ==
21719 XML_SCHEMA_CONTENT_SIMPLE) ||
21720 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
21721 xmlChar *value;
21722
21723 /*
21724 * 5.2.2.2.2 If the {content type} of the ·actual type
21725 * definition· is a simple type definition, then the
21726 * *actual value* of the item must match the canonical
21727 * lexical representation of the {value constraint} value.
21728 */
21729 /*
21730 * TODO: *actual value* is the normalized value, impl. this.
21731 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021732 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021733 *
21734 */
21735 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21736 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21737 xmlSchemaVCustomErr(ctxt,
21738 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
21739 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021740 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021741 "lexical representation of the fixed constraint",
21742 NULL);
21743 }
21744 if (value != NULL)
21745 xmlFree(value);
21746
21747 }
21748 /*
21749 * TODO: What if the content type is not 'mixed' or simple?
21750 */
21751
21752 }
21753
21754 }
21755 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021756 /*
21757 * TODO: 7 If the element information item is the ·validation root·, it must be
21758 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
21759 */
21760
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021761 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021762}
21763
Daniel Veillard4255d502002-04-16 15:50:10 +000021764/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021765 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021766 * @ctxt: a schema validation context
21767 * @node: the top node.
21768 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021769 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
21770 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021771 *
21772 * Returns 0 if the element is valid, a positive error code
21773 * number otherwise and -1 in case of an internal error.
21774 */
21775static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021776xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
21777 xmlSchemaWildcardPtr wild,
21778 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021779{
21780 const xmlChar *uri;
21781 int ret = 0;
21782 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021783
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021784 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021785 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
21786 if (ret == -1) {
21787 xmlSchemaVCustomErr(ctxt,
21788 XML_SCHEMAV_INTERNAL,
21789 ctxt->node, NULL,
21790 "Internal error: xmlSchemaValidateElement, "
21791 "assembling schema by xsi", NULL);
21792 return (-1);
21793 }
21794 /*
21795 * NOTE: We won't react on schema parser errors here.
21796 * TODO: But a warning would be nice.
21797 */
21798 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021799 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
21800 xmlSchemaElementPtr decl = NULL;
21801
21802 if (node->ns != NULL)
21803 decl = xmlHashLookup3(ctxt->schema->elemDecl,
21804 node->name, node->ns->href, NULL);
21805 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021806 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
21807 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021808 if (decl != NULL) {
21809 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021810 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021811 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021812 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021813 "Internal error: xmlSchemaValidateAnyInternal, "
21814 "validating an element in the context of a wildcard.",
21815 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000021816 }
21817 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021818 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21819 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021820 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021821 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021822 /*
21823 * Evaluate IDCs even if a validation error occured.
21824 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021825 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021826 return(-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021827
Daniel Veillardc0826a72004-08-10 14:17:33 +000021828 return (ctxt->err);
21829 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021830 /*
21831 * Evaluate IDCs; we need to know if an IDC field resolves to
21832 * such a node. This node has no type definition and will
21833 * definitely result in an IDC validation error if an IDC field
21834 * resolves.
21835 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021836 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021837 return(-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021838 }
21839 if (node->children != NULL) {
21840 child = node->children;
21841 do {
21842 if (child->type == XML_ELEMENT_NODE) {
21843 if (child->ns != NULL)
21844 uri = child->ns->href;
21845 else
21846 uri = NULL;
21847 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021848 /* TODO: error code. */
21849 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021850 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021851 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000021852 return (ctxt->err);
21853 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021854
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021855 ctxt->node = child;
21856 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021857
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021858 /*
21859 * Recurse over the children.
21860 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021861 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
21862 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021863 if (ret == -1)
21864 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021865
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021866 if (xmlSchemaEndElement(ctxt) == -1)
21867 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021868
Daniel Veillardc0826a72004-08-10 14:17:33 +000021869 if (ret != 0)
21870 return (ret);
21871 }
21872 child = child->next;
21873 } while (child != NULL);
21874 }
21875 return (0);
21876}
21877
21878/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021879 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021880 * @ctxt: a schema validation context
21881 *
21882 * Returns 0 if the element is valid, a positive error code
21883 * number otherwise and -1 in case of an internal or API error.
21884 */
21885static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021886xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021887 xmlSchemaWildcardPtr wild)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021888{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021889
21890 if ((wild == NULL) || (wild->type != XML_SCHEMA_TYPE_ANY) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021891 (ctxt->node == NULL)) {
21892 xmlSchemaVCustomErr(ctxt,
21893 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
21894 "Internal error: xmlSchemaValidateElementByWildcard, "
21895 "bad arguments", NULL);
21896 return (-1);
21897 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021898 if (wild->negNsSet != NULL) {
21899 /*
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000021900 * Don't process rejected namespaces.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021901 */
21902 if (ctxt->node->ns != NULL) {
21903 if (xmlSchemaMatchesWildcardNs(wild, ctxt->node->ns->href) == 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000021904 /* ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021905 return (XML_SCHEMAV_ELEMENT_CONTENT);
21906 }
21907 } else if (xmlSchemaMatchesWildcardNs(wild, NULL) == 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000021908 /* ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021909 return (XML_SCHEMAV_ELEMENT_CONTENT);
21910 }
21911 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021912 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021913 wild, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000021914}
21915
21916/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021917 * xmlSchemaValidateElementByAnyType:
William M. Brack2f2a6632004-08-20 23:09:47 +000021918 * @ctxt: a schema validation context
21919 * @node: the current element
21920 *
21921 * This one validates the content of an element of the type
21922 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
21923 * thus elements in the subtree will be validated, if a corresponding
21924 * declaration in the schema exists.
21925 *
21926 * Returns 0 if the element and its subtree is valid, a positive error code
21927 * otherwise and -1 in case of an internal or API error.
21928 */
21929static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021930xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
21931 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000021932{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021933 xmlSchemaTypePtr oldtype;
21934 xmlNodePtr top, cur;
21935 xmlSchemaElementPtr decl;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021936 int skipContent, ret, insub = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021937
21938 if ((type == NULL) || (ctxt->node == NULL))
21939 return (-1);
21940
21941 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021942 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021943
21944 oldtype = ctxt->type;
21945 top = ctxt->node;
21946 /*
21947 * STREAM: Child nodes are processed.
21948 */
21949 cur = ctxt->node->children;
21950 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021951 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021952 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021953 /*
21954 * The process contents of the wildcard is "lax", thus
21955 * we need to validate the element if a declaration
21956 * exists.
21957 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021958 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021959 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021960 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000021961 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021962 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
21963 ctxt->node = cur;
21964
21965 if (insub) {
21966 /*
21967 * BEGIN element.
21968 */
21969 xmlSchemaBeginElement(ctxt);
21970 } else
21971 insub = 1;
21972
21973 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021974 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
21975 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000021976 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021977 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000021978 "Internal error: xmlSchemaValidateAnyTypeContent, "
21979 "validating an element in the context of a wildcard.",
21980 NULL, NULL);
21981 return (ret);
21982 } else if (ret > 0)
21983 return (ret);
21984 skipContent = 1;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021985 } else {
21986 /*
21987 * IDCs.
21988 */
21989 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
21990 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000021991 }
21992 }
21993 /*
21994 * Browse the full subtree, deep first.
21995 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021996 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021997 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021998 cur = cur->children;
21999 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000022000 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022001 cur = cur->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022002 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000022003 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022004 while (cur != top) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022005 if (cur->type == XML_ELEMENT_NODE) {
22006 /*
22007 * END element.
22008 */
22009 xmlSchemaEndElement(ctxt);
22010 }
22011 if (cur->parent != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022012 cur = cur->parent;
22013 if ((cur != top) && (cur->next != NULL)) {
22014 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000022015 break;
22016 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022017 if (cur->parent == NULL) {
22018 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000022019 break;
22020 }
22021 }
22022 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022023 if (cur == top)
22024 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000022025 } else
22026 break;
22027 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022028 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000022029 return (0);
22030}
22031
22032/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022033 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000022034 * @ctxt: a schema validation context
22035 * @node: the top node.
22036 *
22037 * Validate the content of an element expected to be a complex type type
22038 * xmlschema-1.html#cvc-complex-type
22039 * Validation Rule: Element Locally Valid (Complex Type)
22040 *
22041 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000022042 * number otherwise and -1 in case of internal or API error.
22043 * Note on reported errors: Although it might be nice to report
22044 * the name of the simple/complex type, used to validate the content
22045 * of a node, it is quite unnecessary: for global defined types
22046 * the local name of the element is equal to the NCName of the type,
22047 * for local defined types it makes no sense to output the internal
22048 * computed name of the type. TODO: Instead, one should attach the
22049 * struct of the type involved to the error handler - this allows
22050 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000022051 */
22052static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022053xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022054 xmlSchemaTypePtr type,
22055 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022056{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022057 xmlSchemaTypePtr oldtype;
22058 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022059 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000022060 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022061 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000022062
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022063 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
22064 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022065
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022066 oldtype = ctxt->type;
22067 ctxt->type = type;
22068 elem = ctxt->node;
22069
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022070 /*
22071 * Verify the attributes
22072 */
22073 /*
22074 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022075 */
22076 /* NOTE: removed, since a check for abstract is
22077 * done in the cvc-type constraint.
22078 *
22079 *
22080 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22081 * xmlSchemaVComplexTypeErr(ctxt,
22082 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
22083 * elem, type,
22084 * "The type definition is abstract");
22085 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
22086 *}
22087 */
22088
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022089 attrs = ctxt->attr;
22090 attrTop = ctxt->attrTop;
22091 /*
22092 * STREAM: Attribute nodes are processed.
22093 */
22094 xmlSchemaRegisterAttributes(ctxt, elem->properties);
22095 xmlSchemaValidateAttributes(ctxt, elem, type);
22096 if (ctxt->attr != NULL)
22097 xmlSchemaFreeAttributeStates(ctxt->attr);
22098 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022099 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022100
22101 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022102 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022103 * model was defined. Somehow ->contModel is always not NULL
22104 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022105 * TODO: Check if the obove still occurs.
22106 */
Daniel Veillard4255d502002-04-16 15:50:10 +000022107 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000022108 case XML_SCHEMA_CONTENT_EMPTY: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022109 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022110 * 1 If the {content type} is empty, then the element information
22111 * item has no character or element information item [children].
22112 */
22113 /*
22114 * TODO: Is the entity stuff correct?
22115 */
22116 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
22117 xmlSchemaVComplexTypeErr(ctxt,
22118 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
22119 elem, type,
22120 "Character or element content is not allowed, "
22121 "because the content type is empty");
22122 }
22123 break;
22124 }
22125 case XML_SCHEMA_CONTENT_MIXED:
22126 /*
22127 * Some speedups for anyType or types derived directly from it.
22128 */
22129 if (IS_ANYTYPE(type)) {
22130 /*
22131 * Corresponds to <element name="foo" [type="xsd:anyType"]/>.
22132 */
22133 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
22134 /* TODO: Handle -1. */
22135 break;
22136 }
22137 if (IS_ANYTYPE(type->baseType) &&
22138 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
22139 (type->subtypes == type->baseType->subtypes)) {
22140 /*
22141 * Corresponds to an <extension> of anyType.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022142 */
22143 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
22144 /* TODO: Handle -1. */
22145 break;
22146 }
22147 /* No break on purpose. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022148 case XML_SCHEMA_CONTENT_ELEMENTS: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022149 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022150 xmlChar *values[10];
22151 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022152 /*
22153 * SPEC (2.4) If the {content type} is element-only or mixed,
22154 * then the sequence of the element information item's
22155 * element information item [children], if any, taken in
22156 * order, is ·valid· with respect to the {content type}'s
22157 * particle, as defined in Element Sequence Locally Valid
22158 * (Particle) (§3.9.4).
22159 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022160 /*
22161 * Content model check initialization.
22162 */
22163 if (type->contModel != NULL) {
22164 oldregexp = ctxt->regexp;
22165 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
22166 (xmlRegExecCallbacks)
22167 xmlSchemaValidateCallback, ctxt);
22168#ifdef DEBUG_AUTOMATA
22169 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
22170#endif
22171 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022172 /*
22173 * STREAM: Children are processed.
22174 */
22175 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022176 while (child != NULL) {
22177 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000022178 if (child->ns != NULL)
22179 nsUri = child->ns->href;
22180 else
22181 nsUri = NULL;
22182 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022183 child->name, nsUri, child);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022184 if (ctxt->err == XML_SCHEMAV_INTERNAL) {
22185 xmlRegFreeExecCtxt(ctxt->regexp);
22186 ctxt->regexp = oldregexp;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022187 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022188 }
22189#if 0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022190 if (ctxt->flags & XML_SCHEMA_VALID_INVALID_NEG_WILDCARD) {
22191 ctxt->flags ^= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
22192 ret = -1;
22193 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022194#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022195 /*
22196 * URGENT TODO: Could we anchor an error report
22197 * here to notify of invalid elements?
22198 * TODO: Perhaps it would be better to report
22199 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022200 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022201#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000022202 if (ret < 0)
22203 xmlGenericError(xmlGenericErrorContext,
22204 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000022205 else
22206 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000022207 " --> %s\n", child->name);
22208#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022209 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022210 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
22211 &values[0], &terminal);
22212 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022213 XML_SCHEMAV_ELEMENT_CONTENT,
22214 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022215 "This element is not expected",
22216 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022217 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022218 /*
22219 * Note that this will skip further validation of the
22220 * content.
22221 */
22222 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022223 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000022224 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
22225 /*
22226 * TODO: Ask Daniel if this are all character nodes.
22227 */
22228 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
22229 (child->type == XML_ENTITY_NODE) ||
22230 (child->type == XML_ENTITY_REF_NODE) ||
22231 (child->type == XML_CDATA_SECTION_NODE))) {
22232 /*
22233 * 2.3 If the {content type} is element-only, then the
22234 * element information item has no character information
22235 * item [children] other than those whose [character
22236 * code] is defined as a white space in [XML 1.0 (Second
22237 * Edition)].
22238 */
William M. Brack2f2a6632004-08-20 23:09:47 +000022239 xmlSchemaVComplexTypeErr(ctxt,
22240 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022241 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000022242 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022243 "because the content type is element-only");
22244 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022245 break;
22246 }
22247 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022248 }
22249 /*
22250 * Content model check finalization.
22251 */
22252 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022253 if (ret == 0) {
22254 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022255 &values[0], &terminal);
Daniel Veillard0e460da2005-03-30 22:47:10 +000022256 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022257 * If a next value still exists, It does not have to
Daniel Veillard0e460da2005-03-30 22:47:10 +000022258 * mean that there's an element missing, since it
22259 * might be an optional element. So double check it.
22260 */
22261 ret = xmlRegExecPushString(ctxt->regexp,
22262 NULL, NULL);
22263 if (ret <= 0) {
22264 ret = 1;
22265 xmlSchemaVComplexTypeElemErr(ctxt,
22266 XML_SCHEMAV_ELEMENT_CONTENT,
22267 elem, type, "Missing child element(s)",
22268 nbval, nbneg, values);
22269 } else
22270 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022271#ifdef DEBUG_AUTOMATA
Daniel Veillard0e460da2005-03-30 22:47:10 +000022272 xmlGenericError(xmlGenericErrorContext,
22273 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022274#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022275#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022276 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022277 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022278 "Element %s content check succeeded\n",
22279 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022280#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022281 }
22282 xmlRegFreeExecCtxt(ctxt->regexp);
22283 ctxt->regexp = oldregexp;
22284 }
22285 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000022286 break;
22287 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022288 case XML_SCHEMA_CONTENT_BASIC:
22289 /*
22290 * If the simple content was already validated
22291 * (e.g. a default value), the content need not
22292 * to be validated again.
22293 */
22294 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000022295 xmlChar *value = NULL;
22296 /*
22297 * We hit a complexType with a simpleContent resolving
22298 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000022299 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000022300 /*
22301 * 2.2 If the {content type} is a simple type definition,
22302 * then the element information item has no element
22303 * information item [children], and the ·normalized value·
22304 * of the element information item is ·valid· with respect
22305 * to that simple type definition as defined by String
22306 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022307 */
22308 /*
22309 * STREAM: Children are processed.
22310 */
22311 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022312 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022313 /*
22314 * TODO: Could the entity stuff produce elements
22315 * as well?
22316 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000022317 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000022318 xmlSchemaVComplexTypeErr(ctxt,
22319 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022320 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000022321 "Element content is not allowed, because "
22322 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000022323 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22324 break;
22325 }
22326 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022327 }
22328 ctxt->node = elem;
22329 ctxt->cur = elem->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022330 if (ret != 0) {
22331 FREE_AND_NULL(value)
22332 break;
22333 }
22334 /*
22335 * Validate the character content against a simple type.
22336 */
22337 if (elem->children == NULL)
22338 value = NULL;
22339 else
22340 value = xmlNodeGetContent(elem);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022341 /*
22342 * NOTE: This call won't check the correct types of the
22343 * content nodes, since this should be done here.
22344 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022345 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
22346 type->contentTypeDef, value, 1, 1, 1, 0);
22347 if (ret > 0) {
22348 /*
22349 * NOTE: Although an error will be reported by
22350 * xmlSchemaValidateSimpleTypeValue, the spec wants
22351 * a specific complex type error to be reported
22352 * additionally.
22353 */
22354 xmlSchemaVComplexTypeErr(ctxt,
22355 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
22356 elem, type,
22357 "The character content is not valid");
22358 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22359 } else if (ret < 0) {
22360 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
22361 "Internal error: xmlSchemaValidateComplexType, "
22362 "Element '%s': Error while validating character "
22363 "content against complex type '%s'.\n",
22364 elem->name, type->name);
22365 if (value != NULL)
22366 xmlFree(value);
22367 ctxt->type = oldtype;
22368 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022369 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000022370 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022371 xmlFree(value);
22372
Daniel Veillard01fa6152004-06-29 17:04:39 +000022373 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022374 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022375 default:
22376 TODO xmlGenericError(xmlGenericErrorContext,
22377 "unimplemented content type %d\n",
22378 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000022379 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022380 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022381 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000022382}
22383
22384/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022385 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000022386 * @ctxt: a schema validation context
22387 * @elem: an element
22388 * @type: the list of type declarations
22389 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022390 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000022391 *
22392 * Returns 0 if the element is schemas valid, a positive error code
22393 * number otherwise and -1 in case of internal or API error.
22394 */
22395static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022396xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022397 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022398 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022399 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022400{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022401 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000022402
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022403
22404 if ((ctxt == NULL) || (type == NULL)) {
22405 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
22406 "Internal error: xmlSchemaValidateElementByType, "
22407 "bad arguments", NULL);
22408 return (-1);
22409 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022410 /*
22411 * This one is called by "xmlSchemaValidateElementByDeclaration".
22412 * It will forward to the proper validation
22413 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022414 */
22415 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022416 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022417 XML_SCHEMAV_CVC_TYPE_1,
22418 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022419 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022420 return (XML_SCHEMAV_CVC_TYPE_1);
22421 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022422
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022423 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022424 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022425 XML_SCHEMAV_CVC_TYPE_2,
22426 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000022427 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022428 return (XML_SCHEMAV_CVC_TYPE_2);
22429 }
22430
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022431 switch (type->type) {
22432 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022433 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
22434 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022435 break;
22436 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022437 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022438 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022439 break;
22440 case XML_SCHEMA_TYPE_BASIC:
22441 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
22442 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
22443 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022444 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022445 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022446 break;
22447 default:
22448 ret = -1;
22449 break;
22450 }
22451 if (ret == -1)
22452 return (-1);
22453 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022454 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022455}
22456
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022457static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022458xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022459 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022460 const xmlChar *value,
22461 xmlSchemaValPtr *val)
22462{
22463 xmlSchemaTypePtr prim;
22464
22465 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022466 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022467 XML_SCHEMAV_INTERNAL,
22468 "Internal error: xmlSchemaPostCreateVal, "
22469 "bad arguments", NULL, NULL);
22470 return (-1);
22471 }
22472 /*
22473 * Only string or anySimpleType values are expected to be post-created.
22474 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022475 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022476 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
22477 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
22478 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022479 if (value == NULL)
22480 /* TODO: Can this happen at all? */
22481 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
22482 xmlStrdup(BAD_CAST ""));
22483 else
22484 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
22485 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022486 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022487 XML_SCHEMAV_INTERNAL,
22488 "Internal error: xmlSchemaPostCreateVal, "
22489 "failed to create the value", NULL, NULL);
22490 return (-1);
22491 }
22492 return (0);
22493 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022494 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022495 XML_SCHEMAV_INTERNAL,
22496 "Internal error: xmlSchemaPostCreateVal, "
22497 "the given type is not supported", NULL, NULL);
22498 return (-1);
22499}
22500
22501static int
22502xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022503 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022504{
22505 xmlChar *value;
22506 const xmlChar *defValue;
22507 xmlSchemaValPtr defVal;
22508 int fixed;
22509 int ret;
22510
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022511 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022512 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
22513 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
22514 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022515 vctxt->node = vctxt->attrInfo->node;
22516 vctxt->cur = vctxt->node->children;
22517 /* STREAM */
22518 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022519
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022520 /*
22521 * NOTE: This call also checks the content nodes for correct type.
22522 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022523 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022524 value, 1, 1, 1, 1);
22525
22526 /*
22527 * Handle 'fixed' attributes.
22528 */
22529 if (ret > 0) {
22530 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
22531 /*
22532 * NOTE: Fixed value constraints will be not
22533 * applied if the value was invalid, because:
22534 * 1. The validation process does not return a precomputed
22535 * value.
22536 * 2. An invalid value implies a violation of a fixed
22537 * value constraint.
22538 */
22539 } else if (ret == 0) {
22540 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022541 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022542 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022543 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022544
22545 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022546 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022547 /*
22548 * cvc-au : Attribute Locally Valid (Use)
22549 * For an attribute information item to be·valid·
22550 * with respect to an attribute use its ·normalized
22551 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022552 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022553 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022554 *
22555 * TODO: Use somehow the *normalized* value and the *canonical*
22556 * fixed value. This here compares the canonical values of both.
22557 * The normalized value of, for example, a float type can differ
22558 * from its canonical representation. This all means that a fixed
22559 * value can only be OK, if it's present in the canonical form in
22560 * the instance.
22561 * NOTE: Since the value for string and anySimpleType is not always
22562 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022563 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022564 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022565 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022566 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022567 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022568 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
22569 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022570 ret = -1;
22571 goto exit;
22572 }
22573 value = NULL;
22574 }
22575 if (defVal == NULL) {
22576 xmlChar *str;
22577
22578 /*
22579 * Post-create the default/fixed value.
22580 */
22581 if (defValue == NULL)
22582 str = xmlStrdup(BAD_CAST "");
22583 else
22584 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022585 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
22586 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022587 ret = -1;
22588 FREE_AND_NULL(str)
22589 goto exit;
22590 }
22591 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
22592 }
22593 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
22594 (xmlSchemaWhitespaceValueType) ws,
22595 defVal,
22596 (xmlSchemaWhitespaceValueType) ws) != 0)
22597 {
22598 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022599 }
22600 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022601 }
22602exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022603 if (value != NULL) {
22604 xmlFree(value);
22605 }
22606 return (ret);
22607}
22608
Daniel Veillard4255d502002-04-16 15:50:10 +000022609/**
22610 * xmlSchemaValidateAttributes:
22611 * @ctxt: a schema validation context
22612 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000022613 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000022614 *
22615 * Validate the attributes of an element.
22616 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000022617 * 1. Existent, invalid attributes are reported in the form
22618 * "prefix:localName".
22619 * Reason: readability - it is easier to find the actual XML
22620 * representation of the attributes QName.
22621 * 2. Missing attributes are reported in the form
22622 * {"URI", "localName"}.
22623 * This is necessary, since the the prefix need not to be declared
22624 * at all, and thus is not computable.
22625 *
Daniel Veillard4255d502002-04-16 15:50:10 +000022626 * Returns 0 if the element is schemas valid, a positive error code
22627 * number otherwise and -1 in case of internal or API error.
22628 */
22629static int
Daniel Veillard3646d642004-06-02 19:19:14 +000022630xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022631{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022632 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000022633 int ret;
22634 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022635 const xmlChar *defValue;
22636 xmlSchemaValPtr defVal;
22637 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022638 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000022639 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000022640 int found;
William M. Brack803812b2004-06-03 02:11:24 +000022641 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022642 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022643 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000022644#ifdef DEBUG_ATTR_VALIDATION
22645 int redundant = 0;
22646#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000022647
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022648
Daniel Veillardc0826a72004-08-10 14:17:33 +000022649 /*
22650 * Allow all attributes if the type is anyType.
22651 */
22652 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
22653 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022654
22655 oldnode = ctxt->node;
22656 if (type != NULL)
22657 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000022658 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000022659 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022660 attrDecl = attrUse->attr;
22661#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022662 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000022663 printf("attr use - use: %d\n", attrDecl->occurs);
22664#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022665 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022666
22667 if (curState->decl == attrUse->attr) {
22668#ifdef DEBUG_ATTR_VALIDATION
22669 redundant = 1;
22670#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022671 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022672 attr = curState->attr;
22673#ifdef DEBUG_ATTR_VALIDATION
22674 printf("attr - name: %s\n", attr->name);
22675 if (attr->ns != NULL)
22676 printf("attr - ns: %s\n", attr->ns->href);
22677 else
22678 printf("attr - ns: none\n");
22679#endif
22680 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022681 if (attr == NULL)
22682 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022683 if (attrDecl->ref != NULL) {
22684 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022685 continue;
22686 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022687 if ((attrDecl->refNs == NULL) ||
22688 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022689 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022690 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022691 continue;
22692 }
22693 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000022694 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022695 continue;
22696 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022697 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022698 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022699 if (attr->ns == NULL) {
22700 /*
William M. Bracke7091952004-05-11 15:09:58 +000022701 * accept an unqualified attribute only if the target
22702 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022703 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022704 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000022705 /*
22706 * This check was removed, since the target namespace
22707 * was evaluated during parsing and already took
22708 * "attributeFormDefault" into account.
22709 */
22710 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022711 continue;
22712 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000022713 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022714 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022715 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022716 attr->ns->href))
22717 continue;
22718 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022719 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022720#ifdef DEBUG_ATTR_VALIDATION
22721 printf("found\n");
22722#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022723 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000022724 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022725 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22726 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022727 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022728 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022729 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022730 if (!found) {
22731 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
22732 xmlSchemaAttrStatePtr tmp;
22733
Daniel Veillard3646d642004-06-02 19:19:14 +000022734#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022735 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022736#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022737 /*
22738 * Add a new dummy attribute state.
22739 */
22740 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
22741 if (tmp == NULL) {
22742 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
22743 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022744 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022745 }
22746 tmp->attr = NULL;
22747 tmp->state = XML_SCHEMAS_ATTR_MISSING;
22748 tmp->decl = attrDecl;
22749 tmp->next = NULL;
22750
22751 if (reqAttrStates == NULL) {
22752 reqAttrStates = tmp;
22753 reqAttrStatesTop = tmp;
22754 } else {
22755 reqAttrStatesTop->next = tmp;
22756 reqAttrStatesTop = tmp;
22757 }
22758 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
22759 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
22760 &fixed, &defValue, &defVal))) {
22761 xmlSchemaAttrStatePtr tmp;
22762 /*
22763 * Handle non existent default/fixed attributes.
22764 */
22765 tmp = (xmlSchemaAttrStatePtr)
22766 xmlMalloc(sizeof(xmlSchemaAttrState));
22767 if (tmp == NULL) {
22768 xmlSchemaVErrMemory(ctxt,
22769 "registering schema specified attributes", NULL);
22770 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022771 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022772 }
22773 tmp->attr = NULL;
22774 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
22775 tmp->decl = attrDecl;
22776 tmp->value = defValue;
22777 tmp->next = NULL;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022778 if (defAttrStatesTop == NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022779 defAttrStates = tmp;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022780 else
22781 defAttrStatesTop->next = tmp;
22782 defAttrStatesTop = tmp;
22783 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022784 }
22785 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000022786 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022787 /*
22788 * Add required attributes to the attribute states of the context.
22789 */
22790 if (reqAttrStates != NULL) {
22791 if (ctxt->attr == NULL) {
22792 ctxt->attr = reqAttrStates;
22793 } else {
22794 ctxt->attrTop->next = reqAttrStates;
22795 }
22796 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000022797 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022798 /*
22799 * Process wildcards.
22800 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022801
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022802 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022803#ifdef DEBUG_ATTR_VALIDATION
22804 xmlSchemaWildcardNsPtr ns;
22805 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022806 if (type->attributeWildcard->processContents ==
22807 XML_SCHEMAS_ANY_LAX)
22808 printf("processContents: lax\n");
22809 else if (type->attributeWildcard->processContents ==
22810 XML_SCHEMAS_ANY_STRICT)
22811 printf("processContents: strict\n");
22812 else
22813 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022814 if (type->attributeWildcard->any)
22815 printf("type: any\n");
22816 else if (type->attributeWildcard->negNsSet != NULL) {
22817 printf("type: negated\n");
22818 if (type->attributeWildcard->negNsSet->value == NULL)
22819 printf("ns: (absent)\n");
22820 else
22821 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
22822 } else if (type->attributeWildcard->nsSet != NULL) {
22823 printf("type: set\n");
22824 ns = type->attributeWildcard->nsSet;
22825 while (ns != NULL) {
22826 if (ns->value == NULL)
22827 printf("ns: (absent)\n");
22828 else
22829 printf("ns: %s\n", ns->value);
22830 ns = ns->next;
22831 }
22832 } else
22833 printf("empty\n");
22834
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022835
22836#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000022837 curState = ctxt->attr;
22838 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022839 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
22840 if (curState->attr->ns != NULL)
22841 nsURI = curState->attr->ns->href;
22842 else
22843 nsURI = NULL;
22844 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
22845 nsURI)) {
22846 /*
22847 * Handle processContents.
22848 */
22849 if ((type->attributeWildcard->processContents ==
22850 XML_SCHEMAS_ANY_LAX) ||
22851 (type->attributeWildcard->processContents ==
22852 XML_SCHEMAS_ANY_STRICT)) {
22853
22854 attr = curState->attr;
22855 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022856 attr->name, nsURI);
22857 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022858 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022859 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022860 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22861 /* TODO
22862 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
22863 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022864 } else if (type->attributeWildcard->processContents ==
22865 XML_SCHEMAS_ANY_LAX) {
22866 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022867 } else
22868 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022869 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000022870 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022871 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022872 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022873 curState = curState->next;
22874 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022875 }
22876
Daniel Veillardc0826a72004-08-10 14:17:33 +000022877 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022878 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022879
22880 /*
22881 * Validate the value of the attribute.
22882 */
22883 if (ctxt->value != NULL) {
22884 xmlSchemaFreeValue(ctxt->value);
22885 ctxt->value = NULL;
22886 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022887 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022888 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022889 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022890 switch (curState->state) {
22891 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022892
22893 /*
22894 * Create an attribute info if needed.
22895 */
22896 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022897 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22898 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022899 if (ctxt->attrInfo == NULL) {
22900 xmlSchemaVErrMemory(ctxt,
22901 "allocating an attribute info", NULL);
22902 goto fatal_exit;
22903 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000022904 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022905 }
22906 /*
22907 * Init the attribute info.
22908 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000022909 if (ctxt->attrInfo->value != NULL) {
22910 xmlSchemaFreeValue(ctxt->attrInfo->value);
22911 ctxt->attrInfo->value = NULL;
22912 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022913 ctxt->attrInfo->flags = 0;
22914 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
22915 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022916 if (curState->decl != NULL)
22917 ctxt->attrInfo->typeDef = curState->decl->subtypes;
22918 else
22919 ctxt->attrInfo->typeDef = NULL;
22920 if (curState->attr->ns != NULL)
22921 ctxt->attrInfo->namespaceName =
22922 curState->attr->ns->href;
22923 else
22924 ctxt->attrInfo->namespaceName = NULL;
22925 ctxt->attrInfo->localName = curState->attr->name;
22926
22927 ctxt->nodeInfo = ctxt->attrInfo;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022928 /*
22929 * Evaluate IDCs.
22930 */
22931 if (ctxt->xpathStates != NULL) {
22932 ret = xmlSchemaXPathEvaluate(ctxt,
22933 XML_ATTRIBUTE_NODE);
22934 if (ret == -1)
22935 goto fatal_exit;
22936 }
22937
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022938 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022939 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022940 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022941 if ((ret != 0) && (ctxt->value != NULL)) {
22942 xmlSchemaFreeValue(ctxt->value);
22943 ctxt->value = NULL;
22944 }
22945 /* No break on purpose. */
22946 case XML_SCHEMAS_ATTR_CHECKED:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022947 if (ctxt->xpathStates != NULL) {
22948 /*
22949 * Evaluate IDCs.
22950 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022951 if (ctxt->value != NULL) {
22952 ctxt->attrInfo->value = ctxt->value;
22953 ctxt->value = NULL;
22954 }
22955 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22956 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022957 }
22958 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022959 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022960 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022961 }
22962 curState = curState->next;
22963 }
22964
22965 /*
22966 * Report missing and illegal attributes.
22967 */
22968 curState = ctxt->attr;
22969 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000022970 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
22971 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022972 if (curState->decl != NULL) {
22973 if (curState->decl->ref != NULL)
22974 attrDecl = curState->decl->refDecl;
22975 else
22976 attrDecl = curState->decl;
22977 } else
22978 attrDecl = NULL;
22979 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
22980 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
22981 } else if (curState->state ==
22982 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
22983 xmlSchemaVCustomErr(ctxt,
22984 XML_SCHEMAV_CVC_ATTRIBUTE_2,
22985 (xmlNodePtr) attr,
22986 (xmlSchemaTypePtr) attrDecl,
22987 "The type definition is absent",
22988 NULL);
22989 } else if (curState->state ==
22990 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
22991 xmlSchemaVCustomErr(ctxt,
22992 XML_SCHEMAV_CVC_AU,
22993 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
22994 "The value does not match the fixed value "
22995 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022996 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
22997 xmlSchemaVWildcardErr(ctxt,
22998 XML_SCHEMAV_CVC_WILDCARD,
22999 (xmlNodePtr) attr,
23000 type->attributeWildcard,
23001 "No global attribute declaration found, but "
23002 "stipulated by the strict processContents of "
23003 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023004 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000023005 /* TODO: "prohibited" won't ever be touched here!.
23006 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
23007 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023008 /*
23009 * TODO: One might report different error messages
23010 * for the following errors.
23011 */
23012 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000023013 xmlSchemaVIllegalAttrErr(ctxt,
23014 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
23015 } else {
23016 xmlSchemaVIllegalAttrErr(ctxt,
23017 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
23018 }
23019 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000023020 }
23021 curState = curState->next;
23022 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023023 }
23024
23025 /*
23026 * Add missing default/fixed attributes.
23027 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023028 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023029 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023030
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023031 while (curState != NULL) {
23032 attrDecl = curState->decl;
23033 if (attrDecl->ref != NULL)
23034 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023035 /*
23036 * Evaluate IDCs on default attributes.
23037 */
23038 if (ctxt->xpathStates != NULL) {
23039 /*
23040 * Create an attribute info if needed.
23041 */
23042 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023043 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
23044 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023045 if (ctxt->attrInfo == NULL) {
23046 xmlSchemaVErrMemory(ctxt,
23047 "allocating an attribute info", NULL);
23048 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023049 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023050 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023051 }
23052 /*
23053 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000023054 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023055 */
23056 ctxt->attrInfo->flags = 0;
23057 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
23058 ctxt->attrInfo->node = NULL;
23059 ctxt->attrInfo->typeDef = attrDecl->subtypes;
23060 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
23061 ctxt->attrInfo->localName = attrDecl->name;
23062
23063 ctxt->nodeInfo = ctxt->attrInfo;
23064
23065 ret = xmlSchemaXPathEvaluate(ctxt,
23066 XML_ATTRIBUTE_NODE);
23067 if (ret == -1)
23068 goto fatal_exit;
23069 if (ctxt->attrInfo->value != NULL) {
23070 xmlSchemaFreeValue(ctxt->attrInfo->value);
23071 ctxt->attrInfo->value = NULL;
23072 }
23073 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000023074 /*
23075 * IDCs will consume the precomputed default value,
23076 * so we need to clone it somehow.
23077 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023078 /*
23079 * string or anySimpleType does not create a precomputed value
23080 * by default, so it will be created here on demand.
23081 * TODO: default/fixed attributes are a bit unoptimized:
23082 * the string value will be hold by ->defValue and inside
23083 * the precomputed value.
23084 */
23085 if (attrDecl->defVal == NULL) {
23086 xmlChar *str = xmlStrdup(attrDecl->defValue);
23087
23088 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000023089 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023090 str,
23091 &(attrDecl->defVal)) == -1) {
23092 FREE_AND_NULL(str)
23093 goto fatal_exit;
23094 }
23095 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023096 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
23097 /* TODO: error on NULL return. */
23098 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000023099
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023100 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
23101 goto fatal_exit;
23102 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023103
23104 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
23105 /*
23106 * PSVI: Add a new attribute node to the current element.
23107 */
23108 if (attrDecl->targetNamespace == NULL) {
23109 xmlNewProp(elem, attrDecl->name, curState->value);
23110 } else {
23111 xmlNsPtr ns;
23112
23113 ns = xmlSearchNsByHref(elem->doc, elem,
23114 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023115 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000023116 xmlChar prefix[12];
23117 int counter = 1;
23118
23119 attr = curState->attr;
23120 /*
23121 * Create a namespace declaration on the validation
23122 * root node if no namespace declaration is in scope.
23123 */
23124 snprintf((char *) prefix, sizeof(prefix), "p");
23125 /*
23126 * This is somehow not performant, since the ancestor
23127 * axis beyond @elem will be searched as well.
23128 */
23129 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
23130 while (ns != NULL) {
23131 if (counter > 1000) {
23132 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
23133 XML_SCHEMAV_INTERNAL,
23134 "Internal error: xmlSchemaValidateAttributes, "
23135 "could not compute a ns prefix for "
23136 "default/fixed attribute '%s'.\n",
23137 attrDecl->name, NULL);
23138
23139 break;
23140 }
23141 snprintf((char *) prefix,
23142 sizeof(prefix), "p%d", counter++);
23143 ns = xmlSearchNs(elem->doc, elem,
23144 BAD_CAST prefix);
23145 }
23146 if (ns == NULL) {
23147 ns = xmlNewNs(ctxt->validationRoot,
23148 attrDecl->targetNamespace, BAD_CAST prefix);
23149 xmlNewNsProp(elem, ns, attrDecl->name,
23150 curState->value);
23151 }
23152 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023153 xmlNewNsProp(elem, ns, attrDecl->name,
23154 curState->value);
23155 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023156 }
23157 }
23158 curState = curState->next;
23159 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000023160 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023161 ret = ctxt->err;
23162 goto exit;
23163
23164fatal_exit:
23165 ret = -1;
23166
23167exit:
23168
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023169 if (defAttrStates != NULL)
23170 xmlSchemaFreeAttributeStates(defAttrStates);
23171
Daniel Veillard3646d642004-06-02 19:19:14 +000023172#ifdef DEBUG_ATTR_VALIDATION
23173 if (redundant)
23174 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023175 "xmlSchemaValidateAttributes: redundant call by "
23176 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000023177#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023178 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023179 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023180 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000023181}
23182
23183/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023184 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000023185 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000023186 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023187 * The starting point of the validation, called by
23188 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000023189 *
23190 * Returns 0 if the element is schemas valid, a positive error code
23191 * number otherwise and -1 in case of internal or API error.
23192 */
23193static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023194xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023195{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023196 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023197 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000023198
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023199 ctxt->err = 0;
23200 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023201 if (ctxt->schema == NULL) {
23202 /*
23203 * No schema was specified at time of creation of the validation
23204 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
23205 * of the instance to build a schema.
23206 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023207 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023208 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
23209 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023210 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
23211 if (ctxt->schema == NULL)
23212 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023213 ctxt->xsiAssemble = 1;
23214 } else
23215 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023216 /*
23217 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000023218 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023219 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023220 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
23221 if (ret == -1) {
23222 xmlSchemaVCustomErr(ctxt,
23223 XML_SCHEMAV_INTERNAL,
23224 ctxt->node, NULL,
23225 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023226 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023227 }
23228 /*
23229 * NOTE: We won't react on schema parser errors here.
23230 * TODO: But a warning would be nice.
23231 */
23232 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023233 if (ret != -1) {
23234 if (ctxt->node->ns != NULL)
23235 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
23236 ctxt->node->ns->href);
23237 else
23238 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
23239
23240 if (elemDecl == NULL) {
23241 xmlSchemaVCustomErr(ctxt,
23242 XML_SCHEMAV_CVC_ELT_1,
23243 ctxt->node, NULL,
23244 "No matching global declaration available", NULL);
23245 ret = XML_SCHEMAV_CVC_ELT_1;
23246 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023247 /*
23248 * Augment the IDC definitions.
23249 */
23250 if (ctxt->schema->idcDef != NULL) {
23251 xmlHashScan(ctxt->schema->idcDef,
23252 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
23253 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023254 ctxt->depth = -1;
23255 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023256 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023257 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023258 if (ret < 0) {
23259 xmlSchemaVCustomErr(ctxt,
23260 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
23261 "Internal error: xmlSchemaValidateElement, "
23262 "calling validation by declaration", NULL);
23263 }
23264 }
23265 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023266
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023267 if (ctxt->xsiAssemble) {
23268 if (ctxt->schema != NULL) {
23269 xmlSchemaFree(ctxt->schema);
23270 ctxt->schema = NULL;
23271 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023272 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023273 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023274 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000023275}
23276
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023277
Daniel Veillard4255d502002-04-16 15:50:10 +000023278/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023279 * xmlSchemaValidateOneElement:
23280 * @ctxt: a schema validation context
23281 * @elem: an element node
23282 *
23283 * Validate a branch of a tree, starting with the given @elem.
23284 *
23285 * Returns 0 if the element and its subtree is valid, a positive error
23286 * code number otherwise and -1 in case of an internal or API error.
23287 */
23288int
23289xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23290{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023291 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023292 return (-1);
23293
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023294 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023295 xmlSchemaVErr(ctxt, NULL,
23296 XML_SCHEMAV_INTERNAL,
23297 "API error: xmlSchemaValidateOneElement, "
23298 "no schema specified.\n", NULL, NULL);
23299 return (-1);
23300 }
23301
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023302 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023303 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023304 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023305 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023306}
23307
23308/************************************************************************
23309 * *
23310 * SAX Validation code *
23311 * *
23312 ************************************************************************/
23313
23314/************************************************************************
23315 * *
23316 * Validation interfaces *
23317 * *
23318 ************************************************************************/
23319
23320/**
23321 * xmlSchemaNewValidCtxt:
23322 * @schema: a precompiled XML Schemas
23323 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023324 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023325 *
23326 * Returns the validation context or NULL in case of error
23327 */
23328xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023329xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23330{
Daniel Veillard4255d502002-04-16 15:50:10 +000023331 xmlSchemaValidCtxtPtr ret;
23332
23333 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23334 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023335 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023336 return (NULL);
23337 }
23338 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000023339 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023340 return (ret);
23341}
23342
23343/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023344 * xmlSchemaClearValidCtxt:
23345 * @ctxt: the schema validation context
23346 *
23347 * Free the resources associated to the schema validation context;
23348 * leaves some fields alive intended for reuse of the context.
23349 */
23350static void
23351xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23352{
23353 if (vctxt == NULL)
23354 return;
23355
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023356 vctxt->flags = 0;
23357
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023358 vctxt->validationRoot = NULL;
23359 if (vctxt->attr != NULL) {
23360 xmlSchemaFreeAttributeStates(vctxt->attr);
23361 vctxt->attr = NULL;
23362 }
23363 if (vctxt->value != NULL) {
23364 xmlSchemaFreeValue(vctxt->value);
23365 vctxt->value = NULL;
23366 }
23367 /*
23368 * Augmented IDC information.
23369 */
23370 if (vctxt->aidcs != NULL) {
23371 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23372 do {
23373 next = cur->next;
23374 xmlFree(cur);
23375 cur = next;
23376 } while (cur != NULL);
23377 vctxt->aidcs = NULL;
23378 }
23379 if (vctxt->idcNodes != NULL) {
23380 int i;
23381 xmlSchemaPSVIIDCNodePtr item;
23382
23383 for (i = 0; i < vctxt->nbIdcNodes; i++) {
23384 item = vctxt->idcNodes[i];
23385 xmlFree(item->keys);
23386 xmlFree(item);
23387 }
23388 xmlFree(vctxt->idcNodes);
23389 vctxt->idcNodes = NULL;
23390 }
23391 /*
23392 * Note that we won't delete the XPath state pool here.
23393 */
23394 if (vctxt->xpathStates != NULL) {
23395 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23396 vctxt->xpathStates = NULL;
23397 }
23398 if (vctxt->attrInfo != NULL) {
23399 if (vctxt->attrInfo->value != NULL) {
23400 xmlSchemaFreeValue(vctxt->attrInfo->value);
23401 }
23402 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
23403 }
23404 if (vctxt->elemInfos != NULL) {
23405 int i;
23406 xmlSchemaNodeInfoPtr info;
23407
23408 for (i = 0; i < vctxt->sizeElemInfos; i++) {
23409 info = vctxt->elemInfos[i];
23410 if (info == NULL)
23411 break;
23412 if (info->value != NULL) {
23413 xmlSchemaFreeValue(info->value);
23414 info->value = NULL;
23415 }
23416 if (info->idcMatchers != NULL) {
23417 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
23418 info->idcMatchers = NULL;
23419 }
23420 if (info->idcTable != NULL) {
23421 xmlSchemaIDCFreeIDCTable(info->idcTable);
23422 info->idcTable = NULL;
23423 }
23424 }
23425 }
23426}
23427
23428/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023429 * xmlSchemaFreeValidCtxt:
23430 * @ctxt: the schema validation context
23431 *
23432 * Free the resources associated to the schema validation context
23433 */
23434void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023435xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23436{
Daniel Veillard4255d502002-04-16 15:50:10 +000023437 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023438 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023439 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000023440 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000023441 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023442 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023443 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023444 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023445 if (ctxt->idcNodes != NULL) {
23446 int i;
23447 xmlSchemaPSVIIDCNodePtr item;
23448
23449 for (i = 0; i < ctxt->nbIdcNodes; i++) {
23450 item = ctxt->idcNodes[i];
23451 xmlFree(item->keys);
23452 xmlFree(item);
23453 }
23454 xmlFree(ctxt->idcNodes);
23455 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023456 if (ctxt->idcKeys != NULL) {
23457 int i;
23458 for (i = 0; i < ctxt->nbIdcKeys; i++)
23459 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23460 xmlFree(ctxt->idcKeys);
23461 }
23462
23463 if (ctxt->xpathStates != NULL)
23464 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23465 if (ctxt->xpathStatePool != NULL)
23466 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23467
23468 /*
23469 * Augmented IDC information.
23470 */
23471 if (ctxt->aidcs != NULL) {
23472 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23473 do {
23474 next = cur->next;
23475 xmlFree(cur);
23476 cur = next;
23477 } while (cur != NULL);
23478 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023479 if (ctxt->attrInfo != NULL) {
23480 if (ctxt->attrInfo->value != NULL)
23481 xmlSchemaFreeValue(ctxt->attrInfo->value);
23482 xmlFree(ctxt->attrInfo);
23483 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023484 if (ctxt->elemInfos != NULL) {
23485 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023486 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023487
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023488 for (i = 0; i < ctxt->sizeElemInfos; i++) {
23489 info = ctxt->elemInfos[i];
23490 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023491 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023492 if (info->value != NULL)
23493 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023494 if (info->idcMatchers != NULL)
23495 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023496 if (info->idcTable != NULL)
23497 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023498 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023499 * TODO: Don't know if those will have to be freed if in streaming
23500 * mode.
23501 *
23502 * xmlFree(info->localName);
23503 * if (info->namespaceName != NULL)
23504 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023505 */
23506 xmlFree(info);
23507 }
23508 xmlFree(ctxt->elemInfos);
23509 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023510 xmlFree(ctxt);
23511}
23512
23513/**
23514 * xmlSchemaSetValidErrors:
23515 * @ctxt: a schema validation context
23516 * @err: the error function
23517 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023518 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023519 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023520 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023521 */
23522void
23523xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023524 xmlSchemaValidityErrorFunc err,
23525 xmlSchemaValidityWarningFunc warn, void *ctx)
23526{
Daniel Veillard4255d502002-04-16 15:50:10 +000023527 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023528 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023529 ctxt->error = err;
23530 ctxt->warning = warn;
23531 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023532 if (ctxt->pctxt != NULL)
23533 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023534}
23535
23536/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023537 * xmlSchemaGetValidErrors:
23538 * @ctxt: a XML-Schema validation context
23539 * @err: the error function result
23540 * @warn: the warning function result
23541 * @ctx: the functions context result
23542 *
23543 * Get the error and warning callback informations
23544 *
23545 * Returns -1 in case of error and 0 otherwise
23546 */
23547int
23548xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23549 xmlSchemaValidityErrorFunc * err,
23550 xmlSchemaValidityWarningFunc * warn, void **ctx)
23551{
23552 if (ctxt == NULL)
23553 return (-1);
23554 if (err != NULL)
23555 *err = ctxt->error;
23556 if (warn != NULL)
23557 *warn = ctxt->warning;
23558 if (ctx != NULL)
23559 *ctx = ctxt->userData;
23560 return (0);
23561}
23562
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023563
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023564/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023565 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023566 * @ctxt: a schema validation context
23567 * @options: a combination of xmlSchemaValidOption
23568 *
23569 * Sets the options to be used during the validation.
23570 *
23571 * Returns 0 in case of success, -1 in case of an
23572 * API error.
23573 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023574int
23575xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23576 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023577
23578{
23579 int i;
23580
23581 if (ctxt == NULL)
23582 return (-1);
23583 /*
23584 * WARNING: Change the start value if adding to the
23585 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023586 * TODO: Is there an other, more easy to maintain,
23587 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023588 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023589 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023590 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023591 xmlSchemaVErr(ctxt, NULL,
23592 XML_SCHEMAV_INTERNAL,
23593 "Internal error: xmlSchemaSetValidOptions, "
23594 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023595 return (-1);
23596 }
23597 }
23598 ctxt->options = options;
23599 return (0);
23600}
23601
23602/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023603 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023604 * @ctxt: a schema validation context
23605 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023606 * Get the validation context options.
23607 *
23608 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023609 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023610int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023611xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
23612
23613{
23614 if (ctxt == NULL)
23615 return (-1);
23616 else
23617 return (ctxt->options);
23618}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023619
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023620
Daniel Veillard259f0df2004-08-18 09:13:18 +000023621/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023622 * xmlSchemaValidateDoc:
23623 * @ctxt: a schema validation context
23624 * @doc: a parsed document tree
23625 *
23626 * Validate a document tree in memory.
23627 *
23628 * Returns 0 if the document is schemas valid, a positive error code
23629 * number otherwise and -1 in case of internal or API error.
23630 */
23631int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023632xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23633{
Daniel Veillard4255d502002-04-16 15:50:10 +000023634 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023635 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023636
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023637 ctxt->doc = doc;
23638 ctxt->node = xmlDocGetRootElement(doc);
23639 if (ctxt->node == NULL) {
23640 xmlSchemaVCustomErr(ctxt,
23641 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23642 (xmlNodePtr) doc, NULL,
23643 "The document has no document element", NULL);
23644 return (ctxt->err);
23645 }
23646 ctxt->validationRoot = ctxt->node;
23647 xmlSchemaStartValidation(ctxt);
23648
23649 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000023650}
23651
23652/**
23653 * xmlSchemaValidateStream:
23654 * @ctxt: a schema validation context
23655 * @input: the input to use for reading the data
23656 * @enc: an optional encoding information
23657 * @sax: a SAX handler for the resulting events
23658 * @user_data: the context to provide to the SAX handler.
23659 *
23660 * Validate a document tree in memory.
23661 *
23662 * Returns 0 if the document is schemas valid, a positive error code
23663 * number otherwise and -1 in case of internal or API error.
23664 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023665int
Daniel Veillard4255d502002-04-16 15:50:10 +000023666xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023667 xmlParserInputBufferPtr input, xmlCharEncoding enc,
23668 xmlSAXHandlerPtr sax, void *user_data)
23669{
Daniel Veillard4255d502002-04-16 15:50:10 +000023670 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023671 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023672 ctxt->input = input;
23673 ctxt->enc = enc;
23674 ctxt->sax = sax;
23675 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023676 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023677}
23678
Daniel Veillard5d4644e2005-04-01 13:11:58 +000023679#define bottom_xmlschemas
23680#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000023681#endif /* LIBXML_SCHEMAS_ENABLED */