blob: e92baf9e5d6e9a7ce6a8a2100d8be498a20377ed [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. Buchcik4efd90d2005-06-09 10:32:53 +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.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * 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:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
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
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000046#ifdef LIBXML_READER_ENABLED
47#include <libxml/xmlreader.h>
48#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000049
Daniel Veillarda84c0b32003-06-02 16:58:46 +000050/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000051
Daniel Veillard82bbbd42003-05-11 20:16:09 +000052/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000053
Daniel Veillard82bbbd42003-05-11 20:16:09 +000054/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000055
Daniel Veillard118aed72002-09-24 14:13:13 +000056/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000057
Daniel Veillard4255d502002-04-16 15:50:10 +000058/* #define DEBUG_AUTOMATA 1 */
59
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000060#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000061
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000062/* #define DEBUG_IDC 1 */
63
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000064/* #define DEBUG_INCLUDES 1 */
65
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000066/* #define ENABLE_PARTICLE_RESTRICTION 1 */
67
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000068#define DUMP_CONTENT_MODEL
69
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000070/* #define XML_SCHEMA_SAX_ENABLED */
71
72#ifdef LIBXML_READER_ENABLED
73/* #define XML_SCHEMA_READER_ENABLED */
74#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000075
Daniel Veillard4255d502002-04-16 15:50:10 +000076#define UNBOUNDED (1 << 30)
77#define TODO \
78 xmlGenericError(xmlGenericErrorContext, \
79 "Unimplemented block at %s:%d\n", \
80 __FILE__, __LINE__);
81
William M. Brack2f2a6632004-08-20 23:09:47 +000082#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000083
Daniel Veillard4255d502002-04-16 15:50:10 +000084/*
85 * The XML Schemas namespaces
86 */
87static const xmlChar *xmlSchemaNs = (const xmlChar *)
88 "http://www.w3.org/2001/XMLSchema";
89
90static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
91 "http://www.w3.org/2001/XMLSchema-instance";
92
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000093static const xmlChar *xmlNamespaceNs = (const xmlChar *)
94 "http://www.w3.org/2000/xmlns/";
95
Daniel Veillardc0826a72004-08-10 14:17:33 +000096static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000097 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000098static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000099 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000100static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000101 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000102static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000103 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000104static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000105 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000106#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000107static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000108 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000109#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define IS_SCHEMA(node, type) \
112 ((node != NULL) && (node->ns != NULL) && \
113 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
114 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
115
Daniel Veillardc0826a72004-08-10 14:17:33 +0000116#define FREE_AND_NULL(str) \
117 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000118 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000119 str = NULL; \
120 }
121
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000122#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000123 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
124 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000125
126#define IS_COMPLEX_TYPE(item) \
127 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
128 (item->builtInType == XML_SCHEMAS_ANYTYPE))
129
130#define IS_SIMPLE_TYPE(item) \
131 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
132 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000133 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000135#define IS_ANY_SIMPLE_TYPE(item) \
136 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000137 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000138
139#define IS_NOT_TYPEFIXED(item) \
140 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
141 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
142
143#define HAS_COMPLEX_CONTENT(item) \
144 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
145 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
146 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
147
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000148#define HAS_SIMPLE_CONTENT(item) \
149 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
150 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
151
152#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
153
154#define IS_PARTICLE_EMPTIABLE(item) \
155 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
156
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000157#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
158
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000159#define GET_LIST_ITEM_TYPE(item) item->subtypes
160
161#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
162#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
163#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
164
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000165#define IS_MODEL_GROUP(item) \
166 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
167 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
168 (item->type == XML_SCHEMA_TYPE_ALL))
169
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000170#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
171
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000172#define ELEM_TYPE(item) item->subtypes
173
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000174#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
175
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000176#define SUBST_GROUP_AFF(item) item->refDecl
177
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000178#if 0
179#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
180#endif
181
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000182#define SUBSET_RESTRICTION 1<<0
183#define SUBSET_EXTENSION 1<<1
184#define SUBSET_SUBSTITUTION 1<<2
185#define SUBSET_LIST 1<<3
186#define SUBSET_UNION 1<<4
187
Daniel Veillard4255d502002-04-16 15:50:10 +0000188#define XML_SCHEMAS_PARSE_ERROR 1
189
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000190#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
191
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000192typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
193typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000196typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000197typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000198
199typedef struct _xmlSchemaItemList xmlSchemaItemList;
200typedef xmlSchemaItemList *xmlSchemaItemListPtr;
201
202struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000203 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000204 int nbItems; /* used for dynamic addition of schemata */
205 int sizeItems; /* used for dynamic addition of schemata */
206};
207
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000208typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
209typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
210struct _xmlSchemaAbstractCtxt {
211 int type;
212};
213
214#define XML_SCHEMA_CTXT_PARSER 1
215#define XML_SCHEMA_CTXT_VALIDATOR 2
216
Daniel Veillard4255d502002-04-16 15:50:10 +0000217struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000218 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000219 void *userData; /* user specific data block */
220 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
221 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000222 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000223 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000224 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000225
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000226 xmlSchemaPtr topschema; /* The main schema */
227 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
228
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000229 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000230 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000231 int counter;
232
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000233 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000235 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000236
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000237 const char *buffer;
238 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000239
Daniel Veillard4255d502002-04-16 15:50:10 +0000240 /*
241 * Used to build complex element content models
242 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000243 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000244 xmlAutomataStatePtr start;
245 xmlAutomataStatePtr end;
246 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000247
248 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000249 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000250 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
251 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000252 xmlSchemaAssemblePtr assemble;
253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000255 const xmlChar **localImports; /* list of locally imported namespaces */
256 int sizeLocalImports;
257 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000258 xmlHashTablePtr substGroups;
Daniel Veillard4255d502002-04-16 15:50:10 +0000259};
260
Daniel Veillard4255d502002-04-16 15:50:10 +0000261#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000262#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000263#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
267#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000268#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000269#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000270#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
271#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
272#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
273#define XML_SCHEMAS_ATTR_WILD_SKIP 13
274#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
275#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
276#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
277#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000278
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000279/**
280 * xmlSchemaBasicItem:
281 *
282 * The abstract base type for schema components.
283 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000284typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
285typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
286struct _xmlSchemaBasicItem {
287 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000288};
289
290/**
291 * xmlSchemaAnnotItem:
292 *
293 * The abstract base type for annotated schema components.
294 * (Extends xmlSchemaBasicItem)
295 */
296typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
297typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
298struct _xmlSchemaAnnotItem {
299 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000300 xmlSchemaAnnotPtr annot;
301};
302
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000303/**
304 * xmlSchemaTreeItem:
305 *
306 * The abstract base type for tree-like structured schema components.
307 * (Extends xmlSchemaAnnotItem)
308 */
309typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
310typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
311struct _xmlSchemaTreeItem {
312 xmlSchemaTypeType type;
313 xmlSchemaAnnotPtr annot;
314 xmlSchemaTreeItemPtr next;
315 xmlSchemaTreeItemPtr children;
316};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000317
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000318/**
319 * xmlSchemaQNameRef:
320 *
321 * A component reference item (not a schema component)
322 * (Extends xmlSchemaBasicItem)
323 */
324typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
325typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
326struct _xmlSchemaQNameRef {
327 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000328 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000329 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 const xmlChar *name;
331 const xmlChar *targetNamespace;
332};
333
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000334/**
335 * xmlSchemaParticle:
336 *
337 * A particle component.
338 * (Extends xmlSchemaTreeItem)
339 */
340typedef struct _xmlSchemaParticle xmlSchemaParticle;
341typedef xmlSchemaParticle *xmlSchemaParticlePtr;
342struct _xmlSchemaParticle {
343 xmlSchemaTypeType type;
344 xmlSchemaAnnotPtr annot;
345 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
346 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
347 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000348 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000349 xmlNodePtr node;
350};
351
352/**
353 * xmlSchemaModelGroup:
354 *
355 * A model group component.
356 * (Extends xmlSchemaTreeItem)
357 */
358typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
359typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
360struct _xmlSchemaModelGroup {
361 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
362 xmlSchemaAnnotPtr annot;
363 xmlSchemaTreeItemPtr next; /* not used */
364 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
365 xmlNodePtr node;
366};
367
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000368#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000369/**
370 * xmlSchemaModelGroupDef:
371 *
372 * A model group definition component.
373 * (Extends xmlSchemaTreeItem)
374 */
375typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
376typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
377struct _xmlSchemaModelGroupDef {
378 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
379 xmlSchemaAnnotPtr annot;
380 xmlSchemaTreeItemPtr next; /* not used */
381 xmlSchemaTreeItemPtr children; /* the "model group" */
382 const xmlChar *name;
383 const xmlChar *targetNamespace;
384 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000385 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000386};
387
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000388typedef struct _xmlSchemaIDC xmlSchemaIDC;
389typedef xmlSchemaIDC *xmlSchemaIDCPtr;
390
391/**
392 * xmlSchemaIDCSelect:
393 *
394 * The identity-constraint "field" and "selector" item, holding the
395 * XPath expression.
396 */
397typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
398typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000399struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000400 xmlSchemaIDCSelectPtr next;
401 xmlSchemaIDCPtr idc;
402 int index; /* an index position if significant for IDC key-sequences */
403 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000404 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000405};
406
407/**
408 * xmlSchemaIDC:
409 *
410 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000411 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000412 */
413
414struct _xmlSchemaIDC {
415 xmlSchemaTypeType type;
416 xmlSchemaAnnotPtr annot;
417 xmlSchemaIDCPtr next;
418 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000419 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000420 const xmlChar *targetNamespace;
421 xmlSchemaIDCSelectPtr selector;
422 xmlSchemaIDCSelectPtr fields;
423 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000424 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000425};
426
427/**
428 * xmlSchemaIDCAug:
429 *
430 * The augmented IDC information used for validation.
431 */
432typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
433typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
434struct _xmlSchemaIDCAug {
435 xmlSchemaIDCAugPtr next; /* next in a list */
436 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000437 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000438 tables need to be bubbled upwards */
439};
440
441/**
442 * xmlSchemaPSVIIDCKeySequence:
443 *
444 * The key sequence of a node table item.
445 */
446typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
447typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
448struct _xmlSchemaPSVIIDCKey {
449 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000450 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000451};
452
453/**
454 * xmlSchemaPSVIIDCNode:
455 *
456 * The node table item of a node table.
457 */
458typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
459typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
460struct _xmlSchemaPSVIIDCNode {
461 xmlNodePtr node;
462 xmlSchemaPSVIIDCKeyPtr *keys;
463};
464
465/**
466 * xmlSchemaPSVIIDCBinding:
467 *
468 * The identity-constraint binding item of the [identity-constraint table].
469 */
470typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
471typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
472struct _xmlSchemaPSVIIDCBinding {
473 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
474 xmlSchemaIDCPtr definition; /* the IDC definition */
475 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
476 int nbNodes; /* number of entries in the node table */
477 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000478 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000479 table */
480 /* int nbKeys; number of keys in each key-sequence */
481};
482
483#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
484#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
485
486#define XPATH_STATE_OBJ_MATCHES -2
487#define XPATH_STATE_OBJ_BLOCKED -3
488
489typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
490typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
491
492/**
493 * xmlSchemaIDCStateObj:
494 *
495 * The state object used to evaluate XPath expressions.
496 */
497typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
498typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
499struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000500 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000501 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000502 int depth; /* depth of creation */
503 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000504 int nbHistory;
505 int sizeHistory;
506 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
507 matcher */
508 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000509 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000510};
511
512#define IDC_MATCHER 0
513
514/**
515 * xmlSchemaIDCMatcher:
516 *
517 * Used to IDC selectors (and fields) successively.
518 */
519struct _xmlSchemaIDCMatcher {
520 int type;
521 int depth; /* the tree depth at creation time */
522 xmlSchemaIDCMatcherPtr next; /* next in the list */
523 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
524 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
525 elements */
526 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000527 int targetDepth;
528};
529
530/*
531* Element info flags.
532*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000533#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
534#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
535#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
536#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
537
538#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
539#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
540#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
541
542#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
543#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
544#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
545#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000546
547/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000548 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000549 *
550 * Holds information of an element node.
551 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000552struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000553 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000554 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 const xmlChar *nsName;
557 const xmlChar *value;
558 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000559 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000560 int flags; /* combination of node info flags */
561 int valNeeded;
562 int normVal;
563
564 xmlSchemaElementPtr decl; /* the element/attribute declaration */
565 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000566 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
567 for the scope element*/
568 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
569 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000570 xmlRegExecCtxtPtr regexCtxt;
571
572 const xmlChar **nsBindings; /* Namespace bindings on this element */
573 int nbNsBindings;
574 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000575};
576
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000577/*
578* @metaType values of xmlSchemaAttrInfo.
579*/
580#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
581#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
582#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
584#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000585
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000586typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
587typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
588struct _xmlSchemaAttrInfo {
589 xmlNodePtr node;
590 int nodeType;
591 const xmlChar *localName;
592 const xmlChar *nsName;
593 const xmlChar *value;
594 xmlSchemaValPtr val; /* the pre-computed value if any */
595 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
596 int flags; /* combination of node info flags */
597
598 xmlSchemaAttributePtr decl; /* the attribute declaration */
599 xmlSchemaAttributePtr use; /* the attribute use */
600 int state;
601 int metaType;
602 const xmlChar *vcValue; /* the value constraint value */
603 xmlSchemaNodeInfoPtr parent;
604};
605
606
607#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000608/**
609 * xmlSchemaValidCtxt:
610 *
611 * A Schemas validation context
612 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000613struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000614 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000615 void *userData; /* user specific data block */
616 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000617 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000618 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000619
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000620 xmlSchemaPtr schema; /* The schema in use */
621 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000622 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000623 xmlCharEncoding enc;
624 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000625 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000626 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000627
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 int err;
629 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000630
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000631 xmlNodePtr node;
632 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000633 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000634
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000635 xmlRegExecCtxtPtr regexp;
636 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000637
Daniel Veillardc0826a72004-08-10 14:17:33 +0000638 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000639 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000640 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000641 xmlSchemaParserCtxtPtr pctxt;
642 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000643
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000644 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000645 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000647 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000648
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000649 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
650
651 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
652 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000653
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000654 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
655 int nbIdcNodes;
656 int sizeIdcNodes;
657
658 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
659 int nbIdcKeys;
660 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000661
662 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000663
664 xmlDictPtr dict;
665
666 xmlTextReaderPtr reader;
667
668 xmlSchemaAttrInfoPtr *attrInfos;
669 int nbAttrInfos;
670 int sizeAttrInfos;
671
672 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000673};
674
Daniel Veillard1d913862003-11-21 00:28:39 +0000675/*
676 * These are the entries in the schemas importSchemas hash table
677 */
678typedef struct _xmlSchemaImport xmlSchemaImport;
679typedef xmlSchemaImport *xmlSchemaImportPtr;
680struct _xmlSchemaImport {
681 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000682 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000683 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000684 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000685};
Daniel Veillard4255d502002-04-16 15:50:10 +0000686
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000687/*
688 * These are the entries associated to includes in a schemas
689 */
690typedef struct _xmlSchemaInclude xmlSchemaInclude;
691typedef xmlSchemaInclude *xmlSchemaIncludePtr;
692struct _xmlSchemaInclude {
693 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000694 const xmlChar *schemaLocation;
695 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000696 const xmlChar *origTargetNamespace;
697 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698};
699
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000700/**
701 * xmlSchemaSubstGroup:
702 *
703 *
704 */
705typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
706typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
707struct _xmlSchemaSubstGroup {
708 xmlSchemaElementPtr head;
709 xmlSchemaItemListPtr members;
710};
711
Daniel Veillard4255d502002-04-16 15:50:10 +0000712/************************************************************************
713 * *
714 * Some predeclarations *
715 * *
716 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000717
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000718static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
719 xmlSchemaPtr schema,
720 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000721static void
722xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
723 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000724static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
726static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000727xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
728 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000729static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000730xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
731 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000732static void
733xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000734static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000735xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000736static xmlSchemaTreeItemPtr
737xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
738 xmlNodePtr node, xmlSchemaTypeType type,
739 int withParticle);
740static const xmlChar *
741xmlSchemaCompTypeToString(xmlSchemaTypeType type);
742static xmlSchemaTypeLinkPtr
743xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000744static void
745xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
746 const char *funcName,
747 const char *message);
748static int
749xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
750 xmlSchemaTypePtr baseType,
751 int subset);
752static void
753xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
754 xmlSchemaParserCtxtPtr ctxt,
755 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000756
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000757/************************************************************************
758 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000759 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000760 * *
761 ************************************************************************/
762
763/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000764 * xmlSchemaCompTypeToString:
765 * @type: the type of the schema item
766 *
767 * Returns the component name of a schema item.
768 */
769static const xmlChar *
770xmlSchemaCompTypeToString(xmlSchemaTypeType type)
771{
772 switch (type) {
773 case XML_SCHEMA_TYPE_SIMPLE:
774 return(BAD_CAST "simple type definition");
775 case XML_SCHEMA_TYPE_COMPLEX:
776 return(BAD_CAST "complex type definition");
777 case XML_SCHEMA_TYPE_ELEMENT:
778 return(BAD_CAST "element declaration");
779 case XML_SCHEMA_TYPE_ATTRIBUTE:
780 return(BAD_CAST "attribute declaration");
781 case XML_SCHEMA_TYPE_GROUP:
782 return(BAD_CAST "model group definition");
783 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
784 return(BAD_CAST "attribute group definition");
785 case XML_SCHEMA_TYPE_NOTATION:
786 return(BAD_CAST "notation declaration");
787 case XML_SCHEMA_TYPE_SEQUENCE:
788 return(BAD_CAST "model group (sequence)");
789 case XML_SCHEMA_TYPE_CHOICE:
790 return(BAD_CAST "model group (choice)");
791 case XML_SCHEMA_TYPE_ALL:
792 return(BAD_CAST "model group (all)");
793 case XML_SCHEMA_TYPE_PARTICLE:
794 return(BAD_CAST "particle");
795 default:
796 return(BAD_CAST "Not a schema component");
797 }
798}
799
800/**
801 * xmlSchemaGetComponentNode:
802 * @item: a schema component
803 *
804 * Returns node associated with the schema component.
805 * NOTE that such a node need not be available; plus, a component's
806 * node need not to reflect the component directly, since there is no
807 * one-to-one relationship between the XML Schema representation and
808 * the component representation.
809 */
810static xmlNodePtr
811xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
812{
813 switch (item->type) {
814 case XML_SCHEMA_TYPE_ELEMENT:
815 return (((xmlSchemaElementPtr) item)->node);
816 case XML_SCHEMA_TYPE_ATTRIBUTE:
817 return (((xmlSchemaAttributePtr) item)->node);
818 case XML_SCHEMA_TYPE_COMPLEX:
819 case XML_SCHEMA_TYPE_SIMPLE:
820 return (((xmlSchemaTypePtr) item)->node);
821 case XML_SCHEMA_TYPE_ANY:
822 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
823 return (((xmlSchemaWildcardPtr) item)->node);
824 case XML_SCHEMA_TYPE_PARTICLE:
825 return (((xmlSchemaParticlePtr) item)->node);
826 case XML_SCHEMA_TYPE_SEQUENCE:
827 case XML_SCHEMA_TYPE_CHOICE:
828 case XML_SCHEMA_TYPE_ALL:
829 return (((xmlSchemaModelGroupPtr) item)->node);
830 case XML_SCHEMA_TYPE_GROUP:
831 return (((xmlSchemaModelGroupDefPtr) item)->node);
832 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
833 return (((xmlSchemaAttributeGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_IDC_UNIQUE:
835 case XML_SCHEMA_TYPE_IDC_KEY:
836 case XML_SCHEMA_TYPE_IDC_KEYREF:
837 return (((xmlSchemaIDCPtr) item)->node);
838 default:
839 return (NULL);
840 }
841}
842
843#if 0
844/**
845 * xmlSchemaGetNextComponent:
846 * @item: a schema component
847 *
848 * Returns the next sibling of the schema component.
849 */
850static xmlSchemaBasicItemPtr
851xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
852{
853 switch (item->type) {
854 case XML_SCHEMA_TYPE_ELEMENT:
855 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
856 case XML_SCHEMA_TYPE_ATTRIBUTE:
857 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
858 case XML_SCHEMA_TYPE_COMPLEX:
859 case XML_SCHEMA_TYPE_SIMPLE:
860 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
861 case XML_SCHEMA_TYPE_ANY:
862 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
863 return (NULL);
864 case XML_SCHEMA_TYPE_PARTICLE:
865 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
866 case XML_SCHEMA_TYPE_SEQUENCE:
867 case XML_SCHEMA_TYPE_CHOICE:
868 case XML_SCHEMA_TYPE_ALL:
869 return (NULL);
870 case XML_SCHEMA_TYPE_GROUP:
871 return (NULL);
872 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
873 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
874 case XML_SCHEMA_TYPE_IDC_UNIQUE:
875 case XML_SCHEMA_TYPE_IDC_KEY:
876 case XML_SCHEMA_TYPE_IDC_KEYREF:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
878 default:
879 return (NULL);
880 }
881}
882#endif
883
884/**
885 * xmlSchemaGetAttrName:
886 * @attr: the attribute declaration/use
887 *
888 * Returns the name of the attribute; if the attribute
889 * is a reference, the name of the referenced global type will be returned.
890 */
891static const xmlChar *
892xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
893{
894 if (attr->ref != NULL)
895 return(attr->ref);
896 else
897 return(attr->name);
898}
899
900/**
901 * xmlSchemaGetAttrTargetNsURI:
902 * @type: the type (element or attribute)
903 *
904 * Returns the target namespace URI of the type; if the type is a reference,
905 * the target namespace of the referenced type will be returned.
906 */
907static const xmlChar *
908xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
909{
910 if (attr->ref != NULL)
911 return (attr->refNs);
912 else
913 return(attr->targetNamespace);
914}
915
916/**
917 * xmlSchemaFormatQName:
918 * @buf: the string buffer
919 * @namespaceName: the namespace name
920 * @localName: the local name
921 *
922 * Returns the given QName in the format "{namespaceName}localName" or
923 * just "localName" if @namespaceName is NULL.
924 *
925 * Returns the localName if @namespaceName is NULL, a formatted
926 * string otherwise.
927 */
928static const xmlChar*
929xmlSchemaFormatQName(xmlChar **buf,
930 const xmlChar *namespaceName,
931 const xmlChar *localName)
932{
933 FREE_AND_NULL(*buf)
934 if (namespaceName == NULL)
935 return(localName);
936
937 *buf = xmlStrdup(BAD_CAST "{");
938 *buf = xmlStrcat(*buf, namespaceName);
939 *buf = xmlStrcat(*buf, BAD_CAST "}");
940 *buf = xmlStrcat(*buf, localName);
941
942 return ((const xmlChar *) *buf);
943}
944
945static const xmlChar*
946xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
947{
948 if (ns != NULL)
949 return (xmlSchemaFormatQName(buf, ns->href, localName));
950 else
951 return (xmlSchemaFormatQName(buf, NULL, localName));
952}
953
954static const xmlChar *
955xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
956{
957 switch (item->type) {
958 case XML_SCHEMA_TYPE_ELEMENT:
959 return (((xmlSchemaElementPtr) item)->name);
960 case XML_SCHEMA_TYPE_ATTRIBUTE:
961 return (((xmlSchemaAttributePtr) item)->name);
962 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
963 return (((xmlSchemaAttributeGroupPtr) item)->name);
964 case XML_SCHEMA_TYPE_BASIC:
965 case XML_SCHEMA_TYPE_SIMPLE:
966 case XML_SCHEMA_TYPE_COMPLEX:
967 return (((xmlSchemaTypePtr) item)->name);
968 case XML_SCHEMA_TYPE_GROUP:
969 return (((xmlSchemaModelGroupDefPtr) item)->name);
970 case XML_SCHEMA_TYPE_IDC_KEY:
971 case XML_SCHEMA_TYPE_IDC_UNIQUE:
972 case XML_SCHEMA_TYPE_IDC_KEYREF:
973 return (((xmlSchemaIDCPtr) item)->name);
974 default:
975 /*
976 * Other components cannot have names.
977 */
978 break;
979 }
980 return (NULL);
981}
982
983static const xmlChar *
984xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
985{
986 switch (item->type) {
987 case XML_SCHEMA_TYPE_ELEMENT:
988 return (((xmlSchemaElementPtr) item)->targetNamespace);
989 case XML_SCHEMA_TYPE_ATTRIBUTE:
990 return (((xmlSchemaAttributePtr) item)->targetNamespace);
991 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
992 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_BASIC:
994 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
995 case XML_SCHEMA_TYPE_SIMPLE:
996 case XML_SCHEMA_TYPE_COMPLEX:
997 return (((xmlSchemaTypePtr) item)->targetNamespace);
998 case XML_SCHEMA_TYPE_GROUP:
999 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1000 case XML_SCHEMA_TYPE_IDC_KEY:
1001 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1002 case XML_SCHEMA_TYPE_IDC_KEYREF:
1003 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1004 default:
1005 /*
1006 * Other components cannot have names.
1007 */
1008 break;
1009 }
1010 return (NULL);
1011}
1012
1013static const xmlChar*
1014xmlSchemaGetComponentQName(xmlChar **buf,
1015 void *item)
1016{
1017 return (xmlSchemaFormatQName(buf,
1018 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1019 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1020}
1021
1022/**
1023 * xmlSchemaWildcardPCToString:
1024 * @pc: the type of processContents
1025 *
1026 * Returns a string representation of the type of
1027 * processContents.
1028 */
1029static const xmlChar *
1030xmlSchemaWildcardPCToString(int pc)
1031{
1032 switch (pc) {
1033 case XML_SCHEMAS_ANY_SKIP:
1034 return (BAD_CAST "skip");
1035 case XML_SCHEMAS_ANY_LAX:
1036 return (BAD_CAST "lax");
1037 case XML_SCHEMAS_ANY_STRICT:
1038 return (BAD_CAST "strict");
1039 default:
1040 return (BAD_CAST "invalid process contents");
1041 }
1042}
1043
1044/**
1045 * xmlSchemaGetCanonValueWhtspExt:
1046 * @val: the precomputed value
1047 * @retValue: the returned value
1048 * @ws: the whitespace type of the value
1049 *
1050 * Get a the cononical representation of the value.
1051 * The caller has to free the returned retValue.
1052 *
1053 * Returns 0 if the value could be built and -1 in case of
1054 * API errors or if the value type is not supported yet.
1055 */
1056static int
1057xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1058 xmlSchemaWhitespaceValueType ws,
1059 xmlChar **retValue)
1060{
1061 int list;
1062 xmlSchemaValType valType;
1063 const xmlChar *value, *value2 = NULL;
1064
1065
1066 if ((retValue == NULL) || (val == NULL))
1067 return (-1);
1068 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1069 *retValue = NULL;
1070 do {
1071 value = NULL;
1072 valType = xmlSchemaGetValType(val);
1073 switch (valType) {
1074 case XML_SCHEMAS_STRING:
1075 case XML_SCHEMAS_NORMSTRING:
1076 case XML_SCHEMAS_ANYSIMPLETYPE:
1077 value = xmlSchemaValueGetAsString(val);
1078 if (value != NULL) {
1079 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1080 value2 = xmlSchemaCollapseString(value);
1081 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1082 value2 = xmlSchemaWhiteSpaceReplace(value);
1083 if (value2 != NULL)
1084 value = value2;
1085 }
1086 break;
1087 default:
1088 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1089 if (value2 != NULL)
1090 xmlFree((xmlChar *) value2);
1091 goto internal_error;
1092 }
1093 value = value2;
1094 }
1095 if (*retValue == NULL)
1096 if (value == NULL) {
1097 if (! list)
1098 *retValue = xmlStrdup(BAD_CAST "");
1099 } else
1100 *retValue = xmlStrdup(value);
1101 else if (value != NULL) {
1102 /* List. */
1103 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1104 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1105 }
1106 FREE_AND_NULL(value2)
1107 val = xmlSchemaValueGetNext(val);
1108 } while (val != NULL);
1109
1110 return (0);
1111internal_error:
1112 if (*retValue != NULL)
1113 xmlFree((xmlChar *) (*retValue));
1114 if (value2 != NULL)
1115 xmlFree((xmlChar *) value2);
1116 return (-1);
1117}
1118
1119/**
1120 * xmlSchemaFormatItemForReport:
1121 * @buf: the string buffer
1122 * @itemDes: the designation of the item
1123 * @itemName: the name of the item
1124 * @item: the item as an object
1125 * @itemNode: the node of the item
1126 * @local: the local name
1127 * @parsing: if the function is used during the parse
1128 *
1129 * Returns a representation of the given item used
1130 * for error reports.
1131 *
1132 * The following order is used to build the resulting
1133 * designation if the arguments are not NULL:
1134 * 1a. If itemDes not NULL -> itemDes
1135 * 1b. If (itemDes not NULL) and (itemName not NULL)
1136 * -> itemDes + itemName
1137 * 2. If the preceding was NULL and (item not NULL) -> item
1138 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1139 *
1140 * If the itemNode is an attribute node, the name of the attribute
1141 * will be appended to the result.
1142 *
1143 * Returns the formatted string and sets @buf to the resulting value.
1144 */
1145static xmlChar*
1146xmlSchemaFormatItemForReport(xmlChar **buf,
1147 const xmlChar *itemDes,
1148 xmlSchemaTypePtr item,
1149 xmlNodePtr itemNode)
1150{
1151 xmlChar *str = NULL;
1152 int named = 1;
1153
1154 if (*buf != NULL) {
1155 xmlFree(*buf);
1156 *buf = NULL;
1157 }
1158
1159 if (itemDes != NULL) {
1160 *buf = xmlStrdup(itemDes);
1161 } else if (item != NULL) {
1162 switch (item->type) {
1163 case XML_SCHEMA_TYPE_BASIC:
1164 if (VARIETY_ATOMIC(item))
1165 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1166 else if (VARIETY_LIST(item))
1167 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1168 else if (VARIETY_UNION(item))
1169 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1170 else
1171 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1172 *buf = xmlStrcat(*buf, item->name);
1173 *buf = xmlStrcat(*buf, BAD_CAST "'");
1174 break;
1175 case XML_SCHEMA_TYPE_SIMPLE:
1176 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1177 *buf = xmlStrdup(BAD_CAST"");
1178 } else {
1179 *buf = xmlStrdup(BAD_CAST "local ");
1180 }
1181 if (VARIETY_ATOMIC(item))
1182 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1183 else if (VARIETY_LIST(item))
1184 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1185 else if (VARIETY_UNION(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1187 else
1188 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1189 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1190 *buf = xmlStrcat(*buf, BAD_CAST " '");
1191 *buf = xmlStrcat(*buf, item->name);
1192 *buf = xmlStrcat(*buf, BAD_CAST "'");
1193 }
1194 break;
1195 case XML_SCHEMA_TYPE_COMPLEX:
1196 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1197 *buf = xmlStrdup(BAD_CAST "");
1198 else
1199 *buf = xmlStrdup(BAD_CAST "local ");
1200 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1201 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1202 *buf = xmlStrcat(*buf, BAD_CAST " '");
1203 *buf = xmlStrcat(*buf, item->name);
1204 *buf = xmlStrcat(*buf, BAD_CAST "'");
1205 }
1206 break;
1207 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1208 xmlSchemaAttributePtr attr;
1209
1210 attr = (xmlSchemaAttributePtr) item;
1211 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1212 (attr->ref == NULL)) {
1213 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1214 *buf = xmlStrcat(*buf, BAD_CAST " '");
1215 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1216 attr->targetNamespace, attr->name));
1217 FREE_AND_NULL(str)
1218 *buf = xmlStrcat(*buf, BAD_CAST "'");
1219 } else {
1220 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1221 *buf = xmlStrcat(*buf, BAD_CAST " '");
1222 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1223 attr->refNs, attr->ref));
1224 FREE_AND_NULL(str)
1225 *buf = xmlStrcat(*buf, BAD_CAST "'");
1226 }
1227 }
1228 break;
1229 case XML_SCHEMA_TYPE_ELEMENT: {
1230 xmlSchemaElementPtr elem;
1231
1232 elem = (xmlSchemaElementPtr) item;
1233 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1234 (elem->ref == NULL)) {
1235 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1236 *buf = xmlStrcat(*buf, BAD_CAST " '");
1237 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1238 elem->targetNamespace, elem->name));
1239 *buf = xmlStrcat(*buf, BAD_CAST "'");
1240 }
1241 }
1242 break;
1243 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1244 case XML_SCHEMA_TYPE_IDC_KEY:
1245 case XML_SCHEMA_TYPE_IDC_KEYREF:
1246 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1247 *buf = xmlStrdup(BAD_CAST "unique '");
1248 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1249 *buf = xmlStrdup(BAD_CAST "key '");
1250 else
1251 *buf = xmlStrdup(BAD_CAST "keyRef '");
1252 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1253 *buf = xmlStrcat(*buf, BAD_CAST "'");
1254 break;
1255 case XML_SCHEMA_TYPE_ANY:
1256 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1257 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1258 ((xmlSchemaWildcardPtr) item)->processContents));
1259 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1260 break;
1261 case XML_SCHEMA_FACET_MININCLUSIVE:
1262 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1263 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1264 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1265 case XML_SCHEMA_FACET_TOTALDIGITS:
1266 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1267 case XML_SCHEMA_FACET_PATTERN:
1268 case XML_SCHEMA_FACET_ENUMERATION:
1269 case XML_SCHEMA_FACET_WHITESPACE:
1270 case XML_SCHEMA_FACET_LENGTH:
1271 case XML_SCHEMA_FACET_MAXLENGTH:
1272 case XML_SCHEMA_FACET_MINLENGTH:
1273 *buf = xmlStrdup(BAD_CAST "facet '");
1274 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1275 *buf = xmlStrcat(*buf, BAD_CAST "'");
1276 break;
1277 case XML_SCHEMA_TYPE_NOTATION:
1278 *buf = xmlStrdup(BAD_CAST "notation");
1279 break;
1280 case XML_SCHEMA_TYPE_GROUP: {
1281 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1282 *buf = xmlStrcat(*buf, BAD_CAST " '");
1283 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1284 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1285 ((xmlSchemaModelGroupDefPtr) item)->name));
1286 *buf = xmlStrcat(*buf, BAD_CAST "'");
1287 FREE_AND_NULL(str)
1288 }
1289 break;
1290 case XML_SCHEMA_TYPE_SEQUENCE:
1291 case XML_SCHEMA_TYPE_CHOICE:
1292 case XML_SCHEMA_TYPE_ALL:
1293 case XML_SCHEMA_TYPE_PARTICLE:
1294 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1295 break;
1296 default:
1297 named = 0;
1298 }
1299 } else
1300 named = 0;
1301
1302 if ((named == 0) && (itemNode != NULL)) {
1303 xmlNodePtr elem;
1304
1305 if (itemNode->type == XML_ATTRIBUTE_NODE)
1306 elem = itemNode->parent;
1307 else
1308 elem = itemNode;
1309 *buf = xmlStrdup(BAD_CAST "Element '");
1310 if (elem->ns != NULL) {
1311 *buf = xmlStrcat(*buf,
1312 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1313 FREE_AND_NULL(str)
1314 } else
1315 *buf = xmlStrcat(*buf, elem->name);
1316 *buf = xmlStrcat(*buf, BAD_CAST "'");
1317
1318 }
1319 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1320 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1321 if (itemNode->ns != NULL) {
1322 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1323 itemNode->ns->href, itemNode->name));
1324 FREE_AND_NULL(str)
1325 } else
1326 *buf = xmlStrcat(*buf, itemNode->name);
1327 *buf = xmlStrcat(*buf, BAD_CAST "'");
1328 }
1329 FREE_AND_NULL(str)
1330
1331 return (*buf);
1332}
1333
1334/**
1335 * xmlSchemaFormatFacetEnumSet:
1336 * @buf: the string buffer
1337 * @type: the type holding the enumeration facets
1338 *
1339 * Builds a string consisting of all enumeration elements.
1340 *
1341 * Returns a string of all enumeration elements.
1342 */
1343static const xmlChar *
1344xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1345 xmlChar **buf, xmlSchemaTypePtr type)
1346{
1347 xmlSchemaFacetPtr facet;
1348 xmlSchemaWhitespaceValueType ws;
1349 xmlChar *value = NULL;
1350 int res;
1351
1352 if (*buf != NULL)
1353 xmlFree(*buf);
1354 *buf = NULL;
1355
1356 do {
1357 /*
1358 * Use the whitespace type of the base type.
1359 */
1360 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1361 for (facet = type->facets; facet != NULL; facet = facet->next) {
1362 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1363 continue;
1364 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1365 ws, &value);
1366 if (res == -1) {
1367 xmlSchemaInternalErr(actxt,
1368 "xmlSchemaFormatFacetEnumSet",
1369 "compute the canonical lexical representation");
1370 if (*buf != NULL)
1371 xmlFree(*buf);
1372 *buf = NULL;
1373 return (NULL);
1374 }
1375 if (*buf == NULL)
1376 *buf = xmlStrdup(BAD_CAST "'");
1377 else
1378 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1379 *buf = xmlStrcat(*buf, BAD_CAST value);
1380 *buf = xmlStrcat(*buf, BAD_CAST "'");
1381 if (value != NULL) {
1382 xmlFree((xmlChar *)value);
1383 value = NULL;
1384 }
1385 }
1386 type = type->baseType;
1387 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1388
1389 return ((const xmlChar *) *buf);
1390}
1391
1392/************************************************************************
1393 * *
1394 * Error functions *
1395 * *
1396 ************************************************************************/
1397
1398#if 0
1399static void
1400xmlSchemaErrMemory(const char *msg)
1401{
1402 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1403 msg);
1404}
1405#endif
1406
1407/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001408 * xmlSchemaPErrMemory:
1409 * @node: a context node
1410 * @extra: extra informations
1411 *
1412 * Handle an out of memory condition
1413 */
1414static void
1415xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1416 const char *extra, xmlNodePtr node)
1417{
1418 if (ctxt != NULL)
1419 ctxt->nberrors++;
1420 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1421 extra);
1422}
1423
1424/**
1425 * xmlSchemaPErr:
1426 * @ctxt: the parsing context
1427 * @node: the context node
1428 * @error: the error code
1429 * @msg: the error message
1430 * @str1: extra data
1431 * @str2: extra data
1432 *
1433 * Handle a parser error
1434 */
1435static void
1436xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1437 const char *msg, const xmlChar * str1, const xmlChar * str2)
1438{
1439 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001440 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001441 void *data = NULL;
1442
1443 if (ctxt != NULL) {
1444 ctxt->nberrors++;
1445 channel = ctxt->error;
1446 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001447 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001448 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001449 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001450 error, XML_ERR_ERROR, NULL, 0,
1451 (const char *) str1, (const char *) str2, NULL, 0, 0,
1452 msg, str1, str2);
1453}
1454
1455/**
1456 * xmlSchemaPErr2:
1457 * @ctxt: the parsing context
1458 * @node: the context node
1459 * @node: the current child
1460 * @error: the error code
1461 * @msg: the error message
1462 * @str1: extra data
1463 * @str2: extra data
1464 *
1465 * Handle a parser error
1466 */
1467static void
1468xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1469 xmlNodePtr child, int error,
1470 const char *msg, const xmlChar * str1, const xmlChar * str2)
1471{
1472 if (child != NULL)
1473 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1474 else
1475 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1476}
1477
Daniel Veillard01fa6152004-06-29 17:04:39 +00001478
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001479/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001480 * xmlSchemaPErrExt:
1481 * @ctxt: the parsing context
1482 * @node: the context node
1483 * @error: the error code
1484 * @strData1: extra data
1485 * @strData2: extra data
1486 * @strData3: extra data
1487 * @msg: the message
1488 * @str1: extra parameter for the message display
1489 * @str2: extra parameter for the message display
1490 * @str3: extra parameter for the message display
1491 * @str4: extra parameter for the message display
1492 * @str5: extra parameter for the message display
1493 *
1494 * Handle a parser error
1495 */
1496static void
1497xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1498 const xmlChar * strData1, const xmlChar * strData2,
1499 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1500 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1501 const xmlChar * str5)
1502{
1503
1504 xmlGenericErrorFunc channel = NULL;
1505 xmlStructuredErrorFunc schannel = NULL;
1506 void *data = NULL;
1507
1508 if (ctxt != NULL) {
1509 ctxt->nberrors++;
1510 channel = ctxt->error;
1511 data = ctxt->userData;
1512 schannel = ctxt->serror;
1513 }
1514 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1515 error, XML_ERR_ERROR, NULL, 0,
1516 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001517 (const char *) strData3, 0, 0, msg, str1, str2,
1518 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001519}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001520
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001521/************************************************************************
1522 * *
1523 * Allround error functions *
1524 * *
1525 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001526
1527/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001528 * xmlSchemaVTypeErrMemory:
1529 * @node: a context node
1530 * @extra: extra informations
1531 *
1532 * Handle an out of memory condition
1533 */
1534static void
1535xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1536 const char *extra, xmlNodePtr node)
1537{
1538 if (ctxt != NULL) {
1539 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001540 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001541 }
1542 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1543 extra);
1544}
1545
1546/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001547 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001548 * @ctxt: the validation context
1549 * @node: the context node
1550 * @error: the error code
1551 * @msg: the error message
1552 * @str1: extra data
1553 * @str2: extra data
1554 * @str3: extra data
1555 *
1556 * Handle a validation error
1557 */
1558static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001559xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1560 int error, xmlNodePtr node, const char *msg,
1561 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001563 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001564 xmlGenericErrorFunc channel = NULL;
1565 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001566
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001567 if (ctxt != NULL) {
1568 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1569 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
1570
1571 vctxt->nberrors++;
1572 vctxt->err = error;
1573 channel = vctxt->error;
1574 schannel = vctxt->serror;
1575 data = vctxt->userData;
1576 if ((node == NULL) && (vctxt->depth >= 0) &&
1577 (vctxt->inode != NULL))
1578 node = vctxt->inode->node;
1579 __xmlRaiseError(schannel, channel, data, ctxt,
1580 node, XML_FROM_SCHEMASV,
1581 error, XML_ERR_ERROR, NULL, 0,
1582 (const char *) str1, (const char *) str2,
1583 (const char *) str3, 0, 0, msg, str1, str2, str3);
1584
1585 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1586 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1587
1588 pctxt->nberrors++;
1589 pctxt->err = error;
1590 channel = pctxt->error;
1591 schannel = pctxt->serror;
1592 data = pctxt->userData;
1593 __xmlRaiseError(schannel, channel, data, ctxt,
1594 node, XML_FROM_SCHEMASP,
1595 error, XML_ERR_ERROR, NULL, 0,
1596 (const char *) str1, (const char *) str2,
1597 (const char *) str3, 0, 0, msg, str1, str2, str3);
1598 } else {
1599 TODO
1600 }
1601 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001602}
1603
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001604static void
1605xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1606 int error, xmlNodePtr node, const char *msg,
1607 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001608{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001609 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001610}
1611
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001612static xmlChar *
1613xmlSchemaFormatNodeForError(xmlChar ** msg,
1614 xmlSchemaAbstractCtxtPtr actxt,
1615 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001616{
1617 xmlChar *str = NULL;
1618
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001619 if (node != NULL) {
1620 /*
1621 * Work on tree nodes.
1622 */
1623 if (node->type == XML_ATTRIBUTE_NODE) {
1624 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001625
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001626 *msg = xmlStrdup(BAD_CAST "Element '");
1627 if (elem->ns != NULL)
1628 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1629 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001630 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1632 NULL, elem->name));
1633 FREE_AND_NULL(str);
1634 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1635 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1636 } else {
1637 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001638 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001639 if (node->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, node->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1647 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1648 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1649 /*
1650 * Work on node infos.
1651 */
1652 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1653 xmlSchemaNodeInfoPtr ielem =
1654 vctxt->elemInfos[vctxt->depth];
1655
1656 *msg = xmlStrdup(BAD_CAST "Element '");
1657 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1658 ielem->nsName, ielem->localName));
1659 FREE_AND_NULL(str);
1660 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1661 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1662 } else {
1663 *msg = xmlStrdup(BAD_CAST "Element '");
1664 }
1665 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1666 vctxt->inode->nsName, vctxt->inode->localName));
1667 FREE_AND_NULL(str);
1668 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1669 } else {
1670 TODO
1671 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001672 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001673 /*
1674 * VAL TODO: The output of the given schema component is currently
1675 * disabled.
1676 */
1677#if 0
1678 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1679 *msg = xmlStrcat(*msg, BAD_CAST " [");
1680 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1681 NULL, type, NULL, 0));
1682 FREE_AND_NULL(str)
1683 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685#endif
1686 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001687}
1688
Daniel Veillardc0826a72004-08-10 14:17:33 +00001689static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001690xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1691 const char *funcName,
1692 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001693{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001694 xmlChar *msg = NULL;
1695
1696 msg = xmlStrdup(BAD_CAST "Internal error: ");
1697 msg = xmlStrcat(msg, BAD_CAST funcName);
1698 msg = xmlStrcat(msg, BAD_CAST ", ");
1699 msg = xmlStrcat(msg, BAD_CAST message);
1700 msg = xmlStrcat(msg, BAD_CAST ".\n");
1701
1702 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1703 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1704 (const char *) msg, NULL, NULL);
1705
1706 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1707 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1708 (const char *) msg, NULL, NULL);
1709
1710 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001711}
1712
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001713static void
1714xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1715 xmlParserErrors error,
1716 xmlNodePtr node,
1717 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1718 const char *message,
1719 const xmlChar *str1,
1720 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001721{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001722 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001723
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001724 xmlSchemaFormatNodeForError(&msg, actxt, node);
1725 msg = xmlStrcat(msg, (const xmlChar *) message);
1726 msg = xmlStrcat(msg, BAD_CAST ".\n");
1727 xmlSchemaErr(actxt, error, node,
1728 (const char *) msg, str1, str2);
1729 FREE_AND_NULL(msg)
1730}
1731
1732static int
1733xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1734 xmlNodePtr node)
1735{
1736 if (node != NULL)
1737 return (node->type);
1738 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1739 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1740 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1741 return (-1);
1742}
1743
1744static int
1745xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1746{
1747 switch (item->type) {
1748 case XML_SCHEMA_TYPE_COMPLEX:
1749 case XML_SCHEMA_TYPE_SIMPLE:
1750 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1751 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001752 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001753 case XML_SCHEMA_TYPE_GROUP:
1754 return (1);
1755 case XML_SCHEMA_TYPE_ELEMENT:
1756 if ( ((xmlSchemaElementPtr) item)->flags &
1757 XML_SCHEMAS_ELEM_GLOBAL)
1758 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001759 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001760 case XML_SCHEMA_TYPE_ATTRIBUTE:
1761 if ( ((xmlSchemaAttributePtr) item)->flags &
1762 XML_SCHEMAS_ATTR_GLOBAL)
1763 return(1);
1764 break;
1765 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001766 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001767 return(1);
1768 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001769 return (0);
1770}
1771
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772static void
1773xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1774 xmlParserErrors error,
1775 xmlNodePtr node,
1776 const xmlChar *value,
1777 xmlSchemaTypePtr type,
1778 int displayValue)
1779{
1780 xmlChar *msg = NULL;
1781
1782 xmlSchemaFormatNodeForError(&msg, actxt, node);
1783
1784 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1785 XML_ATTRIBUTE_NODE))
1786 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1787 else
1788 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1789 "value of ");
1790
1791 if (! xmlSchemaIsGlobalItem(type))
1792 msg = xmlStrcat(msg, BAD_CAST "the local ");
1793 else
1794 msg = xmlStrcat(msg, BAD_CAST "the ");
1795
1796 if (VARIETY_ATOMIC(type))
1797 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1798 else if (VARIETY_LIST(type))
1799 msg = xmlStrcat(msg, BAD_CAST "list type");
1800 else if (VARIETY_UNION(type))
1801 msg = xmlStrcat(msg, BAD_CAST "union type");
1802
1803 if (xmlSchemaIsGlobalItem(type)) {
1804 xmlChar *str = NULL;
1805 msg = xmlStrcat(msg, BAD_CAST " '");
1806 if (type->builtInType != 0) {
1807 msg = xmlStrcat(msg, BAD_CAST "xs:");
1808 msg = xmlStrcat(msg, type->name);
1809 } else
1810 msg = xmlStrcat(msg,
1811 xmlSchemaFormatQName(&str,
1812 type->targetNamespace, type->name));
1813 msg = xmlStrcat(msg, BAD_CAST "'");
1814 FREE_AND_NULL(str);
1815 }
1816 msg = xmlStrcat(msg, BAD_CAST ".\n");
1817 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1818 XML_ATTRIBUTE_NODE))
1819 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1820 else
1821 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1822 FREE_AND_NULL(msg)
1823}
1824
Daniel Veillardc0826a72004-08-10 14:17:33 +00001825static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001826xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1827 xmlSchemaNodeInfoPtr ni,
1828 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001829{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001830 if (node != NULL) {
1831 if (node->ns != NULL)
1832 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1833 else
1834 return (xmlSchemaFormatQName(str, NULL, node->name));
1835 } else if (ni != NULL)
1836 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1837 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001838}
1839
Daniel Veillardc0826a72004-08-10 14:17:33 +00001840static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001841xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1842 xmlParserErrors error,
1843 xmlSchemaAttrInfoPtr ni,
1844 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001845{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001846 xmlChar *msg = NULL, *str = NULL;
1847
1848 xmlSchemaFormatNodeForError(&msg, actxt, node);
1849 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1850 xmlSchemaErr(actxt, error, node, (const char *) msg,
1851 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1852 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001853 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001854 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001855}
1856
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1859 xmlParserErrors error,
1860 xmlNodePtr node,
1861 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001862 const char *message,
1863 int nbval,
1864 int nbneg,
1865 xmlChar **values)
1866{
1867 xmlChar *str = NULL, *msg = NULL;
1868 xmlChar *localName, *nsName;
1869 const xmlChar *cur, *end;
1870 int i;
1871
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001872 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001873 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001874 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001875 /*
1876 * Note that is does not make sense to report that we have a
1877 * wildcard here, since the wildcard might be unfolded into
1878 * multiple transitions.
1879 */
1880 if (nbval + nbneg > 0) {
1881 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001882 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001883 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 nsName = NULL;
1886
1887 for (i = 0; i < nbval + nbneg; i++) {
1888 cur = values[i];
1889 /*
1890 * Get the local name.
1891 */
1892 localName = NULL;
1893
1894 end = cur;
1895 if (*end == '*') {
1896 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001897 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001898 } else {
1899 while ((*end != 0) && (*end != '|'))
1900 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001901 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001902 }
1903 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001904 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001905 /*
1906 * Skip "*|*" if they come with negated expressions, since
1907 * they represent the same negated wildcard.
1908 */
1909 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1910 /*
1911 * Get the namespace name.
1912 */
1913 cur = end;
1914 if (*end == '*') {
1915 nsName = xmlStrdup(BAD_CAST "{*}");
1916 } else {
1917 while (*end != 0)
1918 end++;
1919
1920 if (i >= nbval)
1921 nsName = xmlStrdup(BAD_CAST "{##other:");
1922 else
1923 nsName = xmlStrdup(BAD_CAST "{");
1924
1925 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1926 nsName = xmlStrcat(nsName, BAD_CAST "}");
1927 }
1928 str = xmlStrcat(str, BAD_CAST nsName);
1929 FREE_AND_NULL(nsName)
1930 } else {
1931 FREE_AND_NULL(localName);
1932 continue;
1933 }
1934 }
1935 str = xmlStrcat(str, BAD_CAST localName);
1936 FREE_AND_NULL(localName);
1937
1938 if (i < nbval + nbneg -1)
1939 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001940 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001941 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001942 msg = xmlStrcat(msg, BAD_CAST str);
1943 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001944 } else
1945 msg = xmlStrcat(msg, BAD_CAST "\n");
1946 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001947 xmlFree(msg);
1948}
1949
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001950static void
1951xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1952 xmlParserErrors error,
1953 xmlNodePtr node,
1954 const xmlChar *value,
1955 unsigned long length,
1956 xmlSchemaTypePtr type,
1957 xmlSchemaFacetPtr facet,
1958 const char *message,
1959 const xmlChar *str1,
1960 const xmlChar *str2)
1961{
1962 xmlChar *str = NULL, *msg = NULL;
1963 xmlSchemaTypeType facetType;
1964 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1965
1966 xmlSchemaFormatNodeForError(&msg, actxt, node);
1967 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1968 facetType = XML_SCHEMA_FACET_ENUMERATION;
1969 /*
1970 * If enumerations are validated, one must not expect the
1971 * facet to be given.
1972 */
1973 } else
1974 facetType = facet->type;
1975 msg = xmlStrcat(msg, BAD_CAST "[");
1976 msg = xmlStrcat(msg, BAD_CAST "facet '");
1977 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1978 msg = xmlStrcat(msg, BAD_CAST "'] ");
1979 if (message == NULL) {
1980 /*
1981 * Use a default message.
1982 */
1983 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1984 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1985 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1986
1987 char len[25], actLen[25];
1988
1989 /* FIXME, TODO: What is the max expected string length of the
1990 * this value?
1991 */
1992 if (nodeType == XML_ATTRIBUTE_NODE)
1993 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1994 else
1995 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1996
1997 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1998 snprintf(actLen, 24, "%lu", length);
1999
2000 if (facetType == XML_SCHEMA_FACET_LENGTH)
2001 msg = xmlStrcat(msg,
2002 BAD_CAST "this differs from the allowed length of '%s'.\n");
2003 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2004 msg = xmlStrcat(msg,
2005 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2006 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2007 msg = xmlStrcat(msg,
2008 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2009
2010 if (nodeType == XML_ATTRIBUTE_NODE)
2011 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2012 value, (const xmlChar *) actLen, (const xmlChar *) len);
2013 else
2014 xmlSchemaErr(actxt, error, node, (const char *) msg,
2015 (const xmlChar *) actLen, (const xmlChar *) len);
2016
2017 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2018 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2019 "of the set {%s}.\n");
2020 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2021 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2022 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2023 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2024 "by the pattern '%s'.\n");
2025 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2026 facet->value);
2027 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2028 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2029 "minimum value allowed ('%s').\n");
2030 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2031 facet->value);
2032 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2033 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2034 "maximum value allowed ('%s').\n");
2035 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2036 facet->value);
2037 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2038 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2039 "'%s'.\n");
2040 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2041 facet->value);
2042 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2043 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2044 "'%s'.\n");
2045 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2046 facet->value);
2047 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2048 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2049 "digits than are allowed ('%s').\n");
2050 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2051 facet->value);
2052 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2053 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2054 "digits than are allowed ('%s').\n");
2055 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2056 facet->value);
2057 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2058 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2059 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2060 } else {
2061 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2062 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2063 }
2064 } else {
2065 msg = xmlStrcat(msg, (const xmlChar *) message);
2066 msg = xmlStrcat(msg, BAD_CAST ".\n");
2067 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2068 }
2069 FREE_AND_NULL(str)
2070 xmlFree(msg);
2071}
2072
2073#define VERROR(err, type, msg) \
2074 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2075
2076#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2077
2078#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2079
2080#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2081
2082
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002083/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002084 * xmlSchemaPMissingAttrErr:
2085 * @ctxt: the schema validation context
2086 * @ownerDes: the designation of the owner
2087 * @ownerName: the name of the owner
2088 * @ownerItem: the owner as a schema object
2089 * @ownerElem: the owner as an element node
2090 * @node: the parent element node of the missing attribute node
2091 * @type: the corresponding type of the attribute node
2092 *
2093 * Reports an illegal attribute.
2094 */
2095static void
2096xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002097 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002098 xmlSchemaTypePtr ownerItem,
2099 xmlNodePtr ownerElem,
2100 const char *name,
2101 const char *message)
2102{
2103 xmlChar *des = NULL;
2104
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002105 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2106
Daniel Veillardc0826a72004-08-10 14:17:33 +00002107 if (message != NULL)
2108 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 else
2110 xmlSchemaPErr(ctxt, ownerElem, error,
2111 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002112 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002113 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002114}
2115
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002116
Daniel Veillardc0826a72004-08-10 14:17:33 +00002117/**
2118 * xmlSchemaPResCompAttrErr:
2119 * @ctxt: the schema validation context
2120 * @error: the error code
2121 * @ownerDes: the designation of the owner
2122 * @ownerItem: the owner as a schema object
2123 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002124 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002125 * @refName: the referenced local name
2126 * @refURI: the referenced namespace URI
2127 * @message: optional message
2128 *
2129 * Used to report QName attribute values that failed to resolve
2130 * to schema components.
2131 */
2132static void
2133xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002134 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002135 xmlSchemaTypePtr ownerItem,
2136 xmlNodePtr ownerElem,
2137 const char *name,
2138 const xmlChar *refName,
2139 const xmlChar *refURI,
2140 xmlSchemaTypeType refType,
2141 const char *refTypeStr)
2142{
2143 xmlChar *des = NULL, *strA = NULL;
2144
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002145 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002146 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002147 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2148 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002149 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2151 "%s.\n", BAD_CAST des, BAD_CAST name,
2152 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002153 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002154 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002155 FREE_AND_NULL(strA)
2156}
2157
William M. Brack2f2a6632004-08-20 23:09:47 +00002158/**
2159 * xmlSchemaPCustomAttrErr:
2160 * @ctxt: the schema parser context
2161 * @error: the error code
2162 * @ownerDes: the designation of the owner
2163 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002164 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002165 *
2166 * Reports an illegal attribute during the parse.
2167 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168static void
2169xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002170 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002171 xmlChar **ownerDes,
2172 xmlSchemaTypePtr ownerItem,
2173 xmlAttrPtr attr,
2174 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002175{
2176 xmlChar *des = NULL;
2177
2178 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002179 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002180 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002181 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002182 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002183 } else
2184 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002185 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002186 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2188 if (ownerDes == NULL)
2189 FREE_AND_NULL(des);
2190}
2191
2192/**
2193 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002194 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002195 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002196 * @ownerDes: the designation of the attribute's owner
2197 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002200 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002201 */
2202static void
2203xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002204 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002205 xmlChar **ownerDes,
2206 xmlSchemaTypePtr ownerItem,
2207 xmlAttrPtr attr)
2208{
2209 xmlChar *des = NULL, *strA = NULL;
2210
2211 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002212 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002213 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002214 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002215 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 } else
2217 des = *ownerDes;
2218 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2219 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2220 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 if (ownerDes == NULL)
2222 FREE_AND_NULL(des);
2223 FREE_AND_NULL(strA);
2224}
2225
William M. Brack2f2a6632004-08-20 23:09:47 +00002226/**
2227 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002229 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002230 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002231 * @itemElem: the node of the schema item
2232 *
2233 * Creates a designation for an item.
2234 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002235static void
2236xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002237 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002238 xmlSchemaTypePtr item,
2239 xmlNodePtr itemElem)
2240{
2241 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002242 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002243 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002244 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002245 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 } else
2247 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002248}
2249
William M. Brack2f2a6632004-08-20 23:09:47 +00002250/**
2251 * xmlSchemaPCustomErr:
2252 * @ctxt: the schema parser context
2253 * @error: the error code
2254 * @itemDes: the designation of the schema item
2255 * @item: the schema item
2256 * @itemElem: the node of the schema item
2257 * @message: the error message
2258 * @str1: an optional param for the error message
2259 * @str2: an optional param for the error message
2260 * @str3: an optional param for the error message
2261 *
2262 * Reports an error during parsing.
2263 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002264static void
2265xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002266 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002267 xmlChar **itemDes,
2268 xmlSchemaTypePtr item,
2269 xmlNodePtr itemElem,
2270 const char *message,
2271 const xmlChar *str1,
2272 const xmlChar *str2,
2273 const xmlChar *str3)
2274{
2275 xmlChar *des = NULL, *msg = NULL;
2276
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002277 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002278 msg = xmlStrdup(BAD_CAST "%s: ");
2279 msg = xmlStrcat(msg, (const xmlChar *) message);
2280 msg = xmlStrcat(msg, BAD_CAST ".\n");
2281 if ((itemElem == NULL) && (item != NULL))
2282 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002283 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002284 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2285 if (itemDes == NULL)
2286 FREE_AND_NULL(des);
2287 FREE_AND_NULL(msg);
2288}
2289
William M. Brack2f2a6632004-08-20 23:09:47 +00002290/**
2291 * xmlSchemaPCustomErr:
2292 * @ctxt: the schema parser context
2293 * @error: the error code
2294 * @itemDes: the designation of the schema item
2295 * @item: the schema item
2296 * @itemElem: the node of the schema item
2297 * @message: the error message
2298 * @str1: the optional param for the error message
2299 *
2300 * Reports an error during parsing.
2301 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002302static void
2303xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002304 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002305 xmlChar **itemDes,
2306 xmlSchemaTypePtr item,
2307 xmlNodePtr itemElem,
2308 const char *message,
2309 const xmlChar *str1)
2310{
2311 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2312 str1, NULL, NULL);
2313}
2314
William M. Brack2f2a6632004-08-20 23:09:47 +00002315/**
2316 * xmlSchemaPAttrUseErr:
2317 * @ctxt: the schema parser context
2318 * @error: the error code
2319 * @itemDes: the designation of the schema type
2320 * @item: the schema type
2321 * @itemElem: the node of the schema type
2322 * @attr: the invalid schema attribute
2323 * @message: the error message
2324 * @str1: the optional param for the error message
2325 *
2326 * Reports an attribute use error during parsing.
2327 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002328static void
2329xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002330 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002331 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002332 const xmlSchemaAttributePtr attr,
2333 const char *message,
2334 const xmlChar *str1)
2335{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002336 xmlChar *str = NULL, *msg = NULL;
2337 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2338 msg = xmlStrcat(msg, BAD_CAST ", ");
2339 msg = xmlStrcat(msg,
2340 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2341 (xmlSchemaTypePtr) attr, NULL));
2342 FREE_AND_NULL(str);
2343 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 msg = xmlStrcat(msg, (const xmlChar *) message);
2345 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002346 xmlSchemaPErr(ctxt, attr->node, error,
2347 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002348 xmlFree(msg);
2349}
2350
William M. Brack2f2a6632004-08-20 23:09:47 +00002351/**
2352 * xmlSchemaPIllegalFacetAtomicErr:
2353 * @ctxt: the schema parser context
2354 * @error: the error code
2355 * @itemDes: the designation of the type
2356 * @item: the schema type
2357 * @baseItem: the base type of type
2358 * @facet: the illegal facet
2359 *
2360 * Reports an illegal facet for atomic simple types.
2361 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002362static void
2363xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002364 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002365 xmlChar **itemDes,
2366 xmlSchemaTypePtr item,
2367 xmlSchemaTypePtr baseItem,
2368 xmlSchemaFacetPtr facet)
2369{
2370 xmlChar *des = NULL, *strT = NULL;
2371
2372 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2373 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2374 "%s: The facet '%s' is not allowed on types derived from the "
2375 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002376 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002377 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002378 NULL, NULL);
2379 if (itemDes == NULL)
2380 FREE_AND_NULL(des);
2381 FREE_AND_NULL(strT);
2382}
2383
William M. Brack2f2a6632004-08-20 23:09:47 +00002384/**
2385 * xmlSchemaPIllegalFacetListUnionErr:
2386 * @ctxt: the schema parser context
2387 * @error: the error code
2388 * @itemDes: the designation of the schema item involved
2389 * @item: the schema item involved
2390 * @facet: the illegal facet
2391 *
2392 * Reports an illegal facet for <list> and <union>.
2393 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002394static void
2395xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002396 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002397 xmlChar **itemDes,
2398 xmlSchemaTypePtr item,
2399 xmlSchemaFacetPtr facet)
2400{
2401 xmlChar *des = NULL, *strT = NULL;
2402
2403 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002404 xmlSchemaPErr(ctxt, item->node, error,
2405 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002406 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002407 if (itemDes == NULL)
2408 FREE_AND_NULL(des);
2409 FREE_AND_NULL(strT);
2410}
2411
2412/**
2413 * xmlSchemaPMutualExclAttrErr:
2414 * @ctxt: the schema validation context
2415 * @error: the error code
2416 * @elemDes: the designation of the parent element node
2417 * @attr: the bad attribute node
2418 * @type: the corresponding type of the attribute node
2419 *
2420 * Reports an illegal attribute.
2421 */
2422static void
2423xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2424 xmlParserErrors error,
2425 xmlChar **ownerDes,
2426 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002427 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002428 const char *name1,
2429 const char *name2)
2430{
2431 xmlChar *des = NULL;
2432
2433 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002434 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002435 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002436 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002437 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002438 } else
2439 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002440 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002441 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002442 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2443 if (ownerDes == NULL)
2444 FREE_AND_NULL(des)
2445}
2446
2447/**
2448 * xmlSchemaPSimpleTypeErr:
2449 * @ctxt: the schema validation context
2450 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002451 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002452 * @ownerDes: the designation of the owner
2453 * @ownerItem: the schema object if existent
2454 * @node: the validated node
2455 * @value: the validated value
2456 *
2457 * Reports a simple type validation error.
2458 * TODO: Should this report the value of an element as well?
2459 */
2460static void
2461xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2462 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002463 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002465 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002466 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002467 const xmlChar *value,
2468 const char *message,
2469 const xmlChar *str1,
2470 const xmlChar *str2)
2471{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002472 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002473
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002474 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002475 if (message == NULL) {
2476 /*
2477 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 */
2479 if (type != NULL) {
2480 if (node->type == XML_ATTRIBUTE_NODE)
2481 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2482 else
2483 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2484 "valid value of ");
2485 if (! xmlSchemaIsGlobalItem(type))
2486 msg = xmlStrcat(msg, BAD_CAST "the local ");
2487 else
2488 msg = xmlStrcat(msg, BAD_CAST "the ");
2489
2490 if (VARIETY_ATOMIC(type))
2491 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2492 else if (VARIETY_LIST(type))
2493 msg = xmlStrcat(msg, BAD_CAST "list type");
2494 else if (VARIETY_UNION(type))
2495 msg = xmlStrcat(msg, BAD_CAST "union type");
2496
2497 if (xmlSchemaIsGlobalItem(type)) {
2498 xmlChar *str = NULL;
2499 msg = xmlStrcat(msg, BAD_CAST " '");
2500 if (type->builtInType != 0) {
2501 msg = xmlStrcat(msg, BAD_CAST "xs:");
2502 msg = xmlStrcat(msg, type->name);
2503 } else
2504 msg = xmlStrcat(msg,
2505 xmlSchemaFormatQName(&str,
2506 type->targetNamespace, type->name));
2507 msg = xmlStrcat(msg, BAD_CAST "'.");
2508 FREE_AND_NULL(str);
2509 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002510 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002511 if (node->type == XML_ATTRIBUTE_NODE)
2512 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2513 else
2514 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2515 "valid.");
2516 }
2517 if (expected) {
2518 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2519 msg = xmlStrcat(msg, BAD_CAST expected);
2520 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2521 } else
2522 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002523 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002524 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2525 else
2526 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2527 } else {
2528 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2529 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002531 /* Cleanup. */
2532 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002533}
2534
William M. Brack2f2a6632004-08-20 23:09:47 +00002535/**
2536 * xmlSchemaPContentErr:
2537 * @ctxt: the schema parser context
2538 * @error: the error code
2539 * @onwerDes: the designation of the holder of the content
2540 * @ownerItem: the owner item of the holder of the content
2541 * @ownerElem: the node of the holder of the content
2542 * @child: the invalid child node
2543 * @message: the optional error message
2544 * @content: the optional string describing the correct content
2545 *
2546 * Reports an error concerning the content of a schema element.
2547 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002548static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002549xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002550 xmlParserErrors error,
2551 xmlChar **ownerDes,
2552 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002553 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002554 xmlNodePtr child,
2555 const char *message,
2556 const char *content)
2557{
2558 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002559
Daniel Veillardc0826a72004-08-10 14:17:33 +00002560 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002561 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002562 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002563 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002564 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 } else
2566 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002567 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002568 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2569 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002570 BAD_CAST des, BAD_CAST message);
2571 else {
2572 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002573 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2574 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002575 BAD_CAST des, BAD_CAST content);
2576 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2578 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 BAD_CAST des, NULL);
2580 }
2581 }
2582 if (ownerDes == NULL)
2583 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002584}
2585
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002586/************************************************************************
2587 * *
2588 * Streamable error functions *
2589 * *
2590 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002591
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002592
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002593
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002594
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002595/************************************************************************
2596 * *
2597 * Validation helper functions *
2598 * *
2599 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002600
Daniel Veillardc0826a72004-08-10 14:17:33 +00002601
Daniel Veillard4255d502002-04-16 15:50:10 +00002602/************************************************************************
2603 * *
2604 * Allocation functions *
2605 * *
2606 ************************************************************************/
2607
2608/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002609 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002610 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002611 *
2612 * Allocate a new Schema structure.
2613 *
2614 * Returns the newly allocated structure or NULL in case or error
2615 */
2616static xmlSchemaPtr
2617xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2618{
2619 xmlSchemaPtr ret;
2620
2621 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2622 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002623 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002624 return (NULL);
2625 }
2626 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002627 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002628 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002629
2630 return (ret);
2631}
2632
2633/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002634 * xmlSchemaNewSchema:
2635 * @ctxt: a schema validation context
2636 *
2637 * Allocate a new Schema structure.
2638 *
2639 * Returns the newly allocated structure or NULL in case or error
2640 */
2641static xmlSchemaAssemblePtr
2642xmlSchemaNewAssemble(void)
2643{
2644 xmlSchemaAssemblePtr ret;
2645
2646 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2647 if (ret == NULL) {
2648 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2649 return (NULL);
2650 }
2651 memset(ret, 0, sizeof(xmlSchemaAssemble));
2652 ret->items = NULL;
2653 return (ret);
2654}
2655
2656/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002657 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002658 *
2659 * Allocate a new Facet structure.
2660 *
2661 * Returns the newly allocated structure or NULL in case or error
2662 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002663xmlSchemaFacetPtr
2664xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002665{
2666 xmlSchemaFacetPtr ret;
2667
2668 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2669 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 return (NULL);
2671 }
2672 memset(ret, 0, sizeof(xmlSchemaFacet));
2673
2674 return (ret);
2675}
2676
2677/**
2678 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002679 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002680 * @node: a node
2681 *
2682 * Allocate a new annotation structure.
2683 *
2684 * Returns the newly allocated structure or NULL in case or error
2685 */
2686static xmlSchemaAnnotPtr
2687xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2688{
2689 xmlSchemaAnnotPtr ret;
2690
2691 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2692 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002693 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002694 return (NULL);
2695 }
2696 memset(ret, 0, sizeof(xmlSchemaAnnot));
2697 ret->content = node;
2698 return (ret);
2699}
2700
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002701static xmlSchemaItemListPtr
2702xmlSchemaNewItemList(void)
2703{
2704 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002705
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002706 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2707 if (ret == NULL) {
2708 xmlSchemaPErrMemory(NULL,
2709 "allocating an item list structure", NULL);
2710 return (NULL);
2711 }
2712 memset(ret, 0, sizeof(xmlSchemaItemList));
2713 return (ret);
2714}
2715
2716/**
2717 * xmlSchemaAddElementSubstitutionMember:
2718 * @pctxt: a schema parser context
2719 * @head: the head of the substitution group
2720 * @member: the new member of the substitution group
2721 *
2722 * Allocate a new annotation structure.
2723 *
2724 * Returns the newly allocated structure or NULL in case or error
2725 */
2726static int
2727xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2728 xmlSchemaElementPtr head,
2729 xmlSchemaElementPtr member)
2730{
2731 xmlSchemaSubstGroupPtr substGroup;
2732
2733 if (pctxt == NULL)
2734 return (-1);
2735
2736 if (pctxt->substGroups == NULL) {
2737 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2738 if (pctxt->substGroups == NULL)
2739 return (-1);
2740 }
2741 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2742 head->targetNamespace);
2743 if (substGroup == NULL) {
2744 int res;
2745
2746 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2747 if (substGroup == NULL) {
2748 xmlSchemaPErrMemory(NULL,
2749 "xmlSchemaAddElementSubstitution, allocating a substitution "
2750 "group container",
2751 NULL);
2752 return (-1);
2753 }
2754 substGroup->members = xmlSchemaNewItemList();
2755 if (substGroup->members == NULL) {
2756 xmlFree(substGroup);
2757 return (-1);
2758 }
2759 substGroup->head = head;
2760
2761 res = xmlHashAddEntry2(pctxt->substGroups,
2762 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002763 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002764 xmlFree(substGroup->members);
2765 xmlFree(substGroup);
2766 xmlSchemaPErr(pctxt, member->node,
2767 XML_SCHEMAP_INTERNAL,
2768 "Internal error: xmlSchemaAddElementSubstitution, "
2769 "failed to add a new substitution group container for "
2770 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002771 return (-1);
2772 }
2773 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002774 if (substGroup->members->items == NULL) {
2775 substGroup->members->items = (void **) xmlMalloc(
2776 5 * sizeof(xmlSchemaElementPtr));
2777 if (substGroup->members->items == NULL) {
2778 xmlSchemaPErrMemory(NULL,
2779 "allocating list of substitution group members", NULL);
2780 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002781 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002782 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002784 substGroup->members->nbItems) {
2785 substGroup->members->sizeItems *= 2;
2786 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002787 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002788 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2789 if (substGroup->members->items == NULL) {
2790 xmlSchemaPErrMemory(NULL,
2791 "re-allocating list of substitution group members", NULL);
2792 substGroup->members->sizeItems = 0;
2793 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002794 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002795 }
2796 ((xmlSchemaElementPtr *) substGroup->members->items)
2797 [substGroup->members->nbItems++] = (void *) member;
2798 return (0);
2799}
2800
2801/**
2802 * xmlSchemaGetElementSubstitutionGroup:
2803 * @pctxt: a schema parser context
2804 * @head: the head of the substitution group
2805 * @member: the new member of the substitution group
2806 *
2807 * Allocate a new annotation structure.
2808 *
2809 * Returns the newly allocated structure or NULL in case or error
2810 */
2811static xmlSchemaSubstGroupPtr
2812xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2813 xmlSchemaElementPtr head)
2814{
2815 if (pctxt == NULL)
2816 return (NULL);
2817
2818 if (pctxt->substGroups == NULL)
2819 return (NULL);
2820
2821 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2822 head->name, head->targetNamespace));
2823}
2824
2825/**
2826 * xmlSchemaFreeItemList:
2827 * @annot: a schema type structure
2828 *
2829 * Deallocate a annotation structure
2830 */
2831static void
2832xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2833{
2834 if (list == NULL)
2835 return;
2836 if (list->items != NULL)
2837 xmlFree(list->items);
2838 xmlFree(list);
2839}
2840
Daniel Veillard4255d502002-04-16 15:50:10 +00002841/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002842 * xmlSchemaFreeAnnot:
2843 * @annot: a schema type structure
2844 *
2845 * Deallocate a annotation structure
2846 */
2847static void
2848xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2849{
2850 if (annot == NULL)
2851 return;
2852 xmlFree(annot);
2853}
2854
2855/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002856 * xmlSchemaFreeImport:
2857 * @import: a schema import structure
2858 *
2859 * Deallocate an import structure
2860 */
2861static void
2862xmlSchemaFreeImport(xmlSchemaImportPtr import)
2863{
2864 if (import == NULL)
2865 return;
2866
2867 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002868 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002869 xmlFree(import);
2870}
2871
2872/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002873 * xmlSchemaFreeInclude:
2874 * @include: a schema include structure
2875 *
2876 * Deallocate an include structure
2877 */
2878static void
2879xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2880{
2881 if (include == NULL)
2882 return;
2883
2884 xmlFreeDoc(include->doc);
2885 xmlFree(include);
2886}
2887
2888/**
2889 * xmlSchemaFreeIncludeList:
2890 * @includes: a schema include list
2891 *
2892 * Deallocate an include structure
2893 */
2894static void
2895xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2896{
2897 xmlSchemaIncludePtr next;
2898
2899 while (includes != NULL) {
2900 next = includes->next;
2901 xmlSchemaFreeInclude(includes);
2902 includes = next;
2903 }
2904}
2905
2906/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002907 * xmlSchemaFreeNotation:
2908 * @schema: a schema notation structure
2909 *
2910 * Deallocate a Schema Notation structure.
2911 */
2912static void
2913xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2914{
2915 if (nota == NULL)
2916 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002917 xmlFree(nota);
2918}
2919
2920/**
2921 * xmlSchemaFreeAttribute:
2922 * @schema: a schema attribute structure
2923 *
2924 * Deallocate a Schema Attribute structure.
2925 */
2926static void
2927xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2928{
2929 if (attr == NULL)
2930 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002931 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002933 if (attr->defVal != NULL)
2934 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002935 xmlFree(attr);
2936}
2937
2938/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002939 * xmlSchemaFreeWildcardNsSet:
2940 * set: a schema wildcard namespace
2941 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002942 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002943 */
2944static void
2945xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2946{
2947 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002948
Daniel Veillard3646d642004-06-02 19:19:14 +00002949 while (set != NULL) {
2950 next = set->next;
2951 xmlFree(set);
2952 set = next;
2953 }
2954}
2955
2956/**
2957 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002958 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002959 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002960 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002962void
Daniel Veillard3646d642004-06-02 19:19:14 +00002963xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2964{
2965 if (wildcard == NULL)
2966 return;
2967 if (wildcard->annot != NULL)
2968 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002969 if (wildcard->nsSet != NULL)
2970 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2971 if (wildcard->negNsSet != NULL)
2972 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002973 xmlFree(wildcard);
2974}
2975
2976/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002977 * xmlSchemaFreeAttributeGroup:
2978 * @schema: a schema attribute group structure
2979 *
2980 * Deallocate a Schema Attribute Group structure.
2981 */
2982static void
2983xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2984{
2985 if (attr == NULL)
2986 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002987 if (attr->annot != NULL)
2988 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002989 xmlFree(attr);
2990}
2991
2992/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002993 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002994 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002995 *
2996 * Deallocate a list of schema attribute uses.
2997 */
2998static void
2999xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3000{
3001 xmlSchemaAttributeLinkPtr next;
3002
3003 while (attrUse != NULL) {
3004 next = attrUse->next;
3005 xmlFree(attrUse);
3006 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003007 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003008}
3009
3010/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003011 * xmlSchemaFreeQNameRef:
3012 * @item: a QName reference structure
3013 *
3014 * Deallocatea a QName reference structure.
3015 */
3016static void
3017xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3018{
3019 xmlFree(item);
3020}
3021
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003022/**
3023 * xmlSchemaFreeQNameRef:
3024 * @item: a QName reference structure
3025 *
3026 * Deallocatea a QName reference structure.
3027 */
3028static void
3029xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3030{
3031 if (item == NULL)
3032 return;
3033 if (item->members != NULL)
3034 xmlSchemaFreeItemList(item->members);
3035 xmlFree(item);
3036}
3037
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003038static int
3039xmlSchemaAddVolatile(xmlSchemaPtr schema,
3040 xmlSchemaBasicItemPtr item)
3041{
3042 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003043
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003044 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003045 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003046 if (schema->volatiles == NULL) {
3047 xmlSchemaPErrMemory(NULL,
3048 "allocating list of volatiles", NULL);
3049 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003050 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003051 }
3052 list = (xmlSchemaItemListPtr) schema->volatiles;
3053 if (list->items == NULL) {
3054 list->items = (void **) xmlMalloc(
3055 20 * sizeof(xmlSchemaBasicItemPtr));
3056 if (list->items == NULL) {
3057 xmlSchemaPErrMemory(NULL,
3058 "allocating new volatile item buffer", NULL);
3059 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003060 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003061 list->sizeItems = 20;
3062 } else if (list->sizeItems <= list->nbItems) {
3063 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003064 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003065 list->sizeItems * sizeof(xmlSchemaTypePtr));
3066 if (list->items == NULL) {
3067 xmlSchemaPErrMemory(NULL,
3068 "growing volatile item buffer", NULL);
3069 list->sizeItems = 0;
3070 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003071 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003072 }
3073 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3074 return (0);
3075}
3076
3077/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003078 * xmlSchemaFreeTypeLinkList:
3079 * @alink: a type link
3080 *
3081 * Deallocate a list of types.
3082 */
3083static void
3084xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3085{
3086 xmlSchemaTypeLinkPtr next;
3087
3088 while (link != NULL) {
3089 next = link->next;
3090 xmlFree(link);
3091 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003092 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003093}
3094
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003095static void
3096xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3097{
3098 xmlSchemaIDCStateObjPtr next;
3099 while (sto != NULL) {
3100 next = sto->next;
3101 if (sto->history != NULL)
3102 xmlFree(sto->history);
3103 if (sto->xpathCtxt != NULL)
3104 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3105 xmlFree(sto);
3106 sto = next;
3107 }
3108}
3109
3110/**
3111 * xmlSchemaFreeIDC:
3112 * @idc: a identity-constraint definition
3113 *
3114 * Deallocates an identity-constraint definition.
3115 */
3116static void
3117xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3118{
3119 xmlSchemaIDCSelectPtr cur, prev;
3120
3121 if (idcDef == NULL)
3122 return;
3123 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003124 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003125 /* Selector */
3126 if (idcDef->selector != NULL) {
3127 if (idcDef->selector->xpathComp != NULL)
3128 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3129 xmlFree(idcDef->selector);
3130 }
3131 /* Fields */
3132 if (idcDef->fields != NULL) {
3133 cur = idcDef->fields;
3134 do {
3135 prev = cur;
3136 cur = cur->next;
3137 if (prev->xpathComp != NULL)
3138 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003139 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003140 } while (cur != NULL);
3141 }
3142 xmlFree(idcDef);
3143}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003144
Daniel Veillard01fa6152004-06-29 17:04:39 +00003145/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003146 * xmlSchemaFreeElement:
3147 * @schema: a schema element structure
3148 *
3149 * Deallocate a Schema Element structure.
3150 */
3151static void
3152xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3153{
3154 if (elem == NULL)
3155 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003156 if (elem->annot != NULL)
3157 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003159 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003160 if (elem->defVal != NULL)
3161 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 xmlFree(elem);
3163}
3164
3165/**
3166 * xmlSchemaFreeFacet:
3167 * @facet: a schema facet structure
3168 *
3169 * Deallocate a Schema Facet structure.
3170 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003171void
Daniel Veillard4255d502002-04-16 15:50:10 +00003172xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3173{
3174 if (facet == NULL)
3175 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003176 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003177 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003178 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003179 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003180 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003181 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003182 xmlFree(facet);
3183}
3184
3185/**
3186 * xmlSchemaFreeType:
3187 * @type: a schema type structure
3188 *
3189 * Deallocate a Schema Type structure.
3190 */
3191void
3192xmlSchemaFreeType(xmlSchemaTypePtr type)
3193{
3194 if (type == NULL)
3195 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003196 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003197 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003199 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003200
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201 facet = type->facets;
3202 while (facet != NULL) {
3203 next = facet->next;
3204 xmlSchemaFreeFacet(facet);
3205 facet = next;
3206 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003207 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003208 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3209 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003210 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003211 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003212 if (type->memberTypes != NULL)
3213 xmlSchemaFreeTypeLinkList(type->memberTypes);
3214 if (type->facetSet != NULL) {
3215 xmlSchemaFacetLinkPtr next, link;
3216
3217 link = type->facetSet;
3218 do {
3219 next = link->next;
3220 xmlFree(link);
3221 link = next;
3222 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003223 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003224 if (type->contModel != NULL)
3225 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003226 xmlFree(type);
3227}
3228
3229/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003230 * xmlSchemaFreeModelGroupDef:
3231 * @item: a schema model group definition
3232 *
3233 * Deallocates a schema model group definition.
3234 */
3235static void
3236xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3237{
3238 if (item->annot != NULL)
3239 xmlSchemaFreeAnnot(item->annot);
3240 xmlFree(item);
3241}
3242
3243/**
3244 * xmlSchemaFreeModelGroup:
3245 * @item: a schema model group
3246 *
3247 * Deallocates a schema model group structure.
3248 */
3249static void
3250xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3251{
3252 if (item->annot != NULL)
3253 xmlSchemaFreeAnnot(item->annot);
3254 xmlFree(item);
3255}
3256
3257/**
3258 * xmlSchemaFreeParticle:
3259 * @type: a schema type structure
3260 *
3261 * Deallocate a Schema Type structure.
3262 */
3263static void
3264xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3265{
3266 if (item->annot != NULL)
3267 xmlSchemaFreeAnnot(item->annot);
3268 xmlFree(item);
3269}
3270
3271/**
3272 * xmlSchemaFreeMiscComponents:
3273 * @item: a schema component
3274 *
3275 * Deallocates misc. schema component structures.
3276 */
3277static void
3278xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3279{
3280 if (item == NULL)
3281 return;
3282 switch (item->type) {
3283 case XML_SCHEMA_TYPE_PARTICLE:
3284 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3285 return;
3286 case XML_SCHEMA_TYPE_SEQUENCE:
3287 case XML_SCHEMA_TYPE_CHOICE:
3288 case XML_SCHEMA_TYPE_ALL:
3289 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3290 return;
3291 case XML_SCHEMA_TYPE_ANY:
3292 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3293 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3294 break;
3295 default:
3296 /* TODO: This should never be hit. */
3297 TODO
3298 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003299 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003300}
3301
3302static void
3303xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3304{
3305 if (schema->volatiles == NULL)
3306 return;
3307 {
3308 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3309 xmlSchemaTreeItemPtr item;
3310 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003311
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003312 for (i = 0; i < list->nbItems; i++) {
3313 if (list->items[i] != NULL) {
3314 item = (xmlSchemaTreeItemPtr) list->items[i];
3315 switch (item->type) {
3316 case XML_SCHEMA_EXTRA_QNAMEREF:
3317 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3318 break;
3319 default:
3320 xmlSchemaFreeMiscComponents(item);
3321 }
3322 }
3323 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003324 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003325 }
3326}
3327/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003328 * xmlSchemaFreeTypeList:
3329 * @type: a schema type structure
3330 *
3331 * Deallocate a Schema Type structure.
3332 */
3333static void
3334xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3335{
3336 xmlSchemaTypePtr next;
3337
3338 while (type != NULL) {
3339 next = type->redef;
3340 xmlSchemaFreeType(type);
3341 type = next;
3342 }
3343}
3344
3345/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003346 * xmlSchemaFree:
3347 * @schema: a schema structure
3348 *
3349 * Deallocate a Schema structure.
3350 */
3351void
3352xmlSchemaFree(xmlSchemaPtr schema)
3353{
3354 if (schema == NULL)
3355 return;
3356
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003357 if (schema->volatiles != NULL)
3358 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003359 if (schema->notaDecl != NULL)
3360 xmlHashFree(schema->notaDecl,
3361 (xmlHashDeallocator) xmlSchemaFreeNotation);
3362 if (schema->attrDecl != NULL)
3363 xmlHashFree(schema->attrDecl,
3364 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3365 if (schema->attrgrpDecl != NULL)
3366 xmlHashFree(schema->attrgrpDecl,
3367 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3368 if (schema->elemDecl != NULL)
3369 xmlHashFree(schema->elemDecl,
3370 (xmlHashDeallocator) xmlSchemaFreeElement);
3371 if (schema->typeDecl != NULL)
3372 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003373 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003374 if (schema->groupDecl != NULL)
3375 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003376 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003377 if (schema->idcDef != NULL)
3378 xmlHashFree(schema->idcDef,
3379 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003380 if (schema->schemasImports != NULL)
3381 xmlHashFree(schema->schemasImports,
3382 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003383 if (schema->includes != NULL) {
3384 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3385 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003386 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003387 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003388 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003389 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003390 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003391 xmlFree(schema);
3392}
3393
3394/************************************************************************
3395 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003396 * Debug functions *
3397 * *
3398 ************************************************************************/
3399
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003400#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401
Daniel Veillard4255d502002-04-16 15:50:10 +00003402/**
3403 * xmlSchemaElementDump:
3404 * @elem: an element
3405 * @output: the file output
3406 *
3407 * Dump the element
3408 */
3409static void
3410xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003411 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003412 const xmlChar * namespace ATTRIBUTE_UNUSED,
3413 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003414{
3415 if (elem == NULL)
3416 return;
3417
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003418 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3419 fprintf(output, "Particle: %s", name);
3420 fprintf(output, ", term element: %s", elem->ref);
3421 if (elem->refNs != NULL)
3422 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003423 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003424 fprintf(output, "Element");
3425 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3426 fprintf(output, " (global)");
3427 fprintf(output, ": %s ", elem->name);
3428 if (namespace != NULL)
3429 fprintf(output, "ns %s", namespace);
3430 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003431 fprintf(output, "\n");
3432 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003433 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003434 if (elem->maxOccurs >= UNBOUNDED)
3435 fprintf(output, "max: unbounded\n");
3436 else if (elem->maxOccurs != 1)
3437 fprintf(output, "max: %d\n", elem->maxOccurs);
3438 else
3439 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003440 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003441 /*
3442 * Misc other properties.
3443 */
3444 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3445 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3446 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3447 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3448 (elem->id != NULL)) {
3449 fprintf(output, " props: ");
3450 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3451 fprintf(output, "[fixed] ");
3452 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3453 fprintf(output, "[default] ");
3454 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3455 fprintf(output, "[abstract] ");
3456 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3457 fprintf(output, "[nillable] ");
3458 if (elem->id != NULL)
3459 fprintf(output, "[id: '%s'] ", elem->id);
3460 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003461 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003462 /*
3463 * Default/fixed value.
3464 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003465 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003466 fprintf(output, " value: '%s'\n", elem->value);
3467 /*
3468 * Type.
3469 */
3470 if (elem->namedType != NULL) {
3471 fprintf(output, " type: %s ", elem->namedType);
3472 if (elem->namedTypeNs != NULL)
3473 fprintf(output, "ns %s\n", elem->namedTypeNs);
3474 else
3475 fprintf(output, "\n");
3476 }
3477 /*
3478 * Substitution group.
3479 */
3480 if (elem->substGroup != NULL) {
3481 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3482 if (elem->substGroupNs != NULL)
3483 fprintf(output, "ns %s\n", elem->substGroupNs);
3484 else
3485 fprintf(output, "\n");
3486 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003487}
3488
3489/**
3490 * xmlSchemaAnnotDump:
3491 * @output: the file output
3492 * @annot: a annotation
3493 *
3494 * Dump the annotation
3495 */
3496static void
3497xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3498{
3499 xmlChar *content;
3500
3501 if (annot == NULL)
3502 return;
3503
3504 content = xmlNodeGetContent(annot->content);
3505 if (content != NULL) {
3506 fprintf(output, " Annot: %s\n", content);
3507 xmlFree(content);
3508 } else
3509 fprintf(output, " Annot: empty\n");
3510}
3511
3512/**
3513 * xmlSchemaTypeDump:
3514 * @output: the file output
3515 * @type: a type structure
3516 *
3517 * Dump a SchemaType structure
3518 */
3519static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003520xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3521{
3522 xmlChar *str = NULL;
3523 xmlSchemaTreeItemPtr term;
3524 char shift[100];
3525 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003526
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003527 if (particle == NULL)
3528 return;
3529 for (i = 0;((i < depth) && (i < 25));i++)
3530 shift[2 * i] = shift[2 * i + 1] = ' ';
3531 shift[2 * i] = shift[2 * i + 1] = 0;
3532 fprintf(output, shift);
3533 if (particle->children == NULL) {
3534 fprintf(output, "MISSING particle term\n");
3535 return;
3536 }
3537 term = particle->children;
3538 switch (term->type) {
3539 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003540 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003541 ((xmlSchemaElementPtr)term)->targetNamespace,
3542 ((xmlSchemaElementPtr)term)->name));
3543 break;
3544 case XML_SCHEMA_TYPE_SEQUENCE:
3545 fprintf(output, "SEQUENCE");
3546 break;
3547 case XML_SCHEMA_TYPE_CHOICE:
3548 fprintf(output, "CHOICE");
3549 break;
3550 case XML_SCHEMA_TYPE_ALL:
3551 fprintf(output, "ALL");
3552 break;
3553 case XML_SCHEMA_TYPE_ANY:
3554 fprintf(output, "ANY");
3555 break;
3556 default:
3557 fprintf(output, "UNKNOWN\n");
3558 return;
3559 }
3560 if (particle->minOccurs != 1)
3561 fprintf(output, " min: %d", particle->minOccurs);
3562 if (particle->maxOccurs >= UNBOUNDED)
3563 fprintf(output, " max: unbounded");
3564 else if (particle->maxOccurs != 1)
3565 fprintf(output, " max: %d", particle->maxOccurs);
3566 fprintf(output, "\n");
3567 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3568 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3569 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3570 (term->children != NULL)) {
3571 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3572 output, depth +1);
3573 }
3574 if (particle->next != NULL)
3575 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3576 output, depth);
3577}
3578/**
3579 * xmlSchemaTypeDump:
3580 * @output: the file output
3581 * @type: a type structure
3582 *
3583 * Dump a SchemaType structure
3584 */
3585static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003586xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3587{
3588 if (type == NULL) {
3589 fprintf(output, "Type: NULL\n");
3590 return;
3591 }
3592 fprintf(output, "Type: ");
3593 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003594 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003595 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003596 fprintf(output, "no name ");
3597 if (type->targetNamespace != NULL)
3598 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 switch (type->type) {
3600 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003601 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 break;
3603 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003604 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003605 break;
3606 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003607 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003608 break;
3609 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003610 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 break;
3612 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003613 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 break;
3615 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 break;
3618 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003619 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 break;
3621 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003622 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 break;
3624 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003630 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003633 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003635 break;
3636 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003638 break;
3639 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 break;
3642 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003644 break;
3645 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003646 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 break;
3648 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 break;
3651 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 break;
3654 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003657 }
3658 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003659 if (type->base != NULL) {
3660 fprintf(output, " base type: %s", type->base);
3661 if (type->baseNs != NULL)
3662 fprintf(output, " ns %s\n", type->baseNs);
3663 else
3664 fprintf(output, "\n");
3665 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003666 if (type->annot != NULL)
3667 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003668#ifdef DUMP_CONTENT_MODEL
3669 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3670 (type->subtypes != NULL)) {
3671 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3672 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003674#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003675}
3676
3677/**
3678 * xmlSchemaDump:
3679 * @output: the file output
3680 * @schema: a schema structure
3681 *
3682 * Dump a Schema structure.
3683 */
3684void
3685xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3686{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003687 if (output == NULL)
3688 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003689 if (schema == NULL) {
3690 fprintf(output, "Schemas: NULL\n");
3691 return;
3692 }
3693 fprintf(output, "Schemas: ");
3694 if (schema->name != NULL)
3695 fprintf(output, "%s, ", schema->name);
3696 else
3697 fprintf(output, "no name, ");
3698 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003699 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003700 else
3701 fprintf(output, "no target namespace");
3702 fprintf(output, "\n");
3703 if (schema->annot != NULL)
3704 xmlSchemaAnnotDump(output, schema->annot);
3705
3706 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3707 output);
3708 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003710}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003711
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003712#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003713/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003714 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003715 * @vctxt: the WXS validation context
3716 *
3717 * Displays the current IDC table for debug purposes.
3718 */
3719static void
3720xmlSchemaDebugDumpIDCTable(FILE * output,
3721 const xmlChar *namespaceName,
3722 const xmlChar *localName,
3723 xmlSchemaPSVIIDCBindingPtr bind)
3724{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003725 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003726 xmlSchemaPSVIIDCNodePtr tab;
3727 xmlSchemaPSVIIDCKeyPtr key;
3728 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003729
3730 fprintf(output, "IDC: TABLES on %s\n",
3731 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003732 FREE_AND_NULL(str)
3733
3734 if (bind == NULL)
3735 return;
3736 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003737 fprintf(output, "IDC: BINDING %s\n",
3738 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003739 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003740 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003741 for (i = 0; i < bind->nbNodes; i++) {
3742 tab = bind->nodeTable[i];
3743 fprintf(output, " ( ");
3744 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003745 key = tab->keys[j];
3746 if ((key != NULL) && (key->val != NULL)) {
3747 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003748 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003749 fprintf(output, "\"%s\" ", value);
3750 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003751 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003753 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003754 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003755 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003756 else
3757 fprintf(output, "(key missing), ");
3758 }
3759 fprintf(output, ")\n");
3760 }
3761 bind = bind->next;
3762 } while (bind != NULL);
3763}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003764#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003765#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003766
3767/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003768 * *
3769 * Utilities *
3770 * *
3771 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003772
Daniel Veillardc0826a72004-08-10 14:17:33 +00003773/**
3774 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003775 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003776 * @name: the name of the attribute
3777 *
3778 * Seeks an attribute with a name of @name in
3779 * no namespace.
3780 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003781 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003782 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003783static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003784xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003785{
3786 xmlAttrPtr prop;
3787
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003788 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003789 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003790 prop = node->properties;
3791 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003792 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003793 return(prop);
3794 prop = prop->next;
3795 }
3796 return (NULL);
3797}
3798
3799/**
3800 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003801 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003802 * @uri: the uri
3803 * @name: the name of the attribute
3804 *
3805 * Seeks an attribute with a local name of @name and
3806 * a namespace URI of @uri.
3807 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003808 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003809 */
3810static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003811xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003812{
3813 xmlAttrPtr prop;
3814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003815 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003816 return(NULL);
3817 prop = node->properties;
3818 while (prop != NULL) {
3819 if ((prop->ns != NULL) &&
3820 xmlStrEqual(prop->name, BAD_CAST name) &&
3821 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003822 return(prop);
3823 prop = prop->next;
3824 }
3825 return (NULL);
3826}
3827
3828static const xmlChar *
3829xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3830{
3831 xmlChar *val;
3832 const xmlChar *ret;
3833
3834 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003835 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003836 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003837 ret = xmlDictLookup(ctxt->dict, val, -1);
3838 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003839 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003840}
3841
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003842/**
3843 * xmlSchemaGetProp:
3844 * @ctxt: the parser context
3845 * @node: the node
3846 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003847 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003848 * Read a attribute value and internalize the string
3849 *
3850 * Returns the string or NULL if not present.
3851 */
3852static const xmlChar *
3853xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3854 const char *name)
3855{
3856 xmlChar *val;
3857 const xmlChar *ret;
3858
3859 val = xmlGetProp(node, BAD_CAST name);
3860 if (val == NULL)
3861 return(NULL);
3862 ret = xmlDictLookup(ctxt->dict, val, -1);
3863 xmlFree(val);
3864 return(ret);
3865}
3866
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003867/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003868 * *
3869 * Parsing functions *
3870 * *
3871 ************************************************************************/
3872
3873/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003874 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003875 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003876 * @name: the element name
3877 * @ns: the element namespace
3878 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003879 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003880 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003881 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003882 */
3883static xmlSchemaElementPtr
3884xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003885 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886{
3887 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003888
3889 if ((name == NULL) || (schema == NULL))
3890 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003891
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003893 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003894 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003895 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003896 } else
3897 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003898 /*
3899 * This one was removed, since top level element declarations have
3900 * the target namespace specified in targetNamespace of the <schema>
3901 * information element, even if elementFormDefault is "unqualified".
3902 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903
William M. Bracke7091952004-05-11 15:09:58 +00003904 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003905 if (xmlStrEqual(namespace, schema->targetNamespace))
3906 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3907 else
3908 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003909 if ((ret != NULL) &&
3910 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003911 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003912 }
William M. Bracke7091952004-05-11 15:09:58 +00003913 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003914
William M. Brack2f2a6632004-08-20 23:09:47 +00003915 /*
3916 * Removed since imported components will be hold by the main schema only.
3917 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003918 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003919 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003920 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003921 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003922 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003923 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003924 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3925 return (ret);
3926 } else
3927 ret = NULL;
3928 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003929 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003930#ifdef DEBUG
3931 if (ret == NULL) {
3932 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003933 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003934 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003935 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003936 namespace);
3937 }
3938#endif
3939 return (ret);
3940}
3941
3942/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003943 * xmlSchemaGetType:
3944 * @schema: the schemas context
3945 * @name: the type name
3946 * @ns: the type namespace
3947 *
3948 * Lookup a type in the schemas or the predefined types
3949 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003950 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003951 */
3952static xmlSchemaTypePtr
3953xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003954 const xmlChar * namespace)
3955{
Daniel Veillard4255d502002-04-16 15:50:10 +00003956 xmlSchemaTypePtr ret;
3957
3958 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003959 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003960 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003961 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003962 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003963 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 }
3965 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003966 if (ret != NULL)
3967 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003968 /*
3969 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003970 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003971 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003972 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003973 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003974 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003975 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003976 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003977 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3978 return (ret);
3979 } else
3980 ret = NULL;
3981 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003982 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003983#ifdef DEBUG
3984 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003985 if (namespace == NULL)
3986 fprintf(stderr, "Unable to lookup type %s", name);
3987 else
3988 fprintf(stderr, "Unable to lookup type %s:%s", name,
3989 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003990 }
3991#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003992 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003993}
3994
Daniel Veillard3646d642004-06-02 19:19:14 +00003995/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003996 * xmlSchemaGetAttributeDecl:
3997 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00003998 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003999 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004000 *
4001 * Lookup a an attribute in the schema or imported schemas
4002 *
4003 * Returns the attribute declaration or NULL if not found.
4004 */
4005static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004006xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004007 const xmlChar * namespace)
4008{
4009 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004010
4011 if ((name == NULL) || (schema == NULL))
4012 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004013
4014
Daniel Veillard3646d642004-06-02 19:19:14 +00004015 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4016 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004017 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004018 else
4019 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004020 /*
4021 * Removed, since imported components will be hold by the main schema only.
4022 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004023 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004024 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004025 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004026 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004028 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004029 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4030 return (ret);
4031 } else
4032 ret = NULL;
4033 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004034 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004035#ifdef DEBUG
4036 if (ret == NULL) {
4037 if (namespace == NULL)
4038 fprintf(stderr, "Unable to lookup attribute %s", name);
4039 else
4040 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4041 namespace);
4042 }
4043#endif
4044 return (ret);
4045}
4046
4047/**
4048 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004049 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004050 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004051 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004052 *
4053 * Lookup a an attribute group in the schema or imported schemas
4054 *
4055 * Returns the attribute group definition or NULL if not found.
4056 */
4057static xmlSchemaAttributeGroupPtr
4058xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4059 const xmlChar * namespace)
4060{
4061 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004062
4063 if ((name == NULL) || (schema == NULL))
4064 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004065
4066
Daniel Veillard3646d642004-06-02 19:19:14 +00004067 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4068 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004069 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004070 else
4071 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004072 /*
4073 * Removed since imported components will be hold by the main schema only.
4074 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004075 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004076 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004077 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004078 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 if (import != NULL) {
4080 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4081 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4082 return (ret);
4083 else
4084 ret = NULL;
4085 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004086 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004087#ifdef DEBUG
4088 if (ret == NULL) {
4089 if (namespace == NULL)
4090 fprintf(stderr, "Unable to lookup attribute group %s", name);
4091 else
4092 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4093 namespace);
4094 }
4095#endif
4096 return (ret);
4097}
4098
4099/**
4100 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004101 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004102 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004103 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004104 *
4105 * Lookup a group in the schema or imported schemas
4106 *
4107 * Returns the group definition or NULL if not found.
4108 */
4109static xmlSchemaTypePtr
4110xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4111 const xmlChar * namespace)
4112{
4113 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004114
4115 if ((name == NULL) || (schema == NULL))
4116 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004117
Daniel Veillard3646d642004-06-02 19:19:14 +00004118 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004119 /*
4120 * Removed since imported components will be hold by the main schema only.
4121 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004122 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004123 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004124 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004125 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004126 if (import != NULL) {
4127 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4128 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4129 return (ret);
4130 else
4131 ret = NULL;
4132 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004133 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004134#ifdef DEBUG
4135 if (ret == NULL) {
4136 if (namespace == NULL)
4137 fprintf(stderr, "Unable to lookup group %s", name);
4138 else
4139 fprintf(stderr, "Unable to lookup group %s:%s", name,
4140 namespace);
4141 }
4142#endif
4143 return (ret);
4144}
4145
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004146/**
4147 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004148 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004149 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004150 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004151 *
4152 * Lookup a group in the schema or imported schemas
4153 *
4154 * Returns the group definition or NULL if not found.
4155 */
4156static xmlSchemaTreeItemPtr
4157xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4158 xmlSchemaTypeType itemType,
4159 const xmlChar *name,
4160 const xmlChar *targetNs)
4161{
4162 switch (itemType) {
4163 case XML_SCHEMA_TYPE_GROUP:
4164 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4165 name, targetNs));
4166 case XML_SCHEMA_TYPE_ELEMENT:
4167 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4168 name, targetNs));
4169 default:
4170 return (NULL);
4171 }
4172}
4173
Daniel Veillard4255d502002-04-16 15:50:10 +00004174/************************************************************************
4175 * *
4176 * Parsing functions *
4177 * *
4178 ************************************************************************/
4179
4180#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004181 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004182
4183/**
4184 * xmlSchemaIsBlank:
4185 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004186 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004187 *
4188 * Check if a string is ignorable
4189 *
4190 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4191 */
4192static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004194{
Daniel Veillard4255d502002-04-16 15:50:10 +00004195 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004196 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004197 if (len < 0) {
4198 while (*str != 0) {
4199 if (!(IS_BLANK_CH(*str)))
4200 return (0);
4201 str++;
4202 }
4203 } else while ((*str != 0) && (len != 0)) {
4204 if (!(IS_BLANK_CH(*str)))
4205 return (0);
4206 str++;
4207 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004208 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004209
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004210 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004211}
4212
4213/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004214 * xmlSchemaAddAssembledItem:
4215 * @ctxt: a schema parser context
4216 * @schema: the schema being built
4217 * @item: the item
4218 *
4219 * Add a item to the schema's list of current items.
4220 * This is used if the schema was already constructed and
4221 * new schemata need to be added to it.
4222 * *WARNING* this interface is highly subject to change.
4223 *
4224 * Returns 0 if suceeds and -1 if an internal error occurs.
4225 */
4226static int
4227xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4228 xmlSchemaTypePtr item)
4229{
4230 static int growSize = 100;
4231 xmlSchemaAssemblePtr ass;
4232
4233 ass = ctxt->assemble;
4234 if (ass->sizeItems < 0) {
4235 /* If disabled. */
4236 return (0);
4237 }
4238 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004239 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004240 if (ass->items == NULL) {
4241 xmlSchemaPErrMemory(ctxt,
4242 "allocating new item buffer", NULL);
4243 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004244 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004245 ass->sizeItems = growSize;
4246 } else if (ass->sizeItems <= ass->nbItems) {
4247 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004248 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004249 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4250 if (ass->items == NULL) {
4251 xmlSchemaPErrMemory(ctxt,
4252 "growing item buffer", NULL);
4253 ass->sizeItems = 0;
4254 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004255 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004256 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004257 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004258 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4259 return (0);
4260}
4261
4262/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004264 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004265 * @schema: the schema being built
4266 * @name: the item name
4267 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004268 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 * *WARNING* this interface is highly subject to change
4270 *
4271 * Returns the new struture or NULL in case of error
4272 */
4273static xmlSchemaNotationPtr
4274xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004275 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004276{
4277 xmlSchemaNotationPtr ret = NULL;
4278 int val;
4279
4280 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4281 return (NULL);
4282
4283 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004284 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 if (schema->notaDecl == NULL)
4286 return (NULL);
4287
4288 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4289 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004290 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 return (NULL);
4292 }
4293 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004294 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4296 ret);
4297 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004298 /*
4299 * TODO: This should never happen, since a unique name will be computed.
4300 * If it fails, then an other internal error must have occured.
4301 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4303 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004304 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004305 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004306 xmlFree(ret);
4307 return (NULL);
4308 }
4309 return (ret);
4310}
4311
4312
4313/**
4314 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004315 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004316 * @schema: the schema being built
4317 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004318 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004319 *
4320 * Add an XML schema Attrribute declaration
4321 * *WARNING* this interface is highly subject to change
4322 *
4323 * Returns the new struture or NULL in case of error
4324 */
4325static xmlSchemaAttributePtr
4326xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004327 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004328 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004329{
4330 xmlSchemaAttributePtr ret = NULL;
4331 int val;
4332
4333 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4334 return (NULL);
4335
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004336#ifdef DEBUG
4337 fprintf(stderr, "Adding attribute %s\n", name);
4338 if (namespace != NULL)
4339 fprintf(stderr, " target namespace %s\n", namespace);
4340#endif
4341
Daniel Veillard4255d502002-04-16 15:50:10 +00004342 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004343 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 if (schema->attrDecl == NULL)
4345 return (NULL);
4346
4347 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4348 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004349 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004350 return (NULL);
4351 }
4352 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004353 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004354 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004355 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004356 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004357 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004358 if (topLevel) {
4359 xmlSchemaPCustomErr(ctxt,
4360 XML_SCHEMAP_REDEFINED_ATTR,
4361 NULL, NULL, node,
4362 "A global attribute declaration with the name '%s' does "
4363 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004364 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004365 return (NULL);
4366 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004367 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004368 /*
4369 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4370 * in the scenario:
4371 * 1. multiple top-level complex types have different target
4372 * namespaces but have the SAME NAME; this can happen if
4373 * schemata are imported
4374 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004375 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004376 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004377 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004378 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004379 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004380 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004381
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004382 if (val != 0) {
4383 xmlSchemaPCustomErr(ctxt,
4384 XML_SCHEMAP_INTERNAL,
4385 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004386 "Internal error: xmlSchemaAddAttribute, "
4387 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004388 "could not be added to the hash.", name);
4389 xmlFree(ret);
4390 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004391 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004392 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004393 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004394 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004395 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 return (ret);
4397}
4398
4399/**
4400 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004401 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004402 * @schema: the schema being built
4403 * @name: the item name
4404 *
4405 * Add an XML schema Attrribute Group declaration
4406 *
4407 * Returns the new struture or NULL in case of error
4408 */
4409static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004410xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004411 xmlSchemaPtr schema, const xmlChar * name,
4412 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004413{
4414 xmlSchemaAttributeGroupPtr ret = NULL;
4415 int val;
4416
4417 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4418 return (NULL);
4419
4420 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004421 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004422 if (schema->attrgrpDecl == NULL)
4423 return (NULL);
4424
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004425 ret =
4426 (xmlSchemaAttributeGroupPtr)
4427 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004428 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004430 return (NULL);
4431 }
4432 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004433 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004436 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004437 xmlSchemaPCustomErr(ctxt,
4438 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4439 NULL, NULL, node,
4440 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004441 xmlFree(ret);
4442 return (NULL);
4443 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004444 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004445 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 return (ret);
4447}
4448
4449/**
4450 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004451 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 * @schema: the schema being built
4453 * @name: the type name
4454 * @namespace: the type namespace
4455 *
4456 * Add an XML schema Element declaration
4457 * *WARNING* this interface is highly subject to change
4458 *
4459 * Returns the new struture or NULL in case of error
4460 */
4461static xmlSchemaElementPtr
4462xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004463 const xmlChar * name, const xmlChar * namespace,
4464 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004465{
4466 xmlSchemaElementPtr ret = NULL;
4467 int val;
4468
4469 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4470 return (NULL);
4471
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004472#ifdef DEBUG
4473 fprintf(stderr, "Adding element %s\n", name);
4474 if (namespace != NULL)
4475 fprintf(stderr, " target namespace %s\n", namespace);
4476#endif
4477
Daniel Veillard4255d502002-04-16 15:50:10 +00004478 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004479 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004480 if (schema->elemDecl == NULL)
4481 return (NULL);
4482
4483 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4484 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004485 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004486 return (NULL);
4487 }
4488 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004489 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004491 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004493 if (topLevel) {
4494 xmlSchemaPCustomErr(ctxt,
4495 XML_SCHEMAP_REDEFINED_ELEMENT,
4496 NULL, NULL, node,
4497 "A global element declaration with the name '%s' does "
4498 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004499 xmlFree(ret);
4500 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004501 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004502 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004503
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004504 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004505 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004506 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004507 if (val != 0) {
4508 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004509 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004510 NULL, NULL, node,
4511 "Internal error: xmlSchemaAddElement, "
4512 "a dublicate element declaration with the name '%s' "
4513 "could not be added to the hash.", name);
4514 xmlFree(ret);
4515 return (NULL);
4516 }
4517 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004518
Daniel Veillard4255d502002-04-16 15:50:10 +00004519 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004520 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004521 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004522 return (ret);
4523}
4524
4525/**
4526 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004527 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004528 * @schema: the schema being built
4529 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004530 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004532 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 * *WARNING* this interface is highly subject to change
4534 *
4535 * Returns the new struture or NULL in case of error
4536 */
4537static xmlSchemaTypePtr
4538xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004539 const xmlChar * name, const xmlChar * namespace,
4540 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004541{
4542 xmlSchemaTypePtr ret = NULL;
4543 int val;
4544
4545 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4546 return (NULL);
4547
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004548#ifdef DEBUG
4549 fprintf(stderr, "Adding type %s\n", name);
4550 if (namespace != NULL)
4551 fprintf(stderr, " target namespace %s\n", namespace);
4552#endif
4553
Daniel Veillard4255d502002-04-16 15:50:10 +00004554 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004555 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004556 if (schema->typeDecl == NULL)
4557 return (NULL);
4558
4559 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4560 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004561 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004562 return (NULL);
4563 }
4564 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004565 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004566 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004567 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004568 if (val != 0) {
4569 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004570 xmlSchemaPCustomErr(ctxt,
4571 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004572 NULL, NULL, node,
4573 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004574 xmlFree(ret);
4575 return (NULL);
4576 } else {
4577 xmlSchemaTypePtr prev;
4578
4579 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4580 if (prev == NULL) {
4581 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004582 XML_ERR_INTERNAL_ERROR,
4583 "Internal error: xmlSchemaAddType, on type "
4584 "'%s'.\n",
4585 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004586 xmlFree(ret);
4587 return (NULL);
4588 }
4589 ret->redef = prev->redef;
4590 prev->redef = ret;
4591 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004592 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004593 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004594 ret->minOccurs = 1;
4595 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004596 ret->attributeUses = NULL;
4597 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004598 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004599 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004600 return (ret);
4601}
4602
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004603static xmlSchemaQNameRefPtr
4604xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4605 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004606 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004607 const xmlChar *refNs)
4608{
4609 xmlSchemaQNameRefPtr ret;
4610
4611 ret = (xmlSchemaQNameRefPtr)
4612 xmlMalloc(sizeof(xmlSchemaQNameRef));
4613 if (ret == NULL) {
4614 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4615 NULL);
4616 return (NULL);
4617 }
4618 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4619 ret->name = refName;
4620 ret->targetNamespace = refNs;
4621 ret->item = NULL;
4622 ret->itemType = refType;
4623 /*
4624 * Store the reference item in the schema.
4625 */
4626 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4627 return (ret);
4628}
4629
4630/**
4631 * xmlSchemaAddModelGroup:
4632 * @ctxt: a schema parser context
4633 * @schema: the schema being built
4634 * @type: the "compositor" type of the model group
4635 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004636 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004637 *
4638 * Adds a schema model group
4639 * *WARNING* this interface is highly subject to change
4640 *
4641 * Returns the new struture or NULL in case of error
4642 */
4643static xmlSchemaModelGroupPtr
4644xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4645 xmlSchemaTypeType type, const xmlChar **container,
4646 xmlNodePtr node)
4647{
4648 xmlSchemaModelGroupPtr ret = NULL;
4649 xmlChar buf[30];
4650
4651 if ((ctxt == NULL) || (schema == NULL))
4652 return (NULL);
4653
4654#ifdef DEBUG
4655 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004656#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004657 ret = (xmlSchemaModelGroupPtr)
4658 xmlMalloc(sizeof(xmlSchemaModelGroup));
4659 if (ret == NULL) {
4660 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4661 NULL);
4662 return (NULL);
4663 }
4664 ret->type = type;
4665 ret->annot = NULL;
4666 ret->node = node;
4667 ret->children = NULL;
4668 ret->next = NULL;
4669 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4670 if (container != NULL)
4671 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4672 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004673 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004674 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4675 } else {
4676 if (container != NULL)
4677 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4678 }
4679 if (container != NULL)
4680 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4681 /*
4682 * Add to volatile items.
4683 * TODO: this should be changed someday.
4684 */
4685 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4686 xmlFree(ret);
4687 return (NULL);
4688 }
4689 return (ret);
4690}
4691
4692
4693/**
4694 * xmlSchemaAddParticle:
4695 * @ctxt: a schema parser context
4696 * @schema: the schema being built
4697 * @node: the corresponding node in the schema doc
4698 * @min: the minOccurs
4699 * @max: the maxOccurs
4700 *
4701 * Adds an XML schema particle component.
4702 * *WARNING* this interface is highly subject to change
4703 *
4704 * Returns the new struture or NULL in case of error
4705 */
4706static xmlSchemaParticlePtr
4707xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4708 xmlNodePtr node, int min, int max)
4709{
4710 xmlSchemaParticlePtr ret = NULL;
4711 if ((ctxt == NULL) || (schema == NULL))
4712 return (NULL);
4713
4714#ifdef DEBUG
4715 fprintf(stderr, "Adding particle component\n");
4716#endif
4717 ret = (xmlSchemaParticlePtr)
4718 xmlMalloc(sizeof(xmlSchemaParticle));
4719 if (ret == NULL) {
4720 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4721 NULL);
4722 return (NULL);
4723 }
4724 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4725 ret->annot = NULL;
4726 ret->node = node;
4727 ret->minOccurs = min;
4728 ret->maxOccurs = max;
4729 ret->next = NULL;
4730 ret->children = NULL;
4731
4732 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4733 xmlFree(ret);
4734 return (NULL);
4735 }
4736 return (ret);
4737}
4738
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004739/**
4740 * xmlSchemaAddGroup:
4741 * @ctxt: a schema validation context
4742 * @schema: the schema being built
4743 * @name: the group name
4744 *
4745 * Add an XML schema Group definition
4746 *
4747 * Returns the new struture or NULL in case of error
4748 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004749static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004750xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004751 const xmlChar *name, const xmlChar *namespaceName,
4752 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004753{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004754 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004755 int val;
4756
4757 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4758 return (NULL);
4759
4760 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004761 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004762 if (schema->groupDecl == NULL)
4763 return (NULL);
4764
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004765 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004766 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004767 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004768 return (NULL);
4769 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004770 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004771 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004772 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004773 ret->node = node;
4774 ret->targetNamespace = namespaceName;
4775 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004776 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004777 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004778 XML_SCHEMAP_REDEFINED_GROUP,
4779 NULL, NULL, node,
4780 "A global model group definition with the name '%s' does already "
4781 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004782 xmlFree(ret);
4783 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004784 }
4785 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004786 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004787 return (ret);
4788}
4789
Daniel Veillard3646d642004-06-02 19:19:14 +00004790/**
4791 * xmlSchemaNewWildcardNs:
4792 * @ctxt: a schema validation context
4793 *
4794 * Creates a new wildcard namespace constraint.
4795 *
4796 * Returns the new struture or NULL in case of error
4797 */
4798static xmlSchemaWildcardNsPtr
4799xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4800{
4801 xmlSchemaWildcardNsPtr ret;
4802
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004803 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004804 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4805 if (ret == NULL) {
4806 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004807 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004808 }
4809 ret->value = NULL;
4810 ret->next = NULL;
4811 return (ret);
4812}
4813
4814/**
4815 * xmlSchemaAddWildcard:
4816 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004817 * @schema: a schema
4818 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004819 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004820 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004821 *
4822 * Returns the new struture or NULL in case of error
4823 */
4824static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004825xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4826 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004827{
4828 xmlSchemaWildcardPtr ret = NULL;
4829
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004830 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004831 return (NULL);
4832
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004833#ifdef DEBUG
4834 fprintf(stderr, "Adding wildcard component\n");
4835#endif
4836
Daniel Veillard3646d642004-06-02 19:19:14 +00004837 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4838 if (ret == NULL) {
4839 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4840 return (NULL);
4841 }
4842 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004843 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004844 ret->minOccurs = 1;
4845 ret->maxOccurs = 1;
4846
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4848 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4849 "Failed to add a wildcard component to the list", NULL);
4850 xmlFree(ret);
4851 return (NULL);
4852 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004853 return (ret);
4854}
4855
Daniel Veillard4255d502002-04-16 15:50:10 +00004856/************************************************************************
4857 * *
4858 * Utilities for parsing *
4859 * *
4860 ************************************************************************/
4861
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004862#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004863/**
4864 * xmlGetQNameProp:
4865 * @ctxt: a schema validation context
4866 * @node: a subtree containing XML Schema informations
4867 * @name: the attribute name
4868 * @namespace: the result namespace if any
4869 *
4870 * Extract a QName Attribute value
4871 *
4872 * Returns the NCName or NULL if not found, and also update @namespace
4873 * with the namespace URI
4874 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004875static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004876xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004877 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004878{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004879 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004880 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004881 const xmlChar *ret, *prefix;
4882 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004883 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004884
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004885 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004886 attr = xmlSchemaGetPropNode(node, name);
4887 if (attr == NULL)
4888 return (NULL);
4889 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004890
Daniel Veillard4255d502002-04-16 15:50:10 +00004891 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004892 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004893
Daniel Veillardba0153a2004-04-01 10:42:31 +00004894 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004895 ns = xmlSearchNs(node->doc, node, 0);
4896 if (ns) {
4897 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4898 return (val);
4899 }
4900 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004901 ret = xmlSplitQName3(val, &len);
4902 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004903 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004904 }
4905 ret = xmlDictLookup(ctxt->dict, ret, -1);
4906 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004907
4908 ns = xmlSearchNs(node->doc, node, prefix);
4909 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004910 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4911 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004912 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004913 "The QName value '%s' has no corresponding namespace "
4914 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004915 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004916 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004917 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004918 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004920#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004921
4922/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004923 * xmlSchemaPValAttrNodeQNameValue:
4924 * @ctxt: a schema parser context
4925 * @schema: the schema context
4926 * @ownerDes: the designation of the parent element
4927 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004928 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004929 * @local: the resulting local part if found, the attribute value otherwise
4930 * @uri: the resulting namespace URI if found
4931 *
4932 * Extracts the local name and the URI of a QName value and validates it.
4933 * This one is intended to be used on attribute values that
4934 * should resolve to schema components.
4935 *
4936 * Returns 0, in case the QName is valid, a positive error code
4937 * if not valid and -1 if an internal error occurs.
4938 */
4939static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004940xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004941 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004942 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004943 xmlSchemaTypePtr ownerItem,
4944 xmlAttrPtr attr,
4945 const xmlChar *value,
4946 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004947 const xmlChar **local)
4948{
4949 const xmlChar *pref;
4950 xmlNsPtr ns;
4951 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004952
Daniel Veillardc0826a72004-08-10 14:17:33 +00004953 *uri = NULL;
4954 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004955 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004956 if (ret > 0) {
4957 xmlSchemaPSimpleTypeErr(ctxt,
4958 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4959 ownerItem, (xmlNodePtr) attr,
4960 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4961 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004962 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004963 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004964 } else if (ret < 0)
4965 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004966
4967 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004968 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4969 if (ns)
4970 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4971 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4972 /*
4973 * This one takes care of included schemas with no
4974 * target namespace.
4975 */
4976 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004977 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004978 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004979 return (0);
4980 }
4981 /*
4982 * At this point xmlSplitQName3 has to return a local name.
4983 */
4984 *local = xmlSplitQName3(value, &len);
4985 *local = xmlDictLookup(ctxt->dict, *local, -1);
4986 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004987 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4988 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004989 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004990 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004991 ownerItem, (xmlNodePtr) attr,
4992 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
4993 "The value '%s' of simple type 'xs:QName' has no "
4994 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004995 return (ctxt->err);
4996 } else {
4997 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004998 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 return (0);
5000}
5001
5002/**
5003 * xmlSchemaPValAttrNodeQName:
5004 * @ctxt: a schema parser context
5005 * @schema: the schema context
5006 * @ownerDes: the designation of the owner element
5007 * @ownerItem: the owner as a schema object
5008 * @attr: the attribute node
5009 * @local: the resulting local part if found, the attribute value otherwise
5010 * @uri: the resulting namespace URI if found
5011 *
5012 * Extracts and validates the QName of an attribute value.
5013 * This one is intended to be used on attribute values that
5014 * should resolve to schema components.
5015 *
5016 * Returns 0, in case the QName is valid, a positive error code
5017 * if not valid and -1 if an internal error occurs.
5018 */
5019static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005020xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 xmlSchemaPtr schema,
5022 xmlChar **ownerDes,
5023 xmlSchemaTypePtr ownerItem,
5024 xmlAttrPtr attr,
5025 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005026 const xmlChar **local)
5027{
5028 const xmlChar *value;
5029
5030 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005031 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5032 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005033}
5034
5035/**
5036 * xmlSchemaPValAttrQName:
5037 * @ctxt: a schema parser context
5038 * @schema: the schema context
5039 * @ownerDes: the designation of the parent element
5040 * @ownerItem: the owner as a schema object
5041 * @ownerElem: the parent node of the attribute
5042 * @name: the name of the attribute
5043 * @local: the resulting local part if found, the attribute value otherwise
5044 * @uri: the resulting namespace URI if found
5045 *
5046 * Extracts and validates the QName of an attribute value.
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
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005052xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5053 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005054 xmlChar **ownerDes,
5055 xmlSchemaTypePtr ownerItem,
5056 xmlNodePtr ownerElem,
5057 const char *name,
5058 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005059 const xmlChar **local)
5060{
5061 xmlAttrPtr attr;
5062
5063 attr = xmlSchemaGetPropNode(ownerElem, name);
5064 if (attr == NULL) {
5065 *local = NULL;
5066 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005067 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005069 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5070 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071}
5072
5073/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005074 * xmlSchemaPValAttrID:
5075 * @ctxt: a schema parser context
5076 * @schema: the schema context
5077 * @ownerDes: the designation of the parent element
5078 * @ownerItem: the owner as a schema object
5079 * @ownerElem: the parent node of the attribute
5080 * @name: the name of the attribute
5081 *
5082 * Extracts and validates the ID of an attribute value.
5083 *
5084 * Returns 0, in case the ID is valid, a positive error code
5085 * if not valid and -1 if an internal error occurs.
5086 */
5087static int
5088xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005089 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005090 xmlSchemaTypePtr ownerItem,
5091 xmlNodePtr ownerElem,
5092 const xmlChar *name)
5093{
5094 int ret;
5095 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005096 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005097
5098 value = xmlGetNoNsProp(ownerElem, name);
5099 if (value == NULL)
5100 return (0);
5101
5102 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5103 if (attr == NULL)
5104 return (-1);
5105
5106 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005107 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005108 /*
5109 * NOTE: the IDness might have already be declared in the DTD
5110 */
5111 if (attr->atype != XML_ATTRIBUTE_ID) {
5112 xmlIDPtr res;
5113 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005114
5115 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005116 * TODO: Use xmlSchemaStrip here; it's not exported at this
5117 * moment.
5118 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005119 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005121 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005122 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5123 if (res == NULL) {
5124 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005125 xmlSchemaPSimpleTypeErr(ctxt,
5126 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5127 ownerItem, (xmlNodePtr) attr,
5128 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5129 NULL, NULL, "Duplicate value '%s' of simple "
5130 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005131 } else
5132 attr->atype = XML_ATTRIBUTE_ID;
5133 if (strip != NULL)
5134 xmlFree(strip);
5135 }
5136 } else if (ret > 0) {
5137 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005138 xmlSchemaPSimpleTypeErr(ctxt,
5139 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5140 ownerItem, (xmlNodePtr) attr,
5141 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5142 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5143 "not a valid 'xs:NCName'",
5144 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005145 }
5146 xmlFree(value);
5147
5148 return (ret);
5149}
5150
5151/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005152 * xmlGetMaxOccurs:
5153 * @ctxt: a schema validation context
5154 * @node: a subtree containing XML Schema informations
5155 *
5156 * Get the maxOccurs property
5157 *
5158 * Returns the default if not found, or the value
5159 */
5160static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005161xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5162 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005163{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005164 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005165 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005166 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005167
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005168 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5169 if (attr == NULL)
5170 return (def);
5171 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005172
5173 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005174 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005175 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005176 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5177 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005178 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005179 val, NULL, NULL, NULL);
5180 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005181 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005182 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005183 }
5184
5185 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005186 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005189 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005190 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5191 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005192 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005193 val, NULL, NULL, NULL);
5194 return (def);
5195 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005196 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005197 ret = ret * 10 + (*cur - '0');
5198 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005199 }
William M. Brack76e95df2003-10-18 16:20:14 +00005200 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005201 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005202 /*
5203 * TODO: Restrict the maximal value to Integer.
5204 */
5205 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005206 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005207 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5208 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005209 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005210 val, NULL, NULL, NULL);
5211 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005212 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005214}
5215
5216/**
5217 * xmlGetMinOccurs:
5218 * @ctxt: a schema validation context
5219 * @node: a subtree containing XML Schema informations
5220 *
5221 * Get the minOccurs property
5222 *
5223 * Returns the default if not found, or the value
5224 */
5225static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005226xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005227 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005228{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005229 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005230 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005231 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005232
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005233 attr = xmlSchemaGetPropNode(node, "minOccurs");
5234 if (attr == NULL)
5235 return (def);
5236 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005238 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005239 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005240 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005241 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005242 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5243 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005244 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 val, NULL, NULL, NULL);
5246 return (def);
5247 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005248 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005249 ret = ret * 10 + (*cur - '0');
5250 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 }
William M. Brack76e95df2003-10-18 16:20:14 +00005252 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005253 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005254 /*
5255 * TODO: Restrict the maximal value to Integer.
5256 */
5257 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005258 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005259 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5260 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005261 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005262 val, NULL, NULL, NULL);
5263 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005264 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005266}
5267
5268/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005269 * xmlSchemaPGetBoolNodeValue:
5270 * @ctxt: a schema validation context
5271 * @ownerDes: owner designation
5272 * @ownerItem: the owner as a schema item
5273 * @node: the node holding the value
5274 *
5275 * Converts a boolean string value into 1 or 0.
5276 *
5277 * Returns 0 or 1.
5278 */
5279static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005280xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5281 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005282 xmlSchemaTypePtr ownerItem,
5283 xmlNodePtr node)
5284{
5285 xmlChar *value = NULL;
5286 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005287
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005288 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005289 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005290 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005291 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005292 * can have the following legal literals {true, false, 1, 0}.
5293 */
5294 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5295 res = 1;
5296 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5297 res = 0;
5298 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5299 res = 1;
5300 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005301 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005302 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005303 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005305 ownerItem, node,
5306 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5307 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005308 NULL, NULL, NULL);
5309 }
5310 if (value != NULL)
5311 xmlFree(value);
5312 return (res);
5313}
5314
5315/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005316 * xmlGetBooleanProp:
5317 * @ctxt: a schema validation context
5318 * @node: a subtree containing XML Schema informations
5319 * @name: the attribute name
5320 * @def: the default value
5321 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005322 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005323 *
5324 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005325 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005326 */
5327static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005328xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5329 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005330 xmlSchemaTypePtr ownerItem,
5331 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005332 const char *name, int def)
5333{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005334 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005335
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005336 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005337 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005338 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005339 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005340 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005341 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005342 * can have the following legal literals {true, false, 1, 0}.
5343 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 if (xmlStrEqual(val, BAD_CAST "true"))
5345 def = 1;
5346 else if (xmlStrEqual(val, BAD_CAST "false"))
5347 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005348 else if (xmlStrEqual(val, BAD_CAST "1"))
5349 def = 1;
5350 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005351 def = 0;
5352 else {
5353 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005355 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005356 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005357 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5358 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005361}
5362
5363/************************************************************************
5364 * *
5365 * Shema extraction from an Infoset *
5366 * *
5367 ************************************************************************/
5368static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5369 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005370 xmlNodePtr node,
5371 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5373 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005374 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005375 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005376 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005377static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5378 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005379 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005380 xmlNodePtr node,
5381 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005382static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5383 ctxt,
5384 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005385 xmlNodePtr node,
5386 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005387static xmlSchemaAttributeGroupPtr
5388xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005389 xmlSchemaPtr schema, xmlNodePtr node,
5390 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005391static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5392 xmlSchemaPtr schema,
5393 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005394static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005395xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5396 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005397
5398/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005399 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005400 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005401 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005402 * @ownerDes: the designation of the parent element
5403 * @ownerItem: the schema object owner if existent
5404 * @attr: the schema attribute node being validated
5405 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005406 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005407 *
5408 * Validates a value against the given built-in type.
5409 * This one is intended to be used internally for validation
5410 * of schema attribute values during parsing of the schema.
5411 *
5412 * Returns 0 if the value is valid, a positive error code
5413 * number otherwise and -1 in case of an internal or API error.
5414 */
5415static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005416xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5417 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5418 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005419 xmlAttrPtr attr,
5420 const xmlChar *value,
5421 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005422{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005423
5424 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005425
5426 /*
5427 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5428 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005429 */
5430 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005431 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005432 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5433 PERROR_INT("xmlSchemaPValAttrNodeValue",
5434 "the given type is not a built-in type");
5435 return (-1);
5436 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005437 switch (type->builtInType) {
5438 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005439 case XML_SCHEMAS_QNAME:
5440 case XML_SCHEMAS_ANYURI:
5441 case XML_SCHEMAS_TOKEN:
5442 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005443 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5444 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005445 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005446 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005447 PERROR_INT("xmlSchemaPValAttrNodeValue",
5448 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005449 return (-1);
5450 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005451 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005452 /*
5453 * TODO: Should we use the S4S error codes instead?
5454 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005455 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005456 PERROR_INT("xmlSchemaPValAttrNodeValue",
5457 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005458 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 } else if (ret > 0) {
5460 if (VARIETY_LIST(type))
5461 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5462 else
5463 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5464 xmlSchemaPSimpleTypeErr(pctxt,
5465 ret, ownerItem, (xmlNodePtr) attr,
5466 type, NULL, value, NULL, NULL, NULL);
5467 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005468 return (ret);
5469}
5470
5471/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005472 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005473 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005474 * @ctxt: a schema parser context
5475 * @ownerDes: the designation of the parent element
5476 * @ownerItem: the schema object owner if existent
5477 * @attr: the schema attribute node being validated
5478 * @type: the built-in type to be validated against
5479 * @value: the resulting value if any
5480 *
5481 * Extracts and validates a value against the given built-in type.
5482 * This one is intended to be used internally for validation
5483 * of schema attribute values during parsing of the schema.
5484 *
5485 * Returns 0 if the value is valid, a positive error code
5486 * number otherwise and -1 in case of an internal or API error.
5487 */
5488static int
5489xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5490 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005491 xmlSchemaTypePtr ownerItem,
5492 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005493 xmlSchemaTypePtr type,
5494 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 const xmlChar *val;
5497
5498 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005499 return (-1);
5500
Daniel Veillardc0826a72004-08-10 14:17:33 +00005501 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5502 if (value != NULL)
5503 *value = val;
5504
5505 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005506 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005507}
5508
5509/**
5510 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005512 * @ctxt: a schema parser context
5513 * @node: the element node of the attribute
5514 * @ownerDes: the designation of the parent element
5515 * @ownerItem: the schema object owner if existent
5516 * @ownerElem: the owner element node
5517 * @name: the name of the schema attribute node
5518 * @type: the built-in type to be validated against
5519 * @value: the resulting value if any
5520 *
5521 * Extracts and validates a value against the given built-in type.
5522 * This one is intended to be used internally for validation
5523 * of schema attribute values during parsing of the schema.
5524 *
5525 * Returns 0 if the value is valid, a positive error code
5526 * number otherwise and -1 in case of an internal or API error.
5527 */
5528static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005529xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005530 xmlChar **ownerDes,
5531 xmlSchemaTypePtr ownerItem,
5532 xmlNodePtr ownerElem,
5533 const char *name,
5534 xmlSchemaTypePtr type,
5535 const xmlChar **value)
5536{
5537 xmlAttrPtr attr;
5538
5539 if ((ctxt == NULL) || (type == NULL)) {
5540 if (value != NULL)
5541 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005542 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005543 }
5544 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5545 if (value != NULL)
5546 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005547 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005548 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005549 "Internal error: xmlSchemaPValAttr, the given "
5550 "type '%s' is not a built-in type.\n",
5551 type->name, NULL);
5552 return (-1);
5553 }
5554 attr = xmlSchemaGetPropNode(ownerElem, name);
5555 if (attr == NULL) {
5556 if (value != NULL)
5557 *value = NULL;
5558 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 }
5560 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 type, value));
5562}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005563
5564static int
5565xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5566 xmlSchemaPtr schema,
5567 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005568 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005569 const xmlChar *namespaceName)
5570{
5571 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005572 return (1);
5573 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5574 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005575 if (pctxt->localImports != NULL) {
5576 int i;
5577 for (i = 0; i < pctxt->nbLocalImports; i++)
5578 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5579 return (1);
5580 }
5581 if (namespaceName == NULL)
5582 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005583 NULL, (xmlSchemaTypePtr) item, node,
5584 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005585 "namespace are not valid, since not indicated by an import "
5586 "statement", NULL);
5587 else
5588 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005589 NULL, (xmlSchemaTypePtr) item, node,
5590 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005591 "namespace '%s' are not valid, since not indicated by an import "
5592 "statement", namespaceName);
5593 return (0);
5594}
5595
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005597 * xmlSchemaParseAttrDecls:
5598 * @ctxt: a schema validation context
5599 * @schema: the schema being built
5600 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005601 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005602 *
5603 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005604 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005605 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5606 */
5607static xmlNodePtr
5608xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5609 xmlNodePtr child, xmlSchemaTypePtr type)
5610{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005611 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005612
Daniel Veillard4255d502002-04-16 15:50:10 +00005613 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005614 (IS_SCHEMA(child, "attributeGroup"))) {
5615 attr = NULL;
5616 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005617 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005618 } else if (IS_SCHEMA(child, "attributeGroup")) {
5619 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005620 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 }
5622 if (attr != NULL) {
5623 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005624 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5625 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5626 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005627 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005628 lastattr = attr;
5629 } else {
5630 lastattr->next = attr;
5631 lastattr = attr;
5632 }
5633 }
5634 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005635 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005636 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005637}
5638
5639/**
5640 * xmlSchemaParseAnnotation:
5641 * @ctxt: a schema validation context
5642 * @schema: the schema being built
5643 * @node: a subtree containing XML Schema informations
5644 *
5645 * parse a XML schema Attrribute declaration
5646 * *WARNING* this interface is highly subject to change
5647 *
William M. Bracke7091952004-05-11 15:09:58 +00005648 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005649 * 1 in case of success.
5650 */
5651static xmlSchemaAnnotPtr
5652xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5653 xmlNodePtr node)
5654{
5655 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005656 xmlNodePtr child = NULL;
5657 xmlAttrPtr attr;
5658 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005659
Daniel Veillardc0826a72004-08-10 14:17:33 +00005660 /*
5661 * INFO: S4S completed.
5662 */
5663 /*
5664 * id = ID
5665 * {any attributes with non-schema namespace . . .}>
5666 * Content: (appinfo | documentation)*
5667 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5669 return (NULL);
5670 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005671 attr = node->properties;
5672 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005673 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005674 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005675 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005676 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005677
5678 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5680 NULL, NULL, attr);
5681 }
5682 attr = attr->next;
5683 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005684 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005685 /*
5686 * And now for the children...
5687 */
5688 child = node->children;
5689 while (child != NULL) {
5690 if (IS_SCHEMA(child, "appinfo")) {
5691 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005692 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005693 * source = anyURI
5694 * {any attributes with non-schema namespace . . .}>
5695 * Content: ({any})*
5696 */
5697 attr = child->properties;
5698 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005699 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005700 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005701 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005702 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005703
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005704 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5706 NULL, NULL, attr);
5707 }
5708 attr = attr->next;
5709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005710 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5711 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 child = child->next;
5713 } else if (IS_SCHEMA(child, "documentation")) {
5714 /* TODO: make available the content of "documentation". */
5715 /*
5716 * source = anyURI
5717 * {any attributes with non-schema namespace . . .}>
5718 * Content: ({any})*
5719 */
5720 attr = child->properties;
5721 while (attr != NULL) {
5722 if (attr->ns == NULL) {
5723 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005724 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005725 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5726 NULL, NULL, attr);
5727 }
5728 } else {
5729 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5730 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5731 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005732
5733 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5735 NULL, NULL, attr);
5736 }
5737 }
5738 attr = attr->next;
5739 }
5740 /*
5741 * Attribute "xml:lang".
5742 */
5743 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5744 if (attr != NULL)
5745 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 child = child->next;
5748 } else {
5749 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005750 xmlSchemaPContentErr(ctxt,
5751 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005752 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5753 barked = 1;
5754 child = child->next;
5755 }
5756 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005757
Daniel Veillard4255d502002-04-16 15:50:10 +00005758 return (ret);
5759}
5760
5761/**
5762 * xmlSchemaParseFacet:
5763 * @ctxt: a schema validation context
5764 * @schema: the schema being built
5765 * @node: a subtree containing XML Schema informations
5766 *
5767 * parse a XML schema Facet declaration
5768 * *WARNING* this interface is highly subject to change
5769 *
5770 * Returns the new type structure or NULL in case of error
5771 */
5772static xmlSchemaFacetPtr
5773xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005774 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005775{
5776 xmlSchemaFacetPtr facet;
5777 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005778 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005779
5780 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5781 return (NULL);
5782
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005783 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 if (facet == NULL) {
5785 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5786 return (NULL);
5787 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005788 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005789 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005790 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005791 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5792 "Facet %s has no value\n", node->name, NULL);
5793 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005794 return (NULL);
5795 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005797 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005798 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005799 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005800 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005801 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005802 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005803 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005805 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5818 } else if (IS_SCHEMA(node, "minLength")) {
5819 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5820 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005821 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5822 "Unknown facet type %s\n", node->name, NULL);
5823 xmlSchemaFreeFacet(facet);
5824 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005826 xmlSchemaPValAttrID(ctxt, NULL,
5827 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005828 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005829 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5830 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5831 const xmlChar *fixed;
5832
5833 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5834 if (fixed != NULL) {
5835 if (xmlStrEqual(fixed, BAD_CAST "true"))
5836 facet->fixed = 1;
5837 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005838 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005839 child = node->children;
5840
5841 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005842 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5843 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005844 }
5845 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5847 "Facet %s has unexpected child content\n",
5848 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005849 }
5850 return (facet);
5851}
5852
5853/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005854 * xmlSchemaParseWildcardNs:
5855 * @ctxt: a schema parser context
5856 * @wildc: the wildcard, already created
5857 * @node: a subtree containing XML Schema informations
5858 *
5859 * Parses the attribute "processContents" and "namespace"
5860 * of a xsd:anyAttribute and xsd:any.
5861 * *WARNING* this interface is highly subject to change
5862 *
5863 * Returns 0 if everything goes fine, a positive error code
5864 * if something is not valid and -1 if an internal error occurs.
5865 */
5866static int
5867xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5868 xmlSchemaPtr schema,
5869 xmlSchemaWildcardPtr wildc,
5870 xmlNodePtr node)
5871{
5872 const xmlChar *pc, *ns, *dictnsItem;
5873 int ret = 0;
5874 xmlChar *nsItem;
5875 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5876 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005877
Daniel Veillardc0826a72004-08-10 14:17:33 +00005878 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5879 if ((pc == NULL)
5880 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5881 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5882 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5883 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5884 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5885 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5886 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005887 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005888 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889 NULL, node,
5890 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005891 NULL, NULL, NULL);
5892 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005893 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005894 }
5895 /*
5896 * Build the namespace constraints.
5897 */
5898 attr = xmlSchemaGetPropNode(node, "namespace");
5899 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005900 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005901 wildc->any = 1;
5902 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5903 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005904 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 return (-1);
5906 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005907 wildc->negNsSet->value = schema->targetNamespace;
5908 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005909 const xmlChar *end, *cur;
5910
5911 cur = ns;
5912 do {
5913 while (IS_BLANK_CH(*cur))
5914 cur++;
5915 end = cur;
5916 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5917 end++;
5918 if (end == cur)
5919 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005920 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5922 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005923 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005924 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005925 NULL, (xmlNodePtr) attr,
5926 NULL,
5927 "((##any | ##other) | List of (xs:anyURI | "
5928 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005929 nsItem, NULL, NULL, NULL);
5930 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5931 } else {
5932 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5933 dictnsItem = schema->targetNamespace;
5934 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5935 dictnsItem = NULL;
5936 } else {
5937 /*
5938 * Validate the item (anyURI).
5939 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005940 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5942 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5943 }
5944 /*
5945 * Avoid dublicate namespaces.
5946 */
5947 tmp = wildc->nsSet;
5948 while (tmp != NULL) {
5949 if (dictnsItem == tmp->value)
5950 break;
5951 tmp = tmp->next;
5952 }
5953 if (tmp == NULL) {
5954 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5955 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005956 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005957 return (-1);
5958 }
5959 tmp->value = dictnsItem;
5960 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005961 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005962 wildc->nsSet = tmp;
5963 else
5964 lastNs->next = tmp;
5965 lastNs = tmp;
5966 }
5967
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005968 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 xmlFree(nsItem);
5970 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005971 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005972 }
5973 return (ret);
5974}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005975
5976static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005977xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5978 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005979 xmlNodePtr node,
5980 int minOccurs,
5981 int maxOccurs) {
5982
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005983 if ((maxOccurs == 0) && ( minOccurs == 0))
5984 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005985 if (maxOccurs != UNBOUNDED) {
5986 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005987 * TODO: Maybe we should better not create the particle,
5988 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005989 * content model.
5990 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005992 * 3.9.6 Schema Component Constraint: Particle Correct
5993 *
5994 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005995 if (maxOccurs < 1) {
5996 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 * 2.2 {max occurs} must be greater than or equal to 1.
5998 */
5999 xmlSchemaPCustomAttrErr(ctxt,
6000 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006001 NULL, NULL,
6002 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006003 "The value must be greater than or equal to 1");
6004 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6005 } else if (minOccurs > maxOccurs) {
6006 /*
6007 * 2.1 {min occurs} must not be greater than {max occurs}.
6008 */
6009 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006010 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006011 NULL, NULL,
6012 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006013 "The value must not be greater than the value of 'maxOccurs'");
6014 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006016 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006017 return (0);
6018}
6019
Daniel Veillardc0826a72004-08-10 14:17:33 +00006020/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006021 * xmlSchemaParseAny:
6022 * @ctxt: a schema validation context
6023 * @schema: the schema being built
6024 * @node: a subtree containing XML Schema informations
6025 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006026 * Parsea a XML schema <any> element. A particle and wildcard
6027 * will be created (except if minOccurs==maxOccurs==0, in this case
6028 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006029 * *WARNING* this interface is highly subject to change
6030 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006031 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006033static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006034xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6035 xmlNodePtr node)
6036{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006037 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006038 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006039 xmlSchemaWildcardPtr wild;
6040 int min, max;
6041 xmlAttrPtr attr;
6042 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006043
6044 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6045 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006046 /*
6047 * Check for illegal attributes.
6048 */
6049 attr = node->properties;
6050 while (attr != NULL) {
6051 if (attr->ns == NULL) {
6052 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6053 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6054 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6055 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6056 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006057 xmlSchemaPIllegalAttrErr(ctxt,
6058 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6059 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006060 }
6061 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006062 xmlSchemaPIllegalAttrErr(ctxt,
6063 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6064 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006065 }
6066 attr = attr->next;
6067 }
6068 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6069 /*
6070 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006071 */
6072 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6073 "(xs:nonNegativeInteger | unbounded)");
6074 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6075 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006076 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6077 /*
6078 * Create & parse the wildcard.
6079 */
6080 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6081 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006082 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006083 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006084 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006085 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006086 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006087 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006088 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006089 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006090 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 }
6092 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006093 xmlSchemaPContentErr(ctxt,
6094 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006096 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006097 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006098 /*
6099 * No component if minOccurs==maxOccurs==0.
6100 */
6101 if ((min == 0) && (max == 0)) {
6102 /* Don't free the wildcard, since it's already on the list. */
6103 return (NULL);
6104 }
6105 /*
6106 * Create the particle.
6107 */
6108 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6109 if (particle == NULL)
6110 return (NULL);
6111 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006112 wild->minOccurs = min;
6113 wild->maxOccurs = max;
6114 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006115
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006116 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006117}
6118
6119/**
6120 * xmlSchemaParseNotation:
6121 * @ctxt: a schema validation context
6122 * @schema: the schema being built
6123 * @node: a subtree containing XML Schema informations
6124 *
6125 * parse a XML schema Notation declaration
6126 *
6127 * Returns the new structure or NULL in case of error
6128 */
6129static xmlSchemaNotationPtr
6130xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006131 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006132{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006133 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006134 xmlSchemaNotationPtr ret;
6135 xmlNodePtr child = NULL;
6136
6137 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6138 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006139 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006140 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006141 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6142 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006143 return (NULL);
6144 }
6145 ret = xmlSchemaAddNotation(ctxt, schema, name);
6146 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006147 return (NULL);
6148 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006149 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006150
6151 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6152 node, BAD_CAST "id");
6153
6154 if (IS_SCHEMA(child, "annotation")) {
6155 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6156 child = child->next;
6157 }
6158
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 child = node->children;
6160 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006161 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006163 }
6164 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006165 xmlSchemaPContentErr(ctxt,
6166 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006167 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006168 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006169 }
6170
6171 return (ret);
6172}
6173
6174/**
6175 * xmlSchemaParseAnyAttribute:
6176 * @ctxt: a schema validation context
6177 * @schema: the schema being built
6178 * @node: a subtree containing XML Schema informations
6179 *
6180 * parse a XML schema AnyAttrribute declaration
6181 * *WARNING* this interface is highly subject to change
6182 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006183 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006184 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006185static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006186xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6187 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006188{
Daniel Veillard3646d642004-06-02 19:19:14 +00006189 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006190 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006191 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006192
6193 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6194 return (NULL);
6195
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006196 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6197 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006198 if (ret == NULL) {
6199 return (NULL);
6200 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006201 /*
6202 * Check for illegal attributes.
6203 */
6204 attr = node->properties;
6205 while (attr != NULL) {
6206 if (attr->ns == NULL) {
6207 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6208 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6209 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006210 xmlSchemaPIllegalAttrErr(ctxt,
6211 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6212 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 }
6214 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006215 xmlSchemaPIllegalAttrErr(ctxt,
6216 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6217 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006218 }
6219 attr = attr->next;
6220 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006221 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6222 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006223 /*
6224 * Parse the namespace list.
6225 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006226 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006227 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006228 /*
6229 * And now for the children...
6230 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006231 child = node->children;
6232 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006233 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6234 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006235 }
6236 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006237 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006238 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006239 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006241 }
6242
6243 return (ret);
6244}
6245
6246
6247/**
6248 * xmlSchemaParseAttribute:
6249 * @ctxt: a schema validation context
6250 * @schema: the schema being built
6251 * @node: a subtree containing XML Schema informations
6252 *
6253 * parse a XML schema Attrribute declaration
6254 * *WARNING* this interface is highly subject to change
6255 *
William M. Bracke7091952004-05-11 15:09:58 +00006256 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006257 */
6258static xmlSchemaAttributePtr
6259xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006260 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006261{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006262 const xmlChar *name, *attrValue;
6263 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006264 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006265 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 xmlAttrPtr attr, nameAttr;
6267 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006268
6269 /*
6270 * Note that the w3c spec assumes the schema to be validated with schema
6271 * for schemas beforehand.
6272 *
6273 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006274 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006275
6276 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6277 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006278 attr = xmlSchemaGetPropNode(node, "ref");
6279 nameAttr = xmlSchemaGetPropNode(node, "name");
6280
6281 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006282 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006283 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006284 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006285 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006286 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6287 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006288 "One of the attributes 'ref' or 'name' must be present");
6289 return (NULL);
6290 }
6291 if ((topLevel) || (attr == NULL)) {
6292 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006293 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6294 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006295 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006297 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006298 isRef = 1;
6299
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006301 char buf[50];
6302 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006303
6304 /*
6305 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006306 */
6307 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6308 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6309 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006310 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006311 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006312 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006313 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006314 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315 if (ret == NULL) {
6316 if (repName != NULL)
6317 xmlFree(repName);
6318 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006319 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006320 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6321 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006322 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006323 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006324 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6325 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006326 /*
6327 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6328 */
6329 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006330 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6331 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 "ref", "name");
6333 /*
6334 * Check for illegal attributes.
6335 */
6336 attr = node->properties;
6337 while (attr != NULL) {
6338 if (attr->ns == NULL) {
6339 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6340 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006341 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006342 * 3.2.3 : 3.2
6343 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006344 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006345 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 xmlSchemaPIllegalAttrErr(ctxt,
6347 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 (xmlSchemaTypePtr) ret, attr);
6349 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6350 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6351 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006352 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6353 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006355 xmlSchemaPIllegalAttrErr(ctxt,
6356 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6357 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006358 }
6359 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006360 xmlSchemaPIllegalAttrErr(ctxt,
6361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6362 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006363 }
6364 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006365 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006366 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006367 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006368
Daniel Veillardc0826a72004-08-10 14:17:33 +00006369 /*
6370 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006371 */
6372 if (xmlSchemaPValAttrNode(ctxt,
6373 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006374 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6375 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006376 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006377 /*
6378 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006380 /*
6381 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6382 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006383 */
6384 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006385 xmlSchemaPSimpleTypeErr(ctxt,
6386 XML_SCHEMAP_NO_XMLNS,
6387 NULL, (xmlNodePtr) nameAttr,
6388 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6389 "The value of type 'xs:NCName' must not match 'xmlns'",
6390 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006391 if (repName != NULL)
6392 xmlFree(repName);
6393 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006394 }
6395 /*
6396 * Evaluate the target namespace
6397 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006398 if (topLevel) {
6399 ns = schema->targetNamespace;
6400 } else {
6401 attr = xmlSchemaGetPropNode(node, "form");
6402 if (attr != NULL) {
6403 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6404 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6405 ns = schema->targetNamespace;
6406 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006407 xmlSchemaPSimpleTypeErr(ctxt,
6408 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6409 NULL, (xmlNodePtr) attr,
6410 NULL, "(qualified | unqualified)",
6411 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006412 }
6413 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006414 ns = schema->targetNamespace;
6415 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006416 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006417 if (ret == NULL) {
6418 if (repName != NULL)
6419 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006420 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006421 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006422 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006423 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006424 if (topLevel)
6425 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 /*
6427 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6428 * TODO: Move this to the component layer.
6429 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006430 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006431 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006432 XML_SCHEMAP_NO_XSI,
6433 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006434 "The target namespace must not match '%s'",
6435 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 }
6437 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 * Check for illegal attributes.
6439 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006440 attr = node->properties;
6441 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006442 if (attr->ns == NULL) {
6443 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6444 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6445 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6447 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006448 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006449 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6450 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006451 xmlSchemaPIllegalAttrErr(ctxt,
6452 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6453 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 }
6455 }
6456 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006457 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6458 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006459 }
6460 attr = attr->next;
6461 }
6462 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006463 node, "type", &ret->typeNs, &ret->typeName);
6464 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006465 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6466 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006467 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006468 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006469 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006470 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6471 if (ret->defValue != NULL)
6472 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006473 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 * Attribute "default".
6475 */
6476 attr = xmlSchemaGetPropNode(node, "default");
6477 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006478 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006479 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006480 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 */
6482 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6483 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6484 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6485 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006486 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6487 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006488 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006489 /*
6490 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 */
6492 attr = xmlSchemaGetPropNode(node, "use");
6493 if (attr != NULL) {
6494 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6495 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6496 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6497 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6498 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6499 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6500 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6501 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502 xmlSchemaPSimpleTypeErr(ctxt,
6503 XML_SCHEMAP_INVALID_ATTR_USE,
6504 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6505 NULL, "(optional | prohibited | required)",
6506 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006507 } else
6508 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006509 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 * 3.2.3 : 2
6511 * If default and use are both present, use must have
6512 * the actual value optional.
6513 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6515 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006516 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006517 xmlSchemaPSimpleTypeErr(ctxt,
6518 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6519 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6520 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006521 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006522 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006523 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006524 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 /*
6526 * And now for the children...
6527 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006528 child = node->children;
6529 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006530 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6531 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006532 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 * 3.2.3 : 3.2
6538 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006539 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 */
6541 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6542 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6543 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6546 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 }
6549 } else {
6550 if (IS_SCHEMA(child, "simpleType")) {
6551 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006552 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006553 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006555 */
6556 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6557 &repName, (xmlSchemaTypePtr) ret, node, child,
6558 "The attribute 'type' and the <simpleType> child "
6559 "are mutually exclusive", NULL);
6560 } else
6561 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6562 child = child->next;
6563 }
6564 if (child != NULL)
6565 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6566 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6567 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006568 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006569 /*
6570 * Cleanup.
6571 */
6572 if (repName != NULL)
6573 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006574 return (ret);
6575}
6576
6577/**
6578 * xmlSchemaParseAttributeGroup:
6579 * @ctxt: a schema validation context
6580 * @schema: the schema being built
6581 * @node: a subtree containing XML Schema informations
6582 *
6583 * parse a XML schema Attribute Group declaration
6584 * *WARNING* this interface is highly subject to change
6585 *
6586 * Returns the attribute group or NULL in case of error.
6587 */
6588static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006589xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006590 xmlSchemaPtr schema, xmlNodePtr node,
6591 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006592{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006593 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006594 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006596 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006597 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006598
6599 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6600 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006601
6602 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006603 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006604 if ((topLevel) || (attr == NULL)) {
6605 /*
6606 * Parse as an attribute group definition.
6607 * Note that those are allowed at top level only.
6608 */
6609 if (nameAttr == NULL) {
6610 xmlSchemaPMissingAttrErr(ctxt,
6611 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006612 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006613 return (NULL);
6614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006616 * (xmlNodePtr) nameAttr);
6617 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006618 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006619 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006620 */
6621 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006622 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006623 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6624 return (NULL);
6625 }
6626 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6627 if (ret == NULL)
6628 return (NULL);
6629 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6630 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6631 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006632 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006633 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006634 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006635 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006636
6637 /*
6638 * Parse as an attribute group definition reference.
6639 */
6640 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006641 xmlSchemaPMissingAttrErr(ctxt,
6642 XML_SCHEMAP_S4S_ATTR_MISSING,
6643 NULL, node, "ref", NULL);
6644 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006645 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006646 NULL, NULL, attr, &refNs,&ref);
6647
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006648 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006649 name = (const xmlChar *) buf;
6650 if (name == NULL) {
6651 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6652 "attribute group definition reference", node);
6653 return (NULL);
6654 }
6655 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6656 if (ret == NULL)
6657 return (NULL);
6658 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6659 ret->ref = ref;
6660 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006662 xmlSchemaCheckReference(ctxt, schema, node,
6663 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006664 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006665 /*
6666 * Check for illegal attributes.
6667 */
6668 attr = node->properties;
6669 while (attr != NULL) {
6670 if (attr->ns == NULL) {
6671 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6672 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006673 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006674 {
6675 xmlSchemaPIllegalAttrErr(ctxt,
6676 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6677 NULL, NULL, attr);
6678 }
6679 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6680 xmlSchemaPIllegalAttrErr(ctxt,
6681 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6682 NULL, NULL, attr);
6683 }
6684 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 }
6686 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006687 /*
6688 * And now for the children...
6689 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006690 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006691 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006692 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006693 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006694 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6695 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006696 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006697 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006698 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006699 if (IS_SCHEMA(child, "anyAttribute")) {
6700 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6701 child = child->next;
6702 }
6703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006704 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006705 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006706 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6707 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006708 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006709 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006710 ctxt->container = oldcontainer;
6711 return (ret);
6712}
6713
6714/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006715 * xmlSchemaPValAttrFormDefault:
6716 * @value: the value
6717 * @flags: the flags to be modified
6718 * @flagQualified: the specific flag for "qualified"
6719 *
6720 * Returns 0 if the value is valid, 1 otherwise.
6721 */
6722static int
6723xmlSchemaPValAttrFormDefault(const xmlChar *value,
6724 int *flags,
6725 int flagQualified)
6726{
6727 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6728 if ((*flags & flagQualified) == 0)
6729 *flags |= flagQualified;
6730 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006731 return (1);
6732
William M. Brack2f2a6632004-08-20 23:09:47 +00006733 return (0);
6734}
6735
6736/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006737 * xmlSchemaPValAttrBlockFinal:
6738 * @value: the value
6739 * @flags: the flags to be modified
6740 * @flagAll: the specific flag for "#all"
6741 * @flagExtension: the specific flag for "extension"
6742 * @flagRestriction: the specific flag for "restriction"
6743 * @flagSubstitution: the specific flag for "substitution"
6744 * @flagList: the specific flag for "list"
6745 * @flagUnion: the specific flag for "union"
6746 *
6747 * Validates the value of the attribute "final" and "block". The value
6748 * is converted into the specified flag values and returned in @flags.
6749 *
6750 * Returns 0 if the value is valid, 1 otherwise.
6751 */
6752
6753static int
6754xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006755 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006756 int flagAll,
6757 int flagExtension,
6758 int flagRestriction,
6759 int flagSubstitution,
6760 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006761 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006762{
6763 int ret = 0;
6764
6765 /*
6766 * TODO: This does not check for dublicate entries.
6767 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006768 if ((flags == NULL) || (value == NULL))
6769 return (-1);
6770 if (value[0] == 0)
6771 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006772 if (xmlStrEqual(value, BAD_CAST "#all")) {
6773 if (flagAll != -1)
6774 *flags |= flagAll;
6775 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006776 if (flagExtension != -1)
6777 *flags |= flagExtension;
6778 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006779 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006780 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006781 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006782 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006783 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006784 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006785 *flags |= flagUnion;
6786 }
6787 } else {
6788 const xmlChar *end, *cur = value;
6789 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006790
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 do {
6792 while (IS_BLANK_CH(*cur))
6793 cur++;
6794 end = cur;
6795 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6796 end++;
6797 if (end == cur)
6798 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006799 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006800 if (xmlStrEqual(item, BAD_CAST "extension")) {
6801 if (flagExtension != -1) {
6802 if ((*flags & flagExtension) == 0)
6803 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006804 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 ret = 1;
6806 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6807 if (flagRestriction != -1) {
6808 if ((*flags & flagRestriction) == 0)
6809 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006810 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006811 ret = 1;
6812 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6813 if (flagSubstitution != -1) {
6814 if ((*flags & flagSubstitution) == 0)
6815 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 ret = 1;
6818 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6819 if (flagList != -1) {
6820 if ((*flags & flagList) == 0)
6821 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006822 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 ret = 1;
6824 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6825 if (flagUnion != -1) {
6826 if ((*flags & flagUnion) == 0)
6827 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006828 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006830 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006831 ret = 1;
6832 if (item != NULL)
6833 xmlFree(item);
6834 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006835 } while ((ret == 0) && (*cur != 0));
6836 }
6837
Daniel Veillardc0826a72004-08-10 14:17:33 +00006838 return (ret);
6839}
6840
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006841static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006842xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006843 xmlSchemaIDCPtr idc,
6844 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006845 xmlAttrPtr attr,
6846 int isField)
6847{
6848 xmlNodePtr node;
6849
6850 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006851 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006852 * Schema Component Constraint: Selector Value OK
6853 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006855 * in [XPath].
6856 */
6857 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006858 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006859 XML_SCHEMAP_INTERNAL,
6860 "Internal error: xmlSchemaCheckCSelectorXPath, "
6861 "the selector is not specified.\n", NULL, NULL);
6862 return (-1);
6863 }
6864 if (attr == NULL)
6865 node = idc->node;
6866 else
6867 node = (xmlNodePtr) attr;
6868 if (selector->xpath == NULL) {
6869 xmlSchemaPCustomErr(ctxt,
6870 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006871 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6872 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006873 "The XPath expression of the selector is not valid", NULL);
6874 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6875 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006876 const xmlChar **nsArray = NULL;
6877 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006878 /*
6879 * Compile the XPath expression.
6880 */
6881 /*
6882 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006883 * TODO: Call xmlPatterncompile with different options for selector/
6884 * field.
6885 */
6886 nsList = xmlGetNsList(attr->doc, attr->parent);
6887 /*
6888 * Build an array of prefixes and namespaces.
6889 */
6890 if (nsList != NULL) {
6891 int i, count = 0;
6892 xmlNsPtr ns;
6893
6894 for (i = 0; nsList[i] != NULL; i++)
6895 count++;
6896
6897 nsArray = (const xmlChar **) xmlMalloc(
6898 (count * 2 + 1) * sizeof(const xmlChar *));
6899 if (nsArray == NULL) {
6900 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6901 NULL);
6902 return (-1);
6903 }
6904 for (i = 0; i < count; i++) {
6905 ns = nsList[i];
6906 nsArray[2 * i] = nsList[i]->href;
6907 nsArray[2 * i + 1] = nsList[i]->prefix;
6908 }
6909 nsArray[count * 2] = NULL;
6910 xmlFree(nsList);
6911 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006912 /*
6913 * TODO: Differentiate between "selector" and "field".
6914 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006915 if (isField)
6916 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006917 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006918 else
6919 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006920 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006921 if (nsArray != NULL)
6922 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006923
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006924 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006925 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006926 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006927 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6928 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006929 "The XPath expression '%s' could not be "
6930 "compiled", selector->xpath);
6931 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006932 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006933 }
6934 return (0);
6935}
6936
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006937#define ADD_ANNOTATION(annot) \
6938 xmlSchemaAnnotPtr cur = item->annot; \
6939 if (item->annot == NULL) { \
6940 item->annot = annot; \
6941 return (annot); \
6942 } \
6943 cur = item->annot; \
6944 if (cur->next != NULL) { \
6945 cur = cur->next; \
6946 } \
6947 cur->next = annot;
6948
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006949/**
6950 * xmlSchemaAssignAnnotation:
6951 * @item: the schema component
6952 * @annot: the annotation
6953 *
6954 * Adds the annotation to the given schema component.
6955 *
6956 * Returns the given annotaion.
6957 */
6958static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006959xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6960 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006961{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006962 if ((annItem == NULL) || (annot == NULL))
6963 return (NULL);
6964 switch (annItem->type) {
6965 case XML_SCHEMA_TYPE_ELEMENT: {
6966 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6967 ADD_ANNOTATION(annot)
6968 }
6969 break;
6970 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6971 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6972 ADD_ANNOTATION(annot)
6973 }
6974 break;
6975 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6976 case XML_SCHEMA_TYPE_ANY: {
6977 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6978 ADD_ANNOTATION(annot)
6979 }
6980 break;
6981 case XML_SCHEMA_TYPE_PARTICLE:
6982 case XML_SCHEMA_TYPE_IDC_KEY:
6983 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006984 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006985 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6986 ADD_ANNOTATION(annot)
6987 }
6988 break;
6989 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6990 xmlSchemaAttributeGroupPtr item =
6991 (xmlSchemaAttributeGroupPtr) annItem;
6992 ADD_ANNOTATION(annot)
6993 }
6994 break;
6995 case XML_SCHEMA_TYPE_NOTATION: {
6996 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
6997 ADD_ANNOTATION(annot)
6998 }
6999 break;
7000 case XML_SCHEMA_FACET_MININCLUSIVE:
7001 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7002 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7003 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7004 case XML_SCHEMA_FACET_TOTALDIGITS:
7005 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7006 case XML_SCHEMA_FACET_PATTERN:
7007 case XML_SCHEMA_FACET_ENUMERATION:
7008 case XML_SCHEMA_FACET_WHITESPACE:
7009 case XML_SCHEMA_FACET_LENGTH:
7010 case XML_SCHEMA_FACET_MAXLENGTH:
7011 case XML_SCHEMA_FACET_MINLENGTH: {
7012 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7013 ADD_ANNOTATION(annot)
7014 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007015 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007016 case XML_SCHEMA_TYPE_SIMPLE:
7017 case XML_SCHEMA_TYPE_COMPLEX: {
7018 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7019 ADD_ANNOTATION(annot)
7020 }
7021 break;
7022 case XML_SCHEMA_TYPE_GROUP: {
7023 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7024 ADD_ANNOTATION(annot)
7025 }
7026 break;
7027 case XML_SCHEMA_TYPE_SEQUENCE:
7028 case XML_SCHEMA_TYPE_CHOICE:
7029 case XML_SCHEMA_TYPE_ALL: {
7030 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7031 ADD_ANNOTATION(annot)
7032 }
7033 break;
7034 default:
7035 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007036 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007037 NULL, NULL, NULL,
7038 "Internal error: xmlSchemaAddAnnotation, "
7039 "The item is not a annotated schema component", NULL);
7040 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007041 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007042 return (annot);
7043}
7044
7045/**
7046 * xmlSchemaParseIDCSelectorAndField:
7047 * @ctxt: a schema validation context
7048 * @schema: the schema being built
7049 * @node: a subtree containing XML Schema informations
7050 *
7051 * Parses a XML Schema identity-contraint definition's
7052 * <selector> and <field> elements.
7053 *
7054 * Returns the parsed identity-constraint definition.
7055 */
7056static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007057xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007058 xmlSchemaPtr schema,
7059 xmlSchemaIDCPtr idc,
7060 xmlNodePtr node,
7061 int isField)
7062{
7063 xmlSchemaIDCSelectPtr item;
7064 xmlNodePtr child = NULL;
7065 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007066
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007067 /*
7068 * Check for illegal attributes.
7069 */
7070 attr = node->properties;
7071 while (attr != NULL) {
7072 if (attr->ns == NULL) {
7073 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7074 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007075 xmlSchemaPIllegalAttrErr(ctxt,
7076 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7077 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007078 }
7079 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007080 xmlSchemaPIllegalAttrErr(ctxt,
7081 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7082 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007083 }
7084 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007085 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007086 /*
7087 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007088 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007089 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7090 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007091 xmlSchemaPErrMemory(ctxt,
7092 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007093 NULL);
7094 return (NULL);
7095 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007096 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007097 /*
7098 * Attribute "xpath" (mandatory).
7099 */
7100 attr = xmlSchemaGetPropNode(node, "xpath");
7101 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007102 xmlSchemaPMissingAttrErr(ctxt,
7103 XML_SCHEMAP_S4S_ATTR_MISSING,
7104 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 "name", NULL);
7106 } else {
7107 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7108 /*
7109 * URGENT TODO: "field"s have an other syntax than "selector"s.
7110 */
7111
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007112 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7113 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007114 xmlSchemaPErr(ctxt,
7115 (xmlNodePtr) attr,
7116 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007117 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007118 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007119 NULL, NULL);
7120 }
7121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007122 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007123 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007124 /*
7125 * And now for the children...
7126 */
7127 child = node->children;
7128 if (IS_SCHEMA(child, "annotation")) {
7129 /*
7130 * Add the annotation to the parent IDC.
7131 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007132 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007133 xmlSchemaParseAnnotation(ctxt, schema, child));
7134 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007135 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 if (child != NULL) {
7137 xmlSchemaPContentErr(ctxt,
7138 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007139 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007140 NULL, "(annotation?)");
7141 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007142
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007143 return (item);
7144}
7145
7146/**
7147 * xmlSchemaParseIDC:
7148 * @ctxt: a schema validation context
7149 * @schema: the schema being built
7150 * @node: a subtree containing XML Schema informations
7151 *
7152 * Parses a XML Schema identity-contraint definition.
7153 *
7154 * Returns the parsed identity-constraint definition.
7155 */
7156static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007157xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007158 xmlSchemaPtr schema,
7159 xmlNodePtr node,
7160 xmlSchemaTypeType idcCategory,
7161 const xmlChar *targetNamespace)
7162{
7163 xmlSchemaIDCPtr item = NULL;
7164 xmlNodePtr child = NULL;
7165 xmlAttrPtr attr;
7166 const xmlChar *name = NULL;
7167 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7168 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007169
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007170 /*
7171 * Check for illegal attributes.
7172 */
7173 attr = node->properties;
7174 while (attr != NULL) {
7175 if (attr->ns == NULL) {
7176 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7177 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7178 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7179 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007180 xmlSchemaPIllegalAttrErr(ctxt,
7181 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7182 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007183 }
7184 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007185 xmlSchemaPIllegalAttrErr(ctxt,
7186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7187 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007188 }
7189 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007190 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007191 /*
7192 * Attribute "name" (mandatory).
7193 */
7194 attr = xmlSchemaGetPropNode(node, "name");
7195 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007196 xmlSchemaPMissingAttrErr(ctxt,
7197 XML_SCHEMAP_S4S_ATTR_MISSING,
7198 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007199 "name", NULL);
7200 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007201 } else if (xmlSchemaPValAttrNode(ctxt,
7202 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7204 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007205 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007206 /*
7207 * Create the component.
7208 */
7209 if (schema->idcDef == NULL)
7210 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007211 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007212 return (NULL);
7213
7214 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7215 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007216 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007217 "allocating an identity-constraint definition", NULL);
7218 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007219 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007220 /*
7221 * Add the IDC to the list of IDCs on the schema component.
7222 */
7223 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007224 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007225 xmlSchemaPCustomErrExt(ctxt,
7226 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007227 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007228 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007229 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007230 name, targetNamespace, NULL);
7231 xmlFree(item);
7232 return (NULL);
7233 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007234 memset(item, 0, sizeof(xmlSchemaIDC));
7235 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007236 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007237 item->node = node;
7238 /*
7239 * The target namespace of the parent element declaration.
7240 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007242 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7243 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007244 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7245 /*
7246 * Attribute "refer" (mandatory).
7247 */
7248 attr = xmlSchemaGetPropNode(node, "refer");
7249 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007250 xmlSchemaPMissingAttrErr(ctxt,
7251 XML_SCHEMAP_S4S_ATTR_MISSING,
7252 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007253 "refer", NULL);
7254 } else {
7255 /*
7256 * Create a reference item.
7257 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007258 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007259 NULL, NULL);
7260 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007261 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007262 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007263 NULL, NULL, attr,
7264 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007265 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007266 xmlSchemaCheckReference(ctxt, schema, node,
7267 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007268 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007269 }
7270 }
7271 /*
7272 * And now for the children...
7273 */
7274 child = node->children;
7275 if (IS_SCHEMA(child, "annotation")) {
7276 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7277 child = child->next;
7278 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007279 if (child == NULL) {
7280 xmlSchemaPContentErr(ctxt,
7281 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007282 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007283 "A child element is missing",
7284 "(annotation?, (selector, field+))");
7285 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007286 /*
7287 * Child element <selector>.
7288 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007289 if (IS_SCHEMA(child, "selector")) {
7290 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007291 item, child, 0);
7292 child = child->next;
7293 /*
7294 * Child elements <field>.
7295 */
7296 if (IS_SCHEMA(child, "field")) {
7297 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007298 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007299 item, child, 1);
7300 if (field != NULL) {
7301 field->index = item->nbFields;
7302 item->nbFields++;
7303 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007304 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 else
7306 item->fields = field;
7307 lastField = field;
7308 }
7309 child = child->next;
7310 } while (IS_SCHEMA(child, "field"));
7311 } else {
7312 xmlSchemaPContentErr(ctxt,
7313 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007314 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007315 NULL, "(annotation?, (selector, field+))");
7316 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007317 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007318 if (child != NULL) {
7319 xmlSchemaPContentErr(ctxt,
7320 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007321 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007322 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007323 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007324
7325 return (item);
7326}
7327
Daniel Veillardc0826a72004-08-10 14:17:33 +00007328/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007329 * xmlSchemaParseElement:
7330 * @ctxt: a schema validation context
7331 * @schema: the schema being built
7332 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007333 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007334 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007335 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007336 * *WARNING* this interface is highly subject to change
7337 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007338 * Returns the element declaration or a particle; NULL in case
7339 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007340 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007341static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007342xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007343 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007344{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007345 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007346 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007347 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007348 xmlNodePtr child = NULL;
7349 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007350 int min, max, isRef = 0;
7351 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007352
7353 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7354 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007355
Daniel Veillard4255d502002-04-16 15:50:10 +00007356 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007357 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007358 /*
7359 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007360 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 * robust.
7362 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007363 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007364 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007365 if ((topLevel) || (attr == NULL)) {
7366 if (nameAttr == NULL) {
7367 xmlSchemaPMissingAttrErr(ctxt,
7368 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007369 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007370 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007371 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007372 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007373 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007374
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007375 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007376 child = node->children;
7377 if (IS_SCHEMA(child, "annotation")) {
7378 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7379 child = child->next;
7380 }
7381 /*
7382 * Skip particle part if a global declaration.
7383 */
7384 if (topLevel)
7385 goto declaration_part;
7386 /*
7387 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007388 */
7389 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7390 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7391 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007392 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7393 if (particle == NULL)
7394 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007395
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007396 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7397
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007398 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007399 const xmlChar *refNs = NULL, *ref = NULL;
7400 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007401 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007402 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007403 */
7404 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007405 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007407 /*
7408 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007409 */
7410 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007411 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007412 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007413 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007415 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007417 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007418 attr = node->properties;
7419 while (attr != NULL) {
7420 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007421 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7422 xmlStrEqual(attr->name, BAD_CAST "name") ||
7423 xmlStrEqual(attr->name, BAD_CAST "id") ||
7424 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7425 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7426 {
7427 attr = attr->next;
7428 continue;
7429 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007432 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007433 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007434 "Only the attributes 'minOccurs', 'maxOccurs' and "
7435 "'id' are allowed in addition to 'ref'");
7436 break;
7437 }
7438 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7439 xmlSchemaPIllegalAttrErr(ctxt,
7440 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007441 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007442 }
7443 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007444 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007445 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007446 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007447 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007448 if (child != NULL) {
7449 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7450 NULL, NULL, node, child, NULL, "(annotation?)");
7451 }
7452 if ((min == 0) && (max == 0))
7453 goto return_null;
7454 /*
7455 * Create the reference item.
7456 */
7457 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7458 ref, refNs);
7459 if (refer == NULL)
7460 goto return_null;
7461 particle->children = (xmlSchemaTreeItemPtr) refer;
7462 particle->annot = annot;
7463 /*
7464 * Add to assembled items; the reference need to be resolved.
7465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007466 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007467 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7468
7469 return ((xmlSchemaBasicItemPtr) particle);
7470 }
7471 /*
7472 * The declaration part ===============================================
7473 */
7474declaration_part:
7475 {
7476 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7477 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7478
7479 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007480 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007481 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007482 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007483 * Evaluate the target namespace.
7484 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007485 if (topLevel) {
7486 ns = schema->targetNamespace;
7487 } else {
7488 attr = xmlSchemaGetPropNode(node, "form");
7489 if (attr != NULL) {
7490 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7491 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007492 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007493 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007494 xmlSchemaPSimpleTypeErr(ctxt,
7495 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7496 NULL, (xmlNodePtr) attr,
7497 NULL, "(qualified | unqualified)",
7498 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007499 }
7500 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007501 ns = schema->targetNamespace;
7502 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007503 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007504 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007505 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007506 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007507 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7508 decl->node = node;
7509 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007510 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007511 * Check for illegal attributes.
7512 */
William M. Bracke7091952004-05-11 15:09:58 +00007513 attr = node->properties;
7514 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007515 if (attr->ns == NULL) {
7516 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7517 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007520 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007521 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007522 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7523 {
7524 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007525 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007526 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007527 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007528 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007529 xmlSchemaPIllegalAttrErr(ctxt,
7530 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7531 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007532 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007533 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7534 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7536
7537 xmlSchemaPIllegalAttrErr(ctxt,
7538 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007539 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 }
7541 }
7542 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007543
Daniel Veillardc0826a72004-08-10 14:17:33 +00007544 xmlSchemaPIllegalAttrErr(ctxt,
7545 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007546 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007547 }
7548 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549 }
William M. Bracke7091952004-05-11 15:09:58 +00007550 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007551 * Extract/validate attributes.
7552 */
7553 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007554 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 * Process top attributes of global element declarations here.
7556 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007557 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7558 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007559 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7560 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7561 &(decl->substGroupNs), &(decl->substGroup));
7562 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007563 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007564 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007565 /*
7566 * Attribute "final".
7567 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007570 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7571 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7572 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7573 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007574 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007575 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7576 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 -1,
7578 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7579 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007580 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007581 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007582 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7583 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007584 attrValue, NULL, NULL, NULL);
7585 }
7586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007587 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 /*
7589 * Attribute "block".
7590 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007591 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007592 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007593 /*
7594 * Apply default "block" values.
7595 */
7596 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7597 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7598 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7599 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7600 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7601 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007603 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7604 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 -1,
7606 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007607 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007608 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7609 xmlSchemaPSimpleTypeErr(ctxt,
7610 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007611 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007612 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007613 "restriction | substitution))", attrValue,
7614 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007615 }
7616 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007618 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007619 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007620
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007621 attr = xmlSchemaGetPropNode(node, "type");
7622 if (attr != NULL) {
7623 xmlSchemaPValAttrNodeQName(ctxt, schema,
7624 NULL, (xmlSchemaTypePtr) decl, attr,
7625 &(decl->namedTypeNs), &(decl->namedType));
7626 xmlSchemaCheckReference(ctxt, schema, node,
7627 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7628 }
7629 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7630 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007631 if (attr != NULL) {
7632 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007633 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007634 /*
7635 * 3.3.3 : 1
7636 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007637 */
7638 xmlSchemaPMutualExclAttrErr(ctxt,
7639 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007640 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007641 "default", "fixed");
7642 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007643 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7644 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 }
William M. Bracke7091952004-05-11 15:09:58 +00007646 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007647 /*
7648 * And now for the children...
7649 */
7650 oldcontainer = ctxt->container;
7651 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007652 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007653 /*
7654 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007656 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007657 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007658 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 xmlSchemaPContentErr(ctxt,
7660 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007661 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007662 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007663 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007664 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007665 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007666 child = child->next;
7667 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007668 /*
7669 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007670 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007671 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007672 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007673 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007674 xmlSchemaPContentErr(ctxt,
7675 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007676 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007677 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007678 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007679 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007680 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007681 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 }
William M. Bracke7091952004-05-11 15:09:58 +00007683 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007684 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007685 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007686 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007687 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007688 } else if (IS_SCHEMA(child, "key")) {
7689 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007690 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007691 } else if (IS_SCHEMA(child, "keyref")) {
7692 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007693 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007694 }
7695 if (lastIDC != NULL)
7696 lastIDC->next = curIDC;
7697 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007698 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007699 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007700 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007701 }
7702 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007703 xmlSchemaPContentErr(ctxt,
7704 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007705 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007706 NULL, "(annotation?, ((simpleType | complexType)?, "
7707 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007708 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007709 ctxt->container = oldcontainer;
7710 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007711 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007712 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007713 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007714 * different layer.
7715 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007716 FREE_AND_NULL(des)
7717 if (topLevel)
7718 return ((xmlSchemaBasicItemPtr) decl);
7719 else {
7720 particle->children = (xmlSchemaTreeItemPtr) decl;
7721 return ((xmlSchemaBasicItemPtr) particle);
7722 }
7723
7724return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007725 FREE_AND_NULL(des);
7726 if (annot != NULL) {
7727 if (particle != NULL)
7728 particle->annot = NULL;
7729 if (decl != NULL)
7730 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007731 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007732 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007733 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007734}
7735
7736/**
7737 * xmlSchemaParseUnion:
7738 * @ctxt: a schema validation context
7739 * @schema: the schema being built
7740 * @node: a subtree containing XML Schema informations
7741 *
7742 * parse a XML schema Union definition
7743 * *WARNING* this interface is highly subject to change
7744 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 * Returns -1 in case of internal error, 0 in case of success and a positive
7746 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007747 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007748static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007749xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007750 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007751{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007752 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007753 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007754 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007755 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007756
7757 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007758 return (-1);
7759 /* Not a component, don't create it. */
7760 type = ctxt->ctxtType;
7761 /*
7762 * Mark the simple type as being of variety "union".
7763 */
7764 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007765 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007766 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7767 * then the ·simple ur-type definition·."
7768 */
7769 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007770 /*
7771 * Check for illegal attributes.
7772 */
7773 attr = node->properties;
7774 while (attr != NULL) {
7775 if (attr->ns == NULL) {
7776 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7777 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007778 xmlSchemaPIllegalAttrErr(ctxt,
7779 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7780 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007781 }
7782 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007783 xmlSchemaPIllegalAttrErr(ctxt,
7784 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7785 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007786 }
7787 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007788 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007789 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007790 /*
7791 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007792 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007793 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007794 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007795 if (attr != NULL) {
7796 const xmlChar *end;
7797 xmlChar *tmp;
7798 const xmlChar *localName, *nsName;
7799 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7800 xmlSchemaQNameRefPtr ref;
7801
7802 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007803 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007804 do {
7805 while (IS_BLANK_CH(*cur))
7806 cur++;
7807 end = cur;
7808 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7809 end++;
7810 if (end == cur)
7811 break;
7812 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007813 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7814 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007815 /*
7816 * Create the member type link.
7817 */
7818 link = (xmlSchemaTypeLinkPtr)
7819 xmlMalloc(sizeof(xmlSchemaTypeLink));
7820 if (link == NULL) {
7821 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7822 "allocating a type link", NULL);
7823 return (-1);
7824 }
7825 link->type = NULL;
7826 link->next = NULL;
7827 if (lastLink == NULL)
7828 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007829 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007830 lastLink->next = link;
7831 lastLink = link;
7832 /*
7833 * Create a reference item.
7834 */
7835 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7836 localName, nsName);
7837 if (ref == NULL) {
7838 FREE_AND_NULL(tmp)
7839 return (-1);
7840 }
7841 /*
7842 * Assign the reference to the link, it will be resolved
7843 * later during fixup of the union simple type.
7844 */
7845 link->type = (xmlSchemaTypePtr) ref;
7846 }
7847 FREE_AND_NULL(tmp)
7848 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007849 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007850
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007851 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007852 /*
7853 * And now for the children...
7854 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007855 child = node->children;
7856 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007857 /*
7858 * Add the annotation to the simple type ancestor.
7859 */
7860 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7861 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007862 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007863 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007864 if (IS_SCHEMA(child, "simpleType")) {
7865 xmlSchemaTypePtr subtype, last = NULL;
7866
7867 /*
7868 * Anchor the member types in the "subtypes" field of the
7869 * simple type.
7870 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007871 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007872 subtype = (xmlSchemaTypePtr)
7873 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7874 if (subtype != NULL) {
7875 if (last == NULL) {
7876 type->subtypes = subtype;
7877 last = subtype;
7878 } else {
7879 last->next = subtype;
7880 last = subtype;
7881 }
7882 last->next = NULL;
7883 }
7884 child = child->next;
7885 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007886 }
7887 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007888 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007889 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007890 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007891 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007892 if ((attr == NULL) && (type->subtypes == NULL)) {
7893 /*
7894 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007895 * Either the memberTypes [attribute] of the <union> element must
7896 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007897 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007898 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007899 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7900 NULL, NULL, node,
7901 "Either the attribute 'memberTypes' or "
7902 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007903 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007904 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007905}
7906
7907/**
7908 * xmlSchemaParseList:
7909 * @ctxt: a schema validation context
7910 * @schema: the schema being built
7911 * @node: a subtree containing XML Schema informations
7912 *
7913 * parse a XML schema List definition
7914 * *WARNING* this interface is highly subject to change
7915 *
William M. Bracke7091952004-05-11 15:09:58 +00007916 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007917 * 1 in case of success.
7918 */
7919static xmlSchemaTypePtr
7920xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007921 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007922{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007924 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007925 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007926
7927 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7928 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007929 /* Not a component, don't create it. */
7930 type = ctxt->ctxtType;
7931 /*
7932 * Mark the type as being of variety "list".
7933 */
7934 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007935 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007936 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7937 * then the ·simple ur-type definition·."
7938 */
7939 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007940 /*
7941 * Check for illegal attributes.
7942 */
7943 attr = node->properties;
7944 while (attr != NULL) {
7945 if (attr->ns == NULL) {
7946 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7947 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007948 xmlSchemaPIllegalAttrErr(ctxt,
7949 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7950 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007951 }
7952 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007953 xmlSchemaPIllegalAttrErr(ctxt,
7954 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7955 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007956 }
7957 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007958 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007959
7960 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7961
William M. Brack2f2a6632004-08-20 23:09:47 +00007962 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007963 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7964 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 */
7966 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007967 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007968 /*
7969 * And now for the children...
7970 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007971 child = node->children;
7972 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007973 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7974 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007975 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007976 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007977 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007978 /*
7979 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007980 * Either the itemType [attribute] or the <simpleType> [child] of
7981 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007982 */
7983 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007984 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007985 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007986 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007987 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007988 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007989 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007990 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007992 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007993 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007994 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007995 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007996 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007997 "Either the attribute 'itemType' or the <simpleType> child "
7998 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007999 }
8000 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008002 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008003 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008004 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008005 if ((type->ref == NULL) &&
8006 (type->subtypes == NULL) &&
8007 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 "Either the attribute 'itemType' or the <simpleType> child "
8012 "must be present", NULL);
8013 }
8014 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008015}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008016
Daniel Veillard4255d502002-04-16 15:50:10 +00008017/**
8018 * xmlSchemaParseSimpleType:
8019 * @ctxt: a schema validation context
8020 * @schema: the schema being built
8021 * @node: a subtree containing XML Schema informations
8022 *
8023 * parse a XML schema Simple Type definition
8024 * *WARNING* this interface is highly subject to change
8025 *
William M. Bracke7091952004-05-11 15:09:58 +00008026 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008027 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008028 */
8029static xmlSchemaTypePtr
8030xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008031 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008032{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008034 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008035 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008036 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008037
8038 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8039 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008040
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008042 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008043 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008044 xmlSchemaPMissingAttrErr(ctxt,
8045 XML_SCHEMAP_S4S_ATTR_MISSING,
8046 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008047 "name", NULL);
8048 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008049 } else if (xmlSchemaPValAttrNode(ctxt,
8050 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008052 return (NULL);
8053 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008054 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008055
Daniel Veillardc0826a72004-08-10 14:17:33 +00008056 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008057 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008058
Daniel Veillard01fa6152004-06-29 17:04:39 +00008059 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008060 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008061 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008062 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008063 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008064 if (type == NULL)
8065 return (NULL);
8066 type->node = node;
8067 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008068 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008069 /*
8070 * Check for illegal attributes.
8071 */
8072 attr = node->properties;
8073 while (attr != NULL) {
8074 if (attr->ns == NULL) {
8075 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008076 xmlSchemaPIllegalAttrErr(ctxt,
8077 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8078 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008079 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008080 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008081 xmlSchemaPIllegalAttrErr(ctxt,
8082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8083 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008084 }
8085 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008086 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008087 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008088 /*
8089 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008090 *
8091 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008092 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008093 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 if (type == NULL)
8095 return (NULL);
8096 type->node = node;
8097 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008098 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008099 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8100 /*
8101 * Check for illegal attributes.
8102 */
8103 attr = node->properties;
8104 while (attr != NULL) {
8105 if (attr->ns == NULL) {
8106 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8107 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008108 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008109 xmlSchemaPIllegalAttrErr(ctxt,
8110 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8111 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008112 }
8113 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008114 xmlSchemaPIllegalAttrErr(ctxt,
8115 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8116 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008117 }
8118 attr = attr->next;
8119 }
8120 /*
8121 * Attribute "final".
8122 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008125 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8126 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8127 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8128 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8129 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8130 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008131 } else {
8132 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008133 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8134 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008135 XML_SCHEMAS_TYPE_FINAL_LIST,
8136 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8137
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008138 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008139 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008140 type, (xmlNodePtr) attr,
8141 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008142 attrValue, NULL, NULL, NULL);
8143 }
8144 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008145 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008146 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008147 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008148 /*
8149 * And now for the children...
8150 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008151 oldCtxtType = ctxt->ctxtType;
8152 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008153 ctxt->ctxtType = type;
8154 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008155 child = node->children;
8156 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008157 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008159 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008160 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008161 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8162 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008163 "(annotation?, (restriction | list | union))");
8164 } else if (IS_SCHEMA(child, "restriction")) {
8165 xmlSchemaParseRestriction(ctxt, schema, child,
8166 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008167 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008169 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008170 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008171 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008172 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008173 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008174 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008175 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008176 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8177 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008179 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008180 ctxt->parentItem = oldParentItem;
8181 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008182
Daniel Veillard4255d502002-04-16 15:50:10 +00008183 return (type);
8184}
8185
Daniel Veillard4255d502002-04-16 15:50:10 +00008186/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008187 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008188 * @ctxt: a schema validation context
8189 * @schema: the schema being built
8190 * @node: a subtree containing XML Schema informations
8191 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008192 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008193 * *WARNING* this interface is highly subject to change
8194 *
William M. Bracke7091952004-05-11 15:09:58 +00008195 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008196 * 1 in case of success.
8197 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008198static xmlSchemaTreeItemPtr
8199xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8200 xmlSchemaPtr schema,
8201 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008202{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008203 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008204 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008205 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008206 const xmlChar *ref = NULL, *refNs = NULL;
8207 int min, max;
8208
8209 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008210 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008211
8212 attr = xmlSchemaGetPropNode(node, "ref");
8213 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008214 xmlSchemaPMissingAttrErr(ctxt,
8215 XML_SCHEMAP_S4S_ATTR_MISSING,
8216 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 "ref", NULL);
8218 return (NULL);
8219 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008220 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008221 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008222 }
8223 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008224 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008225 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008226 /*
8227 * Check for illegal attributes.
8228 */
8229 attr = node->properties;
8230 while (attr != NULL) {
8231 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008232 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008233 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8234 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8235 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236 xmlSchemaPIllegalAttrErr(ctxt,
8237 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8238 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008239 }
8240 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008241 xmlSchemaPIllegalAttrErr(ctxt,
8242 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8243 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008244 }
8245 attr = attr->next;
8246 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008248 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8249 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 /*
8252 * Create a reference item as the term; it will be substituted for
8253 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008254 */
8255 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8257 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8258 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8259 /*
8260 * And now for the children...
8261 */
8262 child = node->children;
8263 /* TODO: Is annotation even allowed for a model group reference? */
8264 if (IS_SCHEMA(child, "annotation")) {
8265 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008267 */
8268 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8269 child = child->next;
8270 }
8271 if (child != NULL) {
8272 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008274 NULL, NULL, node, child, NULL,
8275 "(annotation?)");
8276 }
8277 /*
8278 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8279 */
8280 if ((min == 0) && (max == 0))
8281 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008282 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008283 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8284 return ((xmlSchemaTreeItemPtr) item);
8285}
8286
8287/**
8288 * xmlSchemaParseModelGroupDefinition:
8289 * @ctxt: a schema validation context
8290 * @schema: the schema being built
8291 * @node: a subtree containing XML Schema informations
8292 *
8293 * Parses a XML schema model group definition.
8294 * *WARNING* this interface is highly subject to change
8295 *
8296 * Returns -1 in case of error, 0 if the declaration is improper and
8297 * 1 in case of success.
8298 */
8299static xmlSchemaModelGroupDefPtr
8300xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8301 xmlSchemaPtr schema,
8302 xmlNodePtr node)
8303{
8304 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008305 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008306 xmlAttrPtr attr;
8307 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008308
8309 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008310 return (NULL);
8311
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008312 attr = xmlSchemaGetPropNode(node, "name");
8313 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008314 xmlSchemaPMissingAttrErr(ctxt,
8315 XML_SCHEMAP_S4S_ATTR_MISSING,
8316 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008317 "name", NULL);
8318 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008319 } else if (xmlSchemaPValAttrNode(ctxt,
8320 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008321 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8322 return (NULL);
8323 }
8324 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8325 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008326 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008327 /*
8328 * Check for illegal attributes.
8329 */
8330 attr = node->properties;
8331 while (attr != NULL) {
8332 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008333 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008334 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 xmlSchemaPIllegalAttrErr(ctxt,
8336 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8337 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008338 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008339 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008340 xmlSchemaPIllegalAttrErr(ctxt,
8341 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8342 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008343 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008344 attr = attr->next;
8345 }
8346 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8347 /*
8348 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008349 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008350 child = node->children;
8351 if (IS_SCHEMA(child, "annotation")) {
8352 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8353 child = child->next;
8354 }
8355 if (IS_SCHEMA(child, "all")) {
8356 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8357 XML_SCHEMA_TYPE_ALL, 0);
8358 child = child->next;
8359 } else if (IS_SCHEMA(child, "choice")) {
8360 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8361 XML_SCHEMA_TYPE_CHOICE, 0);
8362 child = child->next;
8363 } else if (IS_SCHEMA(child, "sequence")) {
8364 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8365 XML_SCHEMA_TYPE_SEQUENCE, 0);
8366 child = child->next;
8367 }
8368 if (child != NULL) {
8369 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008370 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8371 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008372 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008373 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008374
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008375 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008376}
8377
8378/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008379 * xmlSchemaCleanupDoc:
8380 * @ctxt: a schema validation context
8381 * @node: the root of the document.
8382 *
8383 * removes unwanted nodes in a schemas document tree
8384 */
8385static void
8386xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8387{
8388 xmlNodePtr delete, cur;
8389
8390 if ((ctxt == NULL) || (root == NULL)) return;
8391
8392 /*
8393 * Remove all the blank text nodes
8394 */
8395 delete = NULL;
8396 cur = root;
8397 while (cur != NULL) {
8398 if (delete != NULL) {
8399 xmlUnlinkNode(delete);
8400 xmlFreeNode(delete);
8401 delete = NULL;
8402 }
8403 if (cur->type == XML_TEXT_NODE) {
8404 if (IS_BLANK_NODE(cur)) {
8405 if (xmlNodeGetSpacePreserve(cur) != 1) {
8406 delete = cur;
8407 }
8408 }
8409 } else if ((cur->type != XML_ELEMENT_NODE) &&
8410 (cur->type != XML_CDATA_SECTION_NODE)) {
8411 delete = cur;
8412 goto skip_children;
8413 }
8414
8415 /*
8416 * Skip to next node
8417 */
8418 if (cur->children != NULL) {
8419 if ((cur->children->type != XML_ENTITY_DECL) &&
8420 (cur->children->type != XML_ENTITY_REF_NODE) &&
8421 (cur->children->type != XML_ENTITY_NODE)) {
8422 cur = cur->children;
8423 continue;
8424 }
8425 }
8426 skip_children:
8427 if (cur->next != NULL) {
8428 cur = cur->next;
8429 continue;
8430 }
8431
8432 do {
8433 cur = cur->parent;
8434 if (cur == NULL)
8435 break;
8436 if (cur == root) {
8437 cur = NULL;
8438 break;
8439 }
8440 if (cur->next != NULL) {
8441 cur = cur->next;
8442 break;
8443 }
8444 } while (cur != NULL);
8445 }
8446 if (delete != NULL) {
8447 xmlUnlinkNode(delete);
8448 xmlFreeNode(delete);
8449 delete = NULL;
8450 }
8451}
8452
William M. Brack2f2a6632004-08-20 23:09:47 +00008453
8454/**
8455 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008456 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008457 * @ctxt: a schema validation context
8458 * @schemaLocation: an URI defining where to find the imported schema
8459 *
8460 * import a XML schema
8461 * *WARNING* this interface is highly subject to change
8462 *
8463 * Returns -1 in case of error and 1 in case of success.
8464 */
8465#if 0
8466static xmlSchemaImportPtr
8467xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8468 const xmlChar *schemaLocation)
8469{
8470 xmlSchemaImportPtr import;
8471 xmlSchemaParserCtxtPtr newctxt;
8472
8473 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8474 if (newctxt == NULL) {
8475 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8476 NULL);
8477 return (NULL);
8478 }
8479 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8480 /* Keep the same dictionnary for parsing, really */
8481 xmlDictReference(ctxt->dict);
8482 newctxt->dict = ctxt->dict;
8483 newctxt->includes = 0;
8484 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8485
8486 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8487 ctxt->userData);
8488
8489 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8490 if (import == NULL) {
8491 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8492 NULL);
8493 xmlSchemaFreeParserCtxt(newctxt);
8494 return (NULL);
8495 }
8496
8497 memset(import, 0, sizeof(xmlSchemaImport));
8498 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8499 import->schema = xmlSchemaParse(newctxt);
8500
8501 if (import->schema == NULL) {
8502 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008503 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008504 "Failed to import schema from location \"%s\".\n",
8505 schemaLocation, NULL);
8506
8507 xmlSchemaFreeParserCtxt(newctxt);
8508 /* The schemaLocation is held by the dictionary.
8509 if (import->schemaLocation != NULL)
8510 xmlFree((xmlChar *)import->schemaLocation);
8511 */
8512 xmlFree(import);
8513 return NULL;
8514 }
8515
8516 xmlSchemaFreeParserCtxt(newctxt);
8517 return import;
8518}
8519#endif
8520
8521static void
8522xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8523{
8524 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8525 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8526
8527 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8528 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8529
8530 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8531 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8532 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8533 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8534 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8535 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8536 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8537 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8538
8539 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8540 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8541 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8542 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8543 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8544 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8545}
8546
8547static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008548xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008549 xmlSchemaPtr schema,
8550 xmlNodePtr node)
8551{
8552 xmlAttrPtr attr;
8553 const xmlChar *val;
8554
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008555 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8556 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008557 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008558 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8559 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008560 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008561 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8562
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008563 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008564 if (attr != NULL) {
8565 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008567 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008568 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008569 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008570 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008571 "(qualified | unqualified)", val, NULL, NULL, NULL);
8572 }
8573 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008574
8575 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008576 if (attr != NULL) {
8577 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008578 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008579 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008580 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008581 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008583 "(qualified | unqualified)", val, NULL, NULL, NULL);
8584 }
8585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008586
8587 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008588 if (attr != NULL) {
8589 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8590 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8591 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8592 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8593 -1,
8594 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8595 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8596 xmlSchemaPSimpleTypeErr(ctxt,
8597 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008598 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008599 "(#all | List of (extension | restriction | list | union))",
8600 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008602 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603
8604 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008605 if (attr != NULL) {
8606 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8607 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8608 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8609 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8610 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8611 xmlSchemaPSimpleTypeErr(ctxt,
8612 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008613 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008614 "(#all | List of (extension | restriction | substitution))",
8615 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008616 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008617 }
8618}
8619
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008620/**
8621 * xmlSchemaParseSchemaTopLevel:
8622 * @ctxt: a schema validation context
8623 * @schema: the schemas
8624 * @nodes: the list of top level nodes
8625 *
8626 * Returns the internal XML Schema structure built from the resource or
8627 * NULL in case of error
8628 */
8629static void
8630xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8631 xmlSchemaPtr schema, xmlNodePtr nodes)
8632{
8633 xmlNodePtr child;
8634 xmlSchemaAnnotPtr annot;
8635
8636 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8637 return;
8638
8639 child = nodes;
8640 while ((IS_SCHEMA(child, "include")) ||
8641 (IS_SCHEMA(child, "import")) ||
8642 (IS_SCHEMA(child, "redefine")) ||
8643 (IS_SCHEMA(child, "annotation"))) {
8644 if (IS_SCHEMA(child, "annotation")) {
8645 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8646 if (schema->annot == NULL)
8647 schema->annot = annot;
8648 else
8649 xmlSchemaFreeAnnot(annot);
8650 } else if (IS_SCHEMA(child, "import")) {
8651 xmlSchemaParseImport(ctxt, schema, child);
8652 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008653 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008654 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008655 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008656 } else if (IS_SCHEMA(child, "redefine")) {
8657 TODO
8658 }
8659 child = child->next;
8660 }
8661 while (child != NULL) {
8662 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008663 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008664 child = child->next;
8665 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008666 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008667 child = child->next;
8668 } else if (IS_SCHEMA(child, "element")) {
8669 xmlSchemaParseElement(ctxt, schema, child, 1);
8670 child = child->next;
8671 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008672 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008673 child = child->next;
8674 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008675 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008676 child = child->next;
8677 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008678 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 child = child->next;
8680 } else if (IS_SCHEMA(child, "notation")) {
8681 xmlSchemaParseNotation(ctxt, schema, child);
8682 child = child->next;
8683 } else {
8684 xmlSchemaPErr2(ctxt, NULL, child,
8685 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008686 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008687 child->name, NULL);
8688 child = child->next;
8689 }
8690 while (IS_SCHEMA(child, "annotation")) {
8691 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8692 if (schema->annot == NULL)
8693 schema->annot = annot;
8694 else
8695 xmlSchemaFreeAnnot(annot);
8696 child = child->next;
8697 }
8698 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008699 ctxt->parentItem = NULL;
8700 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701}
8702
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008703static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008705 xmlHashTablePtr *imports,
8706 const xmlChar *nsName)
8707{
8708 xmlSchemaImportPtr ret;
8709
8710 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008711 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008712 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008713 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008714 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8715 NULL, NULL, (xmlNodePtr) ctxt->doc,
8716 "Internal error: failed to build the import table",
8717 NULL);
8718 return (NULL);
8719 }
8720 }
8721 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8722 if (ret == NULL) {
8723 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8724 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008725 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008726 memset(ret, 0, sizeof(xmlSchemaImport));
8727 if (nsName == NULL)
8728 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730
8731 return (ret);
8732}
8733
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008734/**
8735 * xmlSchemaNewParserCtxtUseDict:
8736 * @URL: the location of the schema
8737 * @dict: the dictionary to be used
8738 *
8739 * Create an XML Schemas parse context for that file/resource expected
8740 * to contain an XML Schemas file.
8741 *
8742 * Returns the parser context or NULL in case of error
8743 */
8744static xmlSchemaParserCtxtPtr
8745xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8746{
8747 xmlSchemaParserCtxtPtr ret;
8748 /*
8749 if (URL == NULL)
8750 return (NULL);
8751 */
8752
8753 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8754 if (ret == NULL) {
8755 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8756 NULL);
8757 return (NULL);
8758 }
8759 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8760 ret->dict = dict;
8761 xmlDictReference(dict);
8762 if (URL != NULL)
8763 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8764 ret->includes = 0;
8765 return (ret);
8766}
8767
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008768static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008769xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8770{
8771 if (vctxt->pctxt == NULL) {
8772 if (vctxt->schema != NULL)
8773 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8774 else
8775 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8776 if (vctxt->pctxt == NULL) {
8777 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8778 "failed to create a temp. parser context");
8779 return (-1);
8780 }
8781 /* TODO: Pass user data. */
8782 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8783 }
8784 return (0);
8785}
8786
8787static int
8788xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008789 xmlSchemaPtr schema,
8790 xmlNodePtr node,
8791 const xmlChar *nsName,
8792 const xmlChar *location,
8793 xmlDocPtr *doc,
8794 const xmlChar **targetNamespace,
8795 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008796{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008797 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008798 xmlParserCtxtPtr parserCtxt;
8799 xmlSchemaImportPtr import;
8800 const xmlChar *ns;
8801 xmlNodePtr root;
8802
8803 /*
8804 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8805 * <xsi:noNamespaceSchemaLocation>.
8806 */
8807 *doc = NULL;
8808 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008809 * Given that the schemaLocation [attribute] is only a hint, it is open
8810 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008811 * namespace, regardless of the ·actual value· of schemaLocation, but
8812 * such a strategy risks missing useful information when new
8813 * schemaLocations are offered.
8814 *
8815 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8816 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8817 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008818 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008819 */
8820 if (location == NULL) {
8821 /*
8822 * Schema Document Location Strategy:
8823 *
8824 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008825 * either as a resource which is an XML document or a <schema> element
8826 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008827 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008828 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008829 *
8830 * NOTE: Those stategies are not supported, so we will skip.
8831 */
8832 return (0);
8833 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008835 ns = XML_SCHEMAS_NO_NAMESPACE;
8836 else
8837 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008838
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008839 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008840 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008841 /*
8842 * There was a valid resource for the specified namespace already
8843 * defined, so skip.
8844 * TODO: This might be changed someday to allow import of
8845 * components from multiple documents for a single target namespace.
8846 */
8847 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008848 }
8849 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8850 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8851 else {
8852 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8853 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8854 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008855 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008856 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008857 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008858 * 2 Based on the location URI, identify an existing schema document,
8859 * either as a resource which is an XML document or a <schema> element
8860 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008861 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008863 * web which is or contains or references a <schema> element;
8864 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8865 *
8866 */
8867 if ((absolute == 0) && (node != NULL)) {
8868 xmlChar *base, *URI;
8869
8870 base = xmlNodeGetBase(node->doc, node);
8871 if (base == NULL) {
8872 URI = xmlBuildURI(location, node->doc->URL);
8873 } else {
8874 URI = xmlBuildURI(location, base);
8875 xmlFree(base);
8876 }
8877 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008878 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008879 xmlFree(URI);
8880 }
8881 }
8882 parserCtxt = xmlNewParserCtxt();
8883 if (parserCtxt == NULL) {
8884 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8885 "allocating a parser context", NULL);
8886 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 }
8888 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008889 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008890 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008891 xmlDictReference(parserCtxt->dict);
8892 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008893 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008894 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008895 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008896 * 2.1 The referent is (a fragment of) a resource which is an
8897 * XML document (see clause 1.1), which in turn corresponds to
8898 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008899 * set, which in turn corresponds to a valid schema.
8900 * TODO: What to do with the "fragment" stuff?
8901 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008902 * 2.2 The referent is a <schema> element information item in
8903 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008905 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008906 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008907 */
8908 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008909 xmlErrorPtr lerr;
8910 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008911 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008912 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008913 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008914 * If the doc is NULL and the parser error is an IO error we
8915 * will assume that the resource could not be located or accessed.
8916 *
8917 * TODO: Try to find specific error codes to react only on
8918 * localisation failures.
8919 *
8920 * TODO, FIXME: Check the spec: is a namespace added to the imported
8921 * namespaces, even if the schemaLocation did not provide
8922 * a resource? I guess so, since omitting the "schemaLocation"
8923 * attribute, imports a namespace as well.
8924 */
8925 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008926 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008927 xmlFreeParserCtxt(parserCtxt);
8928 return(0);
8929 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008933 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008934 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008935 xmlFreeParserCtxt(parserCtxt);
8936 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8937 }
8938 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008939
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008940 root = xmlDocGetRootElement(*doc);
8941 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008942 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008943 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008944 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008945 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008947 xmlFreeDoc(*doc);
8948 *doc = NULL;
8949 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008950 }
8951
8952 xmlSchemaCleanupDoc(pctxt, root);
8953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008954 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008956 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFreeDoc(*doc);
8961 *doc = NULL;
8962 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008963 }
8964 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008965 /*
8966 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 if (nsName == NULL) {
8969 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008970 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008971 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008972 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008973 "The XML schema to be imported is not expected "
8974 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008976 xmlFreeDoc(*doc);
8977 *doc = NULL;
8978 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8979 }
8980 } else {
8981 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008986 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008987 xmlFreeDoc(*doc);
8988 *doc = NULL;
8989 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8990 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008991 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008992 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008993 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008994 "The XML schema to be imported is expected to have a "
8995 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 "its target namespace of '%s'",
8997 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 xmlFreeDoc(*doc);
8999 *doc = NULL;
9000 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9001 }
9002 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009003 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009004 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009005 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9006 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009007 xmlFreeDoc(*doc);
9008 *doc = NULL;
9009 return (-1);
9010 }
9011 import->schemaLocation = location;
9012 import->doc = *doc;
9013 return (0);
9014}
William M. Brack2f2a6632004-08-20 23:09:47 +00009015
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009016static void
9017xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9018 xmlSchemaPtr schema,
9019 const xmlChar *targetNamespace,
9020 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009022 const xmlChar *oldURL, **oldLocImps, *oldTNS;
9023 int oldFlags, oldNumLocImps, oldSizeLocImps;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009024
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009025 /*
9026 * Save and reset the context & schema.
9027 */
9028 oldURL = pctxt->URL;
9029 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009030 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009031 oldLocImps = pctxt->localImports;
9032 pctxt->localImports = NULL;
9033 oldNumLocImps = pctxt->nbLocalImports;
9034 pctxt->nbLocalImports = 0;
9035 oldSizeLocImps = pctxt->sizeLocalImports;
9036 pctxt->sizeLocalImports = 0;
9037 oldFlags = schema->flags;
9038 xmlSchemaClearSchemaDefaults(schema);
9039 oldTNS = schema->targetNamespace;
9040 schema->targetNamespace = targetNamespace;
9041 /*
9042 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009043 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009044 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9045 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9046 /*
9047 * Restore the context & schema.
9048 */
9049 schema->flags = oldFlags;
9050 schema->targetNamespace = oldTNS;
9051 if (pctxt->localImports != NULL)
9052 xmlFree((xmlChar *) pctxt->localImports);
9053 pctxt->localImports = oldLocImps;
9054 pctxt->nbLocalImports = oldNumLocImps;
9055 pctxt->sizeLocalImports = oldSizeLocImps;
9056 pctxt->URL = oldURL;
9057}
9058
William M. Brack2f2a6632004-08-20 23:09:47 +00009059/**
9060 * xmlSchemaParseImport:
9061 * @ctxt: a schema validation context
9062 * @schema: the schema being built
9063 * @node: a subtree containing XML Schema informations
9064 *
9065 * parse a XML schema Import definition
9066 * *WARNING* this interface is highly subject to change
9067 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009068 * Returns 0 in case of success, a positive error code if
9069 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009070 */
9071static int
9072xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9073 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009074{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009075 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009076 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009077 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009078 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009079 xmlAttrPtr attr;
9080 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009081 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009082
9083 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9084 return (-1);
9085
9086 /*
9087 * Check for illegal attributes.
9088 */
9089 attr = node->properties;
9090 while (attr != NULL) {
9091 if (attr->ns == NULL) {
9092 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9093 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9094 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009095 xmlSchemaPIllegalAttrErr(ctxt,
9096 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9097 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009098 }
9099 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009100 xmlSchemaPIllegalAttrErr(ctxt,
9101 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9102 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009103 }
9104 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009105 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009106 /*
9107 * Extract and validate attributes.
9108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009109 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9110 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009111 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009112 xmlSchemaPSimpleTypeErr(ctxt,
9113 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9114 NULL, node,
9115 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009116 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009117 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9118 }
9119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009120 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9121 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009122 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009123 xmlSchemaPSimpleTypeErr(ctxt,
9124 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9125 NULL, node,
9126 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009127 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009128 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009130 /*
9131 * And now for the children...
9132 */
9133 child = node->children;
9134 if (IS_SCHEMA(child, "annotation")) {
9135 /*
9136 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009137 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009138 */
9139 child = child->next;
9140 }
9141 if (child != NULL) {
9142 xmlSchemaPContentErr(ctxt,
9143 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9144 NULL, NULL, node, child, NULL,
9145 "(annotation?)");
9146 }
9147 /*
9148 * Apply additional constraints.
9149 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009150 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009152 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9153 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009154 * targetNamespace [attribute].
9155 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009156 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009157 xmlSchemaPCustomErr(ctxt,
9158 XML_SCHEMAP_SRC_IMPORT_1_1,
9159 NULL, NULL, node,
9160 "The value of the attribute 'namespace' must not match "
9161 "the target namespace '%s' of the importing schema",
9162 schema->targetNamespace);
9163 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9164 }
9165 } else {
9166 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009167 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009168 * <schema> must have a targetNamespace [attribute].
9169 */
9170 if (schema->targetNamespace == NULL) {
9171 xmlSchemaPCustomErr(ctxt,
9172 XML_SCHEMAP_SRC_IMPORT_1_2,
9173 NULL, NULL, node,
9174 "The attribute 'namespace' must be existent if "
9175 "the importing schema has no target namespace",
9176 NULL);
9177 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9178 }
9179 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009180 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009181 * Add the namespace to the list of locally imported namespace.
9182 */
9183 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009184 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009185 sizeof(const xmlChar*));
9186 ctxt->sizeLocalImports = 10;
9187 ctxt->nbLocalImports = 0;
9188 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9189 ctxt->sizeLocalImports *= 2;
9190 ctxt->localImports = (const xmlChar **) xmlRealloc(
9191 (xmlChar **) ctxt->localImports,
9192 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9193 }
9194 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9195 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009196 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009197 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009198 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9199 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009200 schemaLocation, &doc, &targetNamespace, 0);
9201 if (ret != 0) {
9202 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009203 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009204 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009205 } else if (doc != NULL) {
9206 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9207 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009208 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009209
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009210 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009211}
9212
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009213/**
9214 * xmlSchemaParseInclude:
9215 * @ctxt: a schema validation context
9216 * @schema: the schema being built
9217 * @node: a subtree containing XML Schema informations
9218 *
9219 * parse a XML schema Include definition
9220 *
William M. Bracke7091952004-05-11 15:09:58 +00009221 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009222 * 1 in case of success.
9223 */
9224static int
9225xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9226 xmlNodePtr node)
9227{
9228 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009229 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009230 xmlDocPtr doc = NULL;
9231 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009232 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009233 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009234 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009235 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009236
9237
9238 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9239 return (-1);
9240
9241 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009242 * Check for illegal attributes.
9243 */
9244 attr = node->properties;
9245 while (attr != NULL) {
9246 if (attr->ns == NULL) {
9247 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9248 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009249 xmlSchemaPIllegalAttrErr(ctxt,
9250 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9251 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009252 }
9253 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009254 xmlSchemaPIllegalAttrErr(ctxt,
9255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9256 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009257 }
9258 attr = attr->next;
9259 }
9260 /*
9261 * Extract and validate attributes.
9262 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009263 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009264 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009265 * Preliminary step, extract the URI-Reference for the include and
9266 * make an URI from the base.
9267 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9269 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009270 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009271 xmlChar *uri = NULL;
9272
9273 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9274 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009275 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009276 base = xmlNodeGetBase(node->doc, node);
9277 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009278 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009279 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009280 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009281 xmlFree(base);
9282 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009283 if (uri == NULL) {
9284 xmlSchemaPErr(ctxt,
9285 node,
9286 XML_SCHEMAP_INTERNAL,
9287 "Internal error: xmlSchemaParseInclude, "
9288 "could not build an URI from the schemaLocation.\n",
9289 NULL, NULL);
9290 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009291 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009292 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9293 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009294 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009295 xmlSchemaPMissingAttrErr(ctxt,
9296 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9297 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009298 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009299 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009300 /*
9301 * And now for the children...
9302 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009303 child = node->children;
9304 while (IS_SCHEMA(child, "annotation")) {
9305 /*
9306 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009307 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009308 */
9309 child = child->next;
9310 }
9311 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009312 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009313 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9314 NULL, NULL, node, child, NULL,
9315 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009316 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009317 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009318 * Report self-inclusion.
9319 */
9320 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9321 xmlSchemaPCustomErr(ctxt,
9322 XML_SCHEMAP_SRC_INCLUDE,
9323 NULL, NULL, node,
9324 "The schema document '%s' cannot include itself.",
9325 schemaLocation);
9326 return (XML_SCHEMAP_SRC_INCLUDE);
9327 }
9328 /*
9329 * Check if this one was already processed to avoid incorrect
9330 * duplicate component errors and infinite circular inclusion.
9331 */
9332 include = schema->includes;
9333 while (include != NULL) {
9334 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9335 targetNamespace = include->origTargetNamespace;
9336 if (targetNamespace == NULL) {
9337 /*
9338 * Chameleon include: skip only if it was build for
9339 * the targetNamespace of the including schema.
9340 */
9341 if (xmlStrEqual(schema->targetNamespace,
9342 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009343 goto check_targetNamespace;
9344 }
9345 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009346 goto check_targetNamespace;
9347 }
9348 }
9349 include = include->next;
9350 }
9351 /*
9352 * First step is to parse the input document into an DOM/Infoset
9353 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009354 */
9355 parserCtxt = xmlNewParserCtxt();
9356 if (parserCtxt == NULL) {
9357 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9358 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009359 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009360 }
9361
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009362 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9363 xmlDictFree(parserCtxt->dict);
9364 parserCtxt->dict = ctxt->dict;
9365 xmlDictReference(parserCtxt->dict);
9366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009367
9368 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009369 NULL, SCHEMAS_PARSE_OPTIONS);
9370 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009371 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009372 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009373 * TODO: It is not an error for the ·actual value· of the
9374 * schemaLocation [attribute] to fail to resolve it all, in which
9375 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009376 * So do we need a warning report here?
9377 */
9378 xmlSchemaPCustomErr(ctxt,
9379 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009380 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009381 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009382 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009383 }
9384
9385 /*
9386 * Then extract the root of the schema
9387 */
9388 root = xmlDocGetRootElement(doc);
9389 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009390 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009391 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009392 NULL, NULL, node,
9393 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009395 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009396 }
9397
9398 /*
9399 * Remove all the blank text nodes
9400 */
9401 xmlSchemaCleanupDoc(ctxt, root);
9402
9403 /*
9404 * Check the schemas top level element
9405 */
9406 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009407 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009408 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009409 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009410 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009411 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009412 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009413 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009414
William M. Brack2f2a6632004-08-20 23:09:47 +00009415 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009416 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009417 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9418 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009419 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9420 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009421check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009422 if (targetNamespace != NULL) {
9423 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009424 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009425 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009426 NULL, NULL, node,
9427 "The target namespace of the included schema "
9428 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009429 "has no target namespace",
9430 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009431 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009432 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9433 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009434 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009435 NULL, NULL, node,
9436 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009437 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009438 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009439 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009441 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009443 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009444 } else
9445 wasConvertingNs = 1;
9446 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009447
9448 if (include != NULL)
9449 goto exit;
9450
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009451 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009452 * URGENT TODO: If the schema is a chameleon-include then copy the
9453 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009454 * of those components, do nothing otherwise.
9455 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009456 * for every destinct including targetNamespace; thus not performant at
9457 * the moment.
9458 * TODO: Check when the namespace in wildcards for chameleons needs
9459 * to be converted: before we built wildcard intersections or after.
9460 */
9461 /*
9462 * Register the include.
9463 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009464 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9465 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009466 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9467 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009468 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009469 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009470 include->next = schema->includes;
9471 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009472 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473 * TODO: Use the resolved URI for the this location, since it might
9474 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009475 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009476 include->schemaLocation = schemaLocation;
9477 include->doc = doc;
9478 /*
9479 * In case of chameleons, the original target namespace will differ
9480 * from the resulting namespace.
9481 */
9482 include->origTargetNamespace = targetNamespace;
9483 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009484#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009485 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009486 xmlGenericError(xmlGenericErrorContext,
9487 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9488 " into TNS '%s'\n", schemaLocation,
9489 targetNamespace, schema->targetNamespace);
9490 else
9491 xmlGenericError(xmlGenericErrorContext,
9492 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9493 targetNamespace);
9494#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009495 /*
9496 * Compile the included schema.
9497 */
9498 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9499
9500exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009501 /*
9502 * Remove the converting flag.
9503 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009504 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009505 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009506 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009507 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009508
9509exit_invalid:
9510 if (doc != NULL) {
9511 if (include != NULL)
9512 include->doc = NULL;
9513 xmlFreeDoc(doc);
9514 }
9515 return (ctxt->err);
9516
9517exit_failure:
9518 if (doc != NULL) {
9519 if (include != NULL)
9520 include->doc = NULL;
9521 xmlFreeDoc(doc);
9522 }
9523 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009524}
9525
9526/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009527 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009528 * @ctxt: a schema validation context
9529 * @schema: the schema being built
9530 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009531 * @type: the "compositor" type
9532 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009533 *
9534 * parse a XML schema Sequence definition
9535 * *WARNING* this interface is highly subject to change
9536 *
William M. Bracke7091952004-05-11 15:09:58 +00009537 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009538 * 1 in case of success.
9539 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009540static xmlSchemaTreeItemPtr
9541xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9542 xmlNodePtr node, xmlSchemaTypeType type,
9543 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009544{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009545 xmlSchemaModelGroupPtr item;
9546 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009547 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009548 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009549 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009550 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009551
9552 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009553 return (NULL);
9554 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009555 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009556 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009557 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9558 if (item == NULL)
9559 return (NULL);
9560
9561 if (withParticle) {
9562 if (type == XML_SCHEMA_TYPE_ALL) {
9563 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009564 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009565 } else {
9566 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009567 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9568 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9569 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009571 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9572 /*
9573 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009574 */
9575 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9576 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009577 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009578 particle->children = (xmlSchemaTreeItemPtr) item;
9579 /*
9580 * Check for illegal attributes.
9581 */
9582 attr = node->properties;
9583 while (attr != NULL) {
9584 if (attr->ns == NULL) {
9585 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9586 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9587 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009588 xmlSchemaPIllegalAttrErr(ctxt,
9589 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9590 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 }
9592 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009593 xmlSchemaPIllegalAttrErr(ctxt,
9594 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9595 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009596 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009597 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009598 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 } else {
9600 /*
9601 * Check for illegal attributes.
9602 */
9603 attr = node->properties;
9604 while (attr != NULL) {
9605 if (attr->ns == NULL) {
9606 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009607 xmlSchemaPIllegalAttrErr(ctxt,
9608 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9609 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009610 }
9611 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009612 xmlSchemaPIllegalAttrErr(ctxt,
9613 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9614 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009615 }
9616 attr = attr->next;
9617 }
9618
William M. Brack2f2a6632004-08-20 23:09:47 +00009619 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009620
William M. Brack2f2a6632004-08-20 23:09:47 +00009621 /*
9622 * Extract and validate attributes.
9623 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009624 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009625 /*
9626 * And now for the children...
9627 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009628 child = node->children;
9629 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009630 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009631 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009632 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009633 oldcontainer = ctxt->container;
9634 ctxt->container = container;
9635 if (type == XML_SCHEMA_TYPE_ALL) {
9636 xmlSchemaParticlePtr part, last = NULL;
9637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009638 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009639 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9640 schema, child, 0);
9641 if (part != NULL) {
9642 if (part->minOccurs > 1)
9643 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009644 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009645 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9646 if (part->maxOccurs > 1)
9647 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009648 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 "Invalid value for maxOccurs (must be 0 or 1)",
9650 NULL);
9651 if (last == NULL)
9652 item->children = (xmlSchemaTreeItemPtr) part;
9653 else
9654 last->next = (xmlSchemaTreeItemPtr) part;
9655 last = part;
9656 }
9657 child = child->next;
9658 }
9659 if (child != NULL) {
9660 xmlSchemaPContentErr(ctxt,
9661 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9662 NULL, NULL, node, child, NULL,
9663 "(annotation?, (annotation?, element*)");
9664 }
9665 } else {
9666 /* choice + sequence */
9667 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9668
9669 while ((IS_SCHEMA(child, "element")) ||
9670 (IS_SCHEMA(child, "group")) ||
9671 (IS_SCHEMA(child, "any")) ||
9672 (IS_SCHEMA(child, "choice")) ||
9673 (IS_SCHEMA(child, "sequence"))) {
9674
9675 if (IS_SCHEMA(child, "element")) {
9676 part = (xmlSchemaTreeItemPtr)
9677 xmlSchemaParseElement(ctxt, schema, child, 0);
9678 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009679 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009680 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9681 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009683 xmlSchemaParseAny(ctxt, schema, child);
9684 } else if (IS_SCHEMA(child, "choice")) {
9685 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9686 XML_SCHEMA_TYPE_CHOICE, 1);
9687 } else if (IS_SCHEMA(child, "sequence")) {
9688 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9689 XML_SCHEMA_TYPE_SEQUENCE, 1);
9690 }
9691 if (part != NULL) {
9692 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009693 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009694 else
9695 last->next = part;
9696 last = part;
9697 }
9698 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009699 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009700 if (child != NULL) {
9701 xmlSchemaPContentErr(ctxt,
9702 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9703 NULL, NULL, node, child, NULL,
9704 "(annotation?, (element | group | choice | sequence | any)*)");
9705 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009706 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009707 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009708 if (withParticle) {
9709 if ((min == 0) && (max == 0))
9710 return (NULL);
9711 else
9712 return ((xmlSchemaTreeItemPtr) particle);
9713 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009715}
9716
9717/**
9718 * xmlSchemaParseRestriction:
9719 * @ctxt: a schema validation context
9720 * @schema: the schema being built
9721 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009722 *
9723 * parse a XML schema Restriction definition
9724 * *WARNING* this interface is highly subject to change
9725 *
9726 * Returns the type definition or NULL in case of error
9727 */
9728static xmlSchemaTypePtr
9729xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009730 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009731{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009732 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009733 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009734 char buf[30];
9735 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009736 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009737
9738 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9739 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009740 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009741 type = ctxt->ctxtType;
9742 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009743
9744 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009745 * TODO: Is the container needed at all? the anonymous
9746 * items inside should generate unique names already.
9747 */
9748 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009749 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009750 /*
9751 * Check for illegal attributes.
9752 */
9753 attr = node->properties;
9754 while (attr != NULL) {
9755 if (attr->ns == NULL) {
9756 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9757 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009758 xmlSchemaPIllegalAttrErr(ctxt,
9759 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9760 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009761 }
9762 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009763 xmlSchemaPIllegalAttrErr(ctxt,
9764 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9765 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009766 }
9767 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009768 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009769 /*
9770 * Extract and validate attributes.
9771 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009772 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009773 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009774 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009775 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009776 /*
9777 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9778 * among its [children]), the simple type definition which is
9779 * the {content type} of the type definition ·resolved· to by
9780 * the ·actual value· of the base [attribute]"
9781 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009782 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009783 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009784 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009785 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009786 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009787 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009788 XML_SCHEMAP_S4S_ATTR_MISSING,
9789 type, node, "base", NULL);
9790 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009791 /*
9792 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009793 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009794 child = node->children;
9795 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009796 /*
9797 * Add the annotation to the simple type ancestor.
9798 */
9799 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9800 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009801 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009802 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009803 oldcontainer = ctxt->container;
9804 ctxt->container = container;
9805 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9806 /*
9807 * Corresponds to <simpleType><restriction><simpleType>.
9808 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009809 if (IS_SCHEMA(child, "simpleType")) {
9810 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009811 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009812 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009813 * Either the base [attribute] or the simpleType [child] of the
9814 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009815 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009816 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009817 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009818 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009819 "The attribute 'base' and the <simpleType> child are "
9820 "mutually exclusive", NULL);
9821 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009822 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009823 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009826 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009827 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009828 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9829 NULL, NULL, node, child,
9830 "Either the attribute 'base' or a <simpleType> child "
9831 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009832 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009833 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9834 /*
9835 * Corresponds to <complexType><complexContent><restriction>...
9836 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009837 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009838 * Model groups <all>, <choice> and <sequence>.
9839 */
9840 if (IS_SCHEMA(child, "all")) {
9841 type->subtypes = (xmlSchemaTypePtr)
9842 xmlSchemaParseModelGroup(ctxt, schema, child,
9843 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009844 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009845 } else if (IS_SCHEMA(child, "choice")) {
9846 type->subtypes = (xmlSchemaTypePtr)
9847 xmlSchemaParseModelGroup(ctxt,
9848 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9849 child = child->next;
9850 } else if (IS_SCHEMA(child, "sequence")) {
9851 type->subtypes = (xmlSchemaTypePtr)
9852 xmlSchemaParseModelGroup(ctxt, schema, child,
9853 XML_SCHEMA_TYPE_SEQUENCE, 1);
9854 child = child->next;
9855 /*
9856 * Model group reference <group>.
9857 */
9858 } else if (IS_SCHEMA(child, "group")) {
9859 type->subtypes = (xmlSchemaTypePtr)
9860 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9861 child = child->next;
9862 }
9863 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009864 /*
9865 * Corresponds to <complexType><simpleContent><restriction>...
9866 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009867 * "1.1 the simple type definition corresponding to the <simpleType>
9868 * among the [children] of <restriction> if there is one;"
9869 */
9870 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009871 /*
9872 * We will store the to-be-restricted simple type in
9873 * type->contentTypeDef *temporarily*.
9874 */
9875 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009876 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009877 if ( type->contentTypeDef == NULL)
9878 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 child = child->next;
9880 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009881 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009882
9883 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009884 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009885 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009886 /*
9887 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009888 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009889 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009890
Daniel Veillard01fa6152004-06-29 17:04:39 +00009891 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009892 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009893 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009894 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009895 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9896 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009897 * *Single Facet Value*
9898 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009899 while ((IS_SCHEMA(child, "minInclusive")) ||
9900 (IS_SCHEMA(child, "minExclusive")) ||
9901 (IS_SCHEMA(child, "maxInclusive")) ||
9902 (IS_SCHEMA(child, "maxExclusive")) ||
9903 (IS_SCHEMA(child, "totalDigits")) ||
9904 (IS_SCHEMA(child, "fractionDigits")) ||
9905 (IS_SCHEMA(child, "pattern")) ||
9906 (IS_SCHEMA(child, "enumeration")) ||
9907 (IS_SCHEMA(child, "whiteSpace")) ||
9908 (IS_SCHEMA(child, "length")) ||
9909 (IS_SCHEMA(child, "maxLength")) ||
9910 (IS_SCHEMA(child, "minLength"))) {
9911 facet = xmlSchemaParseFacet(ctxt, schema, child);
9912 if (facet != NULL) {
9913 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009914 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009915 else
9916 lastfacet->next = facet;
9917 lastfacet = facet;
9918 lastfacet->next = NULL;
9919 }
9920 child = child->next;
9921 }
9922 /*
9923 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924 */
9925 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009926 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009928 facet = type->facets;
9929 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009930 facetLink = (xmlSchemaFacetLinkPtr)
9931 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009932 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009933 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009934 xmlFree(facetLink);
9935 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009936 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009937 facetLink->facet = facet;
9938 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009939 if (lastFacetLink == NULL)
9940 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009941 else
9942 lastFacetLink->next = facetLink;
9943 lastFacetLink = facetLink;
9944 facet = facet->next;
9945 } while (facet != NULL);
9946 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009947 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009948 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9949 /*
9950 * Attribute uses/declarations.
9951 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009952 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009953 /*
9954 * Attribute wildcard.
9955 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009956 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009957 type->attributeWildcard =
9958 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009959 child = child->next;
9960 }
9961 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009962 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009963 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9964 xmlSchemaPContentErr(ctxt,
9965 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009966 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009967 "annotation?, (group | all | choice | sequence)?, "
9968 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009969 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 xmlSchemaPContentErr(ctxt,
9971 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009972 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009973 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9974 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9975 "length | minLength | maxLength | enumeration | whiteSpace | "
9976 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9977 } else {
9978 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009979 xmlSchemaPContentErr(ctxt,
9980 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009981 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009982 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9983 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9984 "length | minLength | maxLength | enumeration | whiteSpace | "
9985 "pattern)*))");
9986 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009987 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009988 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009989 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009990}
9991
9992/**
9993 * xmlSchemaParseExtension:
9994 * @ctxt: a schema validation context
9995 * @schema: the schema being built
9996 * @node: a subtree containing XML Schema informations
9997 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009998 * Parses an <extension>, which is found inside a
9999 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010000 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010001 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010002 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010003 */
10004static xmlSchemaTypePtr
10005xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010007{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010008 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010009 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010010 char buf[30];
10011 const xmlChar *oldcontainer, *container;
10012 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010013
10014 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10015 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010016 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010017 type = ctxt->ctxtType;
10018 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010019
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010020 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10021 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10022 /*
10023 * Check for illegal attributes.
10024 */
10025 attr = node->properties;
10026 while (attr != NULL) {
10027 if (attr->ns == NULL) {
10028 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10029 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010030 xmlSchemaPIllegalAttrErr(ctxt,
10031 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10032 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010033 }
10034 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010035 xmlSchemaPIllegalAttrErr(ctxt,
10036 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10037 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010038 }
10039 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010040 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010041
10042 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010043
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010044 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010045 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010046 */
10047 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010048 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10049 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010050 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010051 XML_SCHEMAP_S4S_ATTR_MISSING,
10052 NULL, node, "base", NULL);
10053 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 /*
10055 * And now for the children...
10056 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010057 child = node->children;
10058 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010059 /*
10060 * Add the annotation to the type ancestor.
10061 */
10062 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10063 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010064 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010065 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010066 oldcontainer = ctxt->container;
10067 ctxt->container = container;
10068 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10069 /*
10070 * Corresponds to <complexType><complexContent><extension>... and:
10071 *
10072 * Model groups <all>, <choice>, <sequence> and <group>.
10073 */
10074 if (IS_SCHEMA(child, "all")) {
10075 type->subtypes = (xmlSchemaTypePtr)
10076 xmlSchemaParseModelGroup(ctxt, schema,
10077 child, XML_SCHEMA_TYPE_ALL, 1);
10078 child = child->next;
10079 } else if (IS_SCHEMA(child, "choice")) {
10080 type->subtypes = (xmlSchemaTypePtr)
10081 xmlSchemaParseModelGroup(ctxt, schema,
10082 child, XML_SCHEMA_TYPE_CHOICE, 1);
10083 child = child->next;
10084 } else if (IS_SCHEMA(child, "sequence")) {
10085 type->subtypes = (xmlSchemaTypePtr)
10086 xmlSchemaParseModelGroup(ctxt, schema,
10087 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10088 child = child->next;
10089 } else if (IS_SCHEMA(child, "group")) {
10090 type->subtypes = (xmlSchemaTypePtr)
10091 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10092 child = child->next;
10093 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010094 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010095 if (child != NULL) {
10096 /*
10097 * Attribute uses/declarations.
10098 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010099 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 /*
10101 * Attribute wildcard.
10102 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010103 if (IS_SCHEMA(child, "anyAttribute")) {
10104 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010105 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10106 child = child->next;
10107 }
10108 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010109 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010110 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10111 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010112 xmlSchemaPContentErr(ctxt,
10113 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010114 NULL, NULL, node, child, NULL,
10115 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010116 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010117 } else {
10118 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010119 xmlSchemaPContentErr(ctxt,
10120 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010121 NULL, NULL, node, child, NULL,
10122 "(annotation?, ((attribute | attributeGroup)*, "
10123 "anyAttribute?))");
10124 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010125 }
10126 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010127 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010128}
10129
10130/**
10131 * xmlSchemaParseSimpleContent:
10132 * @ctxt: a schema validation context
10133 * @schema: the schema being built
10134 * @node: a subtree containing XML Schema informations
10135 *
10136 * parse a XML schema SimpleContent definition
10137 * *WARNING* this interface is highly subject to change
10138 *
10139 * Returns the type definition or NULL in case of error
10140 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010141static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010142xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10143 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010144{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010145 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010146 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010147 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010148
10149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010150 return (-1);
10151 /* Not a component, don't create it. */
10152 type = ctxt->ctxtType;
10153 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10154 /*
10155 * Check for illegal attributes.
10156 */
10157 attr = node->properties;
10158 while (attr != NULL) {
10159 if (attr->ns == NULL) {
10160 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010161 xmlSchemaPIllegalAttrErr(ctxt,
10162 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10163 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010164 }
10165 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010166 xmlSchemaPIllegalAttrErr(ctxt,
10167 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10168 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010169 }
10170 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010171 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010172
10173 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010174
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175 /*
10176 * And now for the children...
10177 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010178 child = node->children;
10179 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010180 /*
10181 * Add the annotation to the complex type ancestor.
10182 */
10183 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10184 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010185 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010186 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010187 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010188 xmlSchemaParseRestriction(ctxt, schema, child,
10189 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010191 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010192 xmlSchemaParseExtension(ctxt, schema, child,
10193 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010194 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010195 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010196 if (child != NULL) {
10197 xmlSchemaPContentErr(ctxt,
10198 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010199 NULL, NULL, node, child, NULL,
10200 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010201 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010202 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010203}
10204
10205/**
10206 * xmlSchemaParseComplexContent:
10207 * @ctxt: a schema validation context
10208 * @schema: the schema being built
10209 * @node: a subtree containing XML Schema informations
10210 *
10211 * parse a XML schema ComplexContent definition
10212 * *WARNING* this interface is highly subject to change
10213 *
10214 * Returns the type definition or NULL in case of error
10215 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010216static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010217xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10218 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010219{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010220 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010221 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010222 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010223
10224 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 return (-1);
10226 /* Not a component, don't create it. */
10227 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010228 /*
10229 * Check for illegal attributes.
10230 */
10231 attr = node->properties;
10232 while (attr != NULL) {
10233 if (attr->ns == NULL) {
10234 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010235 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010236 {
10237 xmlSchemaPIllegalAttrErr(ctxt,
10238 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10239 NULL, NULL, attr);
10240 }
10241 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10242 xmlSchemaPIllegalAttrErr(ctxt,
10243 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10244 NULL, NULL, attr);
10245 }
10246 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010247 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010248
10249 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10250
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010251 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010252 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010253 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10255 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10256 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010257 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010258 child = node->children;
10259 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010260 /*
10261 * Add the annotation to the complex type ancestor.
10262 */
10263 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10264 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010265 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010266 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010267 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010268 xmlSchemaParseRestriction(ctxt, schema, child,
10269 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010270 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010271 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010272 xmlSchemaParseExtension(ctxt, schema, child,
10273 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010274 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010275 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010276 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010277 xmlSchemaPContentErr(ctxt,
10278 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10279 NULL, NULL, node, child,
10280 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010281 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010282 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010283}
10284
10285/**
10286 * xmlSchemaParseComplexType:
10287 * @ctxt: a schema validation context
10288 * @schema: the schema being built
10289 * @node: a subtree containing XML Schema informations
10290 *
10291 * parse a XML schema Complex Type definition
10292 * *WARNING* this interface is highly subject to change
10293 *
10294 * Returns the type definition or NULL in case of error
10295 */
10296static xmlSchemaTypePtr
10297xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010298 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010299{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010300 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010301 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010302 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010303 xmlAttrPtr attr;
10304 const xmlChar *attrValue;
10305 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010306 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010307 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010308
Daniel Veillard4255d502002-04-16 15:50:10 +000010309
10310 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10311 return (NULL);
10312
Daniel Veillard01fa6152004-06-29 17:04:39 +000010313 ctxtType = ctxt->ctxtType;
10314
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010315 if (topLevel) {
10316 attr = xmlSchemaGetPropNode(node, "name");
10317 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010318 xmlSchemaPMissingAttrErr(ctxt,
10319 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010320 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010321 } else if (xmlSchemaPValAttrNode(ctxt,
10322 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010323 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10324 return (NULL);
10325 }
10326 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010327
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010328 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010329 /*
10330 * Parse as local complex type definition.
10331 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010332 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010333 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10334 if (type == NULL)
10335 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010336 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010337 type->node = node;
10338 type->type = XML_SCHEMA_TYPE_COMPLEX;
10339 /*
10340 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 */
10342 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010343 /*
10344 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010345 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010346 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010347 if (type == NULL)
10348 return (NULL);
10349 type->node = node;
10350 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010351 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010352 }
10353 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 /*
10355 * Handle attributes.
10356 */
10357 attr = node->properties;
10358 while (attr != NULL) {
10359 if (attr->ns == NULL) {
10360 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10361 /*
10362 * Attribute "id".
10363 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010364 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10365 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010366 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10367 /*
10368 * Attribute "mixed".
10369 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010370 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010372 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10373 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010374 /*
10375 * Attributes of global complex type definitions.
10376 */
10377 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10378 /* Pass. */
10379 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10380 /*
10381 * Attribute "abstract".
10382 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010383 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10384 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010385 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10386 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10387 /*
10388 * Attribute "final".
10389 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010390 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010391 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010392 if (xmlSchemaPValAttrBlockFinal(attrValue,
10393 &(type->flags),
10394 -1,
10395 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10396 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10397 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010398 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010399 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010401 type, (xmlNodePtr) attr, NULL,
10402 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010403 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010404 } else
10405 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010406 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10407 /*
10408 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010409 */
10410 attrValue = xmlSchemaGetNodeContent(ctxt,
10411 (xmlNodePtr) attr);
10412 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010413 -1,
10414 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010415 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010416 -1, -1, -1) != 0) {
10417 xmlSchemaPSimpleTypeErr(ctxt,
10418 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010419 type, (xmlNodePtr) attr, NULL,
10420 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010421 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010422 } else
10423 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010424 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010425 xmlSchemaPIllegalAttrErr(ctxt,
10426 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010427 &des, type, attr);
10428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010429 } else {
10430 xmlSchemaPIllegalAttrErr(ctxt,
10431 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010432 &des, type, attr);
10433 }
10434 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 xmlSchemaPIllegalAttrErr(ctxt,
10436 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10437 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010438 }
10439 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010441 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010442 /*
10443 * Apply default "block" values.
10444 */
10445 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10446 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10447 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10448 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10449 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010450 if (! final) {
10451 /*
10452 * Apply default "block" values.
10453 */
10454 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10455 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10456 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10457 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10458 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010459 /*
10460 * And now for the children...
10461 */
10462 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010463 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010464 child = node->children;
10465 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010466 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10467 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010468 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010469 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010470 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010471 /*
10472 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010473 * Specifying mixed='true' when the <simpleContent>
10474 * alternative is chosen has no effect
10475 */
William M. Bracke7091952004-05-11 15:09:58 +000010476 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10477 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010478 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010479 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010480 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010481 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10482 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010483 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010484 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010485 /*
10486 * SPEC
10487 * "...the third alternative (neither <simpleContent> nor
10488 * <complexContent>) is chosen. This case is understood as shorthand
10489 * for complex content restricting the ·ur-type definition·, and the
10490 * details of the mappings should be modified as necessary.
10491 */
10492 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10493 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010494 /*
10495 * Parse model groups.
10496 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010497 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010498 type->subtypes = (xmlSchemaTypePtr)
10499 xmlSchemaParseModelGroup(ctxt, schema, child,
10500 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010501 child = child->next;
10502 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010503 type->subtypes = (xmlSchemaTypePtr)
10504 xmlSchemaParseModelGroup(ctxt, schema, child,
10505 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010506 child = child->next;
10507 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010508 type->subtypes = (xmlSchemaTypePtr)
10509 xmlSchemaParseModelGroup(ctxt, schema, child,
10510 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010511 child = child->next;
10512 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010513 type->subtypes = (xmlSchemaTypePtr)
10514 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010515 child = child->next;
10516 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010517 /*
10518 * Parse attribute decls/refs.
10519 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010520 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010521 /*
10522 * Parse attribute wildcard.
10523 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010524 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010525 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10526 child = child->next;
10527 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010528 }
10529 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010530 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010531 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010532 &des, type, node, child,
10533 NULL, "(annotation?, (simpleContent | complexContent | "
10534 "((group | all | choice | sequence)?, ((attribute | "
10535 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010536 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010537 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010538 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010539 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010540 return (type);
10541}
10542
Daniel Veillard4255d502002-04-16 15:50:10 +000010543/**
10544 * xmlSchemaParseSchema:
10545 * @ctxt: a schema validation context
10546 * @node: a subtree containing XML Schema informations
10547 *
10548 * parse a XML schema definition from a node set
10549 * *WARNING* this interface is highly subject to change
10550 *
10551 * Returns the internal XML Schema structure built from the resource or
10552 * NULL in case of error
10553 */
10554static xmlSchemaPtr
10555xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10556{
10557 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010558 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010559 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010560 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010561
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010562 /*
10563 * This one is called by xmlSchemaParse only and is used if
10564 * the schema to be parsed was specified via the API; i.e. not
10565 * automatically by the validated instance document.
10566 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010567 if ((ctxt == NULL) || (node == NULL))
10568 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010569 nberrors = ctxt->nberrors;
10570 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010571 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010572 xmlSchemaImportPtr import;
10573
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010575 if (schema == NULL)
10576 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010577 /*
10578 * Disable build of list of items.
10579 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010580 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010581 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010582 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010583 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10584 /*
10585 * TODO: Should we proceed with an invalid target namespace?
10586 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010587 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
10588 } else {
10589 schema->targetNamespace = NULL;
10590 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010591 /*
10592 * Add the current ns name and location to the import table;
10593 * this is needed to have a consistent mechanism, regardless
10594 * if all schemata are constructed dynamically fired by the
10595 * instance or if the schema to be used was specified via
10596 * the API.
10597 */
10598 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10599 schema->targetNamespace);
10600 if (import == NULL) {
10601 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10602 NULL, NULL, (xmlNodePtr) ctxt->doc,
10603 "Internal error: xmlSchemaParseSchema, "
10604 "failed to add an import entry", NULL);
10605 xmlSchemaFree(schema);
10606 schema = NULL;
10607 return (NULL);
10608 }
10609 import->schemaLocation = ctxt->URL;
10610 /*
10611 * NOTE: We won't set the doc here, otherwise it will be freed
10612 * if the import struct is freed.
10613 * import->doc = ctxt->doc;
10614 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010615 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010616 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10617 } else {
10618 xmlDocPtr doc;
10619
10620 doc = node->doc;
10621
10622 if ((doc != NULL) && (doc->URL != NULL)) {
10623 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10624 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010625 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010626 } else {
10627 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10628 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010629 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010630 }
10631 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010632 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010633 if (ctxt->nberrors != 0) {
10634 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010635 xmlSchemaFree(schema);
10636 schema = NULL;
10637 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010638 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010639 if (schema != NULL)
10640 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010641 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010642#ifdef DEBUG
10643 if (schema == NULL)
10644 xmlGenericError(xmlGenericErrorContext,
10645 "xmlSchemaParse() failed\n");
10646#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010647 return (schema);
10648}
10649
10650/************************************************************************
10651 * *
10652 * Validating using Schemas *
10653 * *
10654 ************************************************************************/
10655
10656/************************************************************************
10657 * *
10658 * Reading/Writing Schemas *
10659 * *
10660 ************************************************************************/
10661
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010662#if 0 /* Will be enabled if it is clear what options are needed. */
10663/**
10664 * xmlSchemaParserCtxtSetOptions:
10665 * @ctxt: a schema parser context
10666 * @options: a combination of xmlSchemaParserOption
10667 *
10668 * Sets the options to be used during the parse.
10669 *
10670 * Returns 0 in case of success, -1 in case of an
10671 * API error.
10672 */
10673static int
10674xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10675 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010676
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010677{
10678 int i;
10679
10680 if (ctxt == NULL)
10681 return (-1);
10682 /*
10683 * WARNING: Change the start value if adding to the
10684 * xmlSchemaParseOption.
10685 */
10686 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10687 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010688 return (-1);
10689 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010690 }
10691 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010692 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010693}
10694
10695/**
10696 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010697 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010698 *
10699 * Returns the option combination of the parser context.
10700 */
10701static int
10702xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010703
10704{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010705 if (ctxt == NULL)
10706 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010707 else
10708 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010709}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010710#endif
10711
Daniel Veillard4255d502002-04-16 15:50:10 +000010712/**
10713 * xmlSchemaNewParserCtxt:
10714 * @URL: the location of the schema
10715 *
10716 * Create an XML Schemas parse context for that file/resource expected
10717 * to contain an XML Schemas file.
10718 *
10719 * Returns the parser context or NULL in case of error
10720 */
10721xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010722xmlSchemaNewParserCtxt(const char *URL)
10723{
Daniel Veillard4255d502002-04-16 15:50:10 +000010724 xmlSchemaParserCtxtPtr ret;
10725
10726 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010727 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010728
10729 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10730 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010731 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010732 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010733 return (NULL);
10734 }
10735 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010736 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010737 ret->dict = xmlDictCreate();
10738 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010739 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010740 return (ret);
10741}
10742
10743/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010744 * xmlSchemaNewMemParserCtxt:
10745 * @buffer: a pointer to a char array containing the schemas
10746 * @size: the size of the array
10747 *
10748 * Create an XML Schemas parse context for that memory buffer expected
10749 * to contain an XML Schemas file.
10750 *
10751 * Returns the parser context or NULL in case of error
10752 */
10753xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010754xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10755{
Daniel Veillard6045c902002-10-09 21:13:59 +000010756 xmlSchemaParserCtxtPtr ret;
10757
10758 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010759 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010760
10761 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10762 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010763 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010764 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010765 return (NULL);
10766 }
10767 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10768 ret->buffer = buffer;
10769 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010770 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010771 return (ret);
10772}
10773
10774/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010775 * xmlSchemaNewDocParserCtxt:
10776 * @doc: a preparsed document tree
10777 *
10778 * Create an XML Schemas parse context for that document.
10779 * NB. The document may be modified during the parsing process.
10780 *
10781 * Returns the parser context or NULL in case of error
10782 */
10783xmlSchemaParserCtxtPtr
10784xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10785{
10786 xmlSchemaParserCtxtPtr ret;
10787
10788 if (doc == NULL)
10789 return (NULL);
10790
10791 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10792 if (ret == NULL) {
10793 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10794 NULL);
10795 return (NULL);
10796 }
10797 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10798 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010799 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010800 /* The application has responsibility for the document */
10801 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010802
10803 return (ret);
10804}
10805
10806/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010807 * xmlSchemaFreeParserCtxt:
10808 * @ctxt: the schema parser context
10809 *
10810 * Free the resources associated to the schema parser context
10811 */
10812void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010813xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10814{
Daniel Veillard4255d502002-04-16 15:50:10 +000010815 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010816 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010817 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010818 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010819 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010820 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010821 xmlFree(ctxt->assemble);
10822 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010823 if (ctxt->vctxt != NULL) {
10824 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10825 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010826 if (ctxt->localImports != NULL)
10827 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010828 if (ctxt->substGroups != NULL)
10829 xmlHashFree(ctxt->substGroups,
10830 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010831 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010832 xmlFree(ctxt);
10833}
10834
10835/************************************************************************
10836 * *
10837 * Building the content models *
10838 * *
10839 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010840
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010841static void
10842xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010843 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010844{
10845 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010846 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010847 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010848 xmlSchemaSubstGroupPtr substGroup;
10849 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010850
10851 elemDecl = (xmlSchemaElementPtr) particle->children;
10852 /*
10853 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010854 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010855 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010856 end = xmlAutomataNewState(pctxt->am);
10857 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10858 if (substGroup == NULL) {
10859 xmlSchemaPErr(pctxt, GET_NODE(particle),
10860 XML_SCHEMAP_INTERNAL,
10861 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10862 "declaration is marked having a subst. group but none "
10863 "available.\n", elemDecl->name, NULL);
10864 return;
10865 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010866 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010867 /*
10868 * NOTE that we put the declaration in, even if it's abstract,
10869 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010870 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010871 xmlAutomataNewTransition2(pctxt->am,
10872 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010873 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10874 /*
10875 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010876 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010877 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010878 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10879 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010880 xmlAutomataNewTransition2(pctxt->am,
10881 start, NULL,
10882 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010883 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010884 }
10885 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010886 int counter;
10887 xmlAutomataStatePtr hop;
10888 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10889 UNBOUNDED : particle->maxOccurs - 1;
10890 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10891
10892 counter =
10893 xmlAutomataNewCounter(pctxt->am, minOccurs,
10894 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010895 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010896
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010897 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010898 xmlAutomataNewTransition2(pctxt->am,
10899 start, NULL,
10900 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010901 hop);
10902 /*
10903 * Add subst. group members.
10904 */
10905 for (i = 0; i < substGroup->members->nbItems; i++) {
10906 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10907 xmlAutomataNewEpsilon(pctxt->am,
10908 xmlAutomataNewTransition2(pctxt->am,
10909 start, NULL,
10910 member->name, member->targetNamespace, member),
10911 hop);
10912 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010913 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10914 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10915 }
10916 if (particle->minOccurs == 0)
10917 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010918 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010919}
10920
10921static void
10922xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10923 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010924{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010925 if (((xmlSchemaElementPtr) particle->children)->flags &
10926 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010927 /*
10928 * Substitution groups.
10929 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010930 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010931 } else {
10932 xmlSchemaElementPtr elemDecl;
10933 xmlAutomataStatePtr start;
10934
10935 elemDecl = (xmlSchemaElementPtr) particle->children;
10936
10937 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010938 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010939 if (particle->maxOccurs == 1) {
10940 start = ctxt->state;
10941 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10942 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10943 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10944 /* Special case. */
10945 start = ctxt->state;
10946 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10947 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010948 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010949 } else {
10950 int counter;
10951 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10952 UNBOUNDED : particle->maxOccurs - 1;
10953 int minOccurs = particle->minOccurs < 1 ?
10954 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010955
10956 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010957 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10958 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10959 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10960 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10961 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
10962 NULL, counter);
10963 }
10964 if (particle->minOccurs == 0)
10965 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
10966 }
10967}
10968
Daniel Veillard4255d502002-04-16 15:50:10 +000010969/**
10970 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000010971 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010972 * @particle: the particle component
10973 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000010974 *
10975 * Generate the automata sequence needed for that type
10976 */
10977static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010978xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010979 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010980 const xmlChar * name)
10981{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010982 if (particle == NULL) {
10983 xmlSchemaPErr(ctxt, NULL,
10984 XML_SCHEMAP_INTERNAL,
10985 "Internal error: xmlSchemaBuildAContentModel, "
10986 "particle is NULL.\n", NULL, NULL);
10987 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010988 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010989 if (particle->children == NULL) {
10990 xmlSchemaPErr(ctxt, GET_NODE(particle),
10991 XML_SCHEMAP_INTERNAL,
10992 "Internal error: xmlSchemaBuildAContentModel, "
10993 "no term on particle.\n", NULL, NULL);
10994 return;
10995 }
10996
10997 switch (particle->children->type) {
10998 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010999 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011000 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011001 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011002
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011003 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011004
Daniel Veillardc0826a72004-08-10 14:17:33 +000011005 start = ctxt->state;
11006 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011007
11008 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011009 if (wild->any == 1) {
11010 /*
11011 * We need to add both transitions:
11012 *
11013 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011014 */
11015 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011016 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011017 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011018 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11019 /*
11020 * 2. the {"*"} for elements in no namespace.
11021 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011022 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011023 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011024 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011025 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11026
11027 } else if (wild->nsSet != NULL) {
11028 ns = wild->nsSet;
11029 do {
11030 ctxt->state = start;
11031 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011032 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011033 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11034 ns = ns->next;
11035 } while (ns != NULL);
11036
11037 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011038
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011039 /*
11040 * Lead nodes with the negated namespace to the sink-state
11041 * {"*", "##other"}.
11042 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011043 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011044 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011045 /*
11046 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011047 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011048 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011049 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011050 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011051 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011052 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011053 } else {
11054 int counter;
11055 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011056 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011057 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011058 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011059 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011060
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011062 hop = xmlAutomataNewState(ctxt->am);
11063 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011064 ctxt->state =
11065 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011066 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011067 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011068 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011069 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011070 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011071 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011072 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011073 ns = wild->nsSet;
11074 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011075 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011076 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011077 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011078 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11079 ns = ns->next;
11080 } while (ns != NULL);
11081
11082 } else if (wild->negNsSet != NULL) {
11083 xmlAutomataStatePtr deadEnd;
11084
11085 deadEnd = xmlAutomataNewState(ctxt->am);
11086 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011087 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011088 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011089 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011090 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011091 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011092 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11093 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11094 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011095 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011097 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 ctxt->state = end;
11099 break;
11100 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011101 case XML_SCHEMA_TYPE_ELEMENT:
11102 xmlSchemaBuildContentModelForElement(ctxt, particle);
11103 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011104 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011105 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011106
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011107 /*
11108 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011109 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011110 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011111 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11112 sub = particle->children->children;
11113 while (sub != NULL) {
11114 xmlSchemaBuildAContentModel(ctxt,
11115 (xmlSchemaParticlePtr) sub, name);
11116 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011117 }
11118 } else {
11119 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011120
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011121 if (particle->maxOccurs >= UNBOUNDED) {
11122 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011123 xmlAutomataStatePtr tmp;
11124 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011125
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011126 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011127 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011128 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011129
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011130 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011131 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011132
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011133 sub = particle->children->children;
11134 while (sub != NULL) {
11135 xmlSchemaBuildAContentModel(ctxt,
11136 (xmlSchemaParticlePtr) sub, name);
11137 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011138 }
11139 tmp = ctxt->state;
11140 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11141 oldstate, counter);
11142 ctxt->state =
11143 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11144 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011145
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011146 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011147 sub = particle->children->children;
11148 while (sub != NULL) {
11149 xmlSchemaBuildAContentModel(ctxt,
11150 (xmlSchemaParticlePtr) sub, name);
11151 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011152 }
11153 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11154 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011155 if (particle->minOccurs == 0) {
11156 xmlAutomataNewEpsilon(ctxt->am,
11157 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011158 }
11159 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011160 } else if ((particle->maxOccurs > 1)
11161 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011162 xmlAutomataStatePtr tmp;
11163 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011164
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011165 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011166 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011167 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011168
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011169 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011170 particle->minOccurs - 1,
11171 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011172
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011173 sub = particle->children->children;
11174 while (sub != NULL) {
11175 xmlSchemaBuildAContentModel(ctxt,
11176 (xmlSchemaParticlePtr) sub, name);
11177 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011178 }
11179 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011180 xmlAutomataNewCountedTrans(ctxt->am,
11181 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011182 ctxt->state =
11183 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11184 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 if (particle->minOccurs == 0) {
11186 xmlAutomataNewEpsilon(ctxt->am,
11187 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011188 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011189 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011190 sub = particle->children->children;
11191 while (sub != NULL) {
11192 xmlSchemaBuildAContentModel(ctxt,
11193 (xmlSchemaParticlePtr) sub, name);
11194 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011195 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011197 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11198 ctxt->state);
11199 }
11200 }
11201 }
11202 break;
11203 }
11204 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011205 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011206 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011207
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011208 start = ctxt->state;
11209 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011210
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011211 /*
11212 * iterate over the subtypes and remerge the end with an
11213 * epsilon transition
11214 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 if (particle->maxOccurs == 1) {
11216 sub = particle->children->children;
11217 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011218 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011219 xmlSchemaBuildAContentModel(ctxt,
11220 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011221 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011222 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011223 }
11224 } else {
11225 int counter;
11226 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011227 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11228 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011229 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011230 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011231
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011232 /*
11233 * use a counter to keep track of the number of transtions
11234 * which went through the choice.
11235 */
11236 counter =
11237 xmlAutomataNewCounter(ctxt->am, minOccurs,
11238 maxOccurs);
11239 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011240
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011241 sub = particle->children->children;
11242 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011243 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011244 xmlSchemaBuildAContentModel(ctxt,
11245 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011247 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011248 }
11249 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11250 counter);
11251 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11252 counter);
11253 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011255 xmlAutomataNewEpsilon(ctxt->am, start, end);
11256 }
11257 ctxt->state = end;
11258 break;
11259 }
11260 case XML_SCHEMA_TYPE_ALL:{
11261 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011262 xmlSchemaParticlePtr sub;
11263 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011264 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011265
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 sub = (xmlSchemaParticlePtr) particle->children->children;
11267 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011268 break;
11269 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011270 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011272
11273 elemDecl = (xmlSchemaElementPtr) sub->children;
11274 if (elemDecl == NULL) {
11275 xmlSchemaPErr(ctxt, NULL,
11276 XML_SCHEMAP_INTERNAL,
11277 "Internal error: xmlSchemaBuildAContentModel, "
11278 "<element> particle a NULL term.\n", NULL, NULL);
11279 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011280 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011281 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011282 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011283 * {particles} of the group must be 0 or 1; this is
11284 * already ensured during the parse of the content of
11285 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011286 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011287 if ((sub->minOccurs == 1) &&
11288 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011289 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011290 ctxt->state,
11291 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011292 elemDecl->targetNamespace,
11293 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011294 } else if ((sub->minOccurs == 0) &&
11295 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011296
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011297 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011298 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011299 elemDecl->name,
11300 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011301 0,
11302 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011303 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011304 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011305 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011307 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011308 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011309 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011310 break;
11311 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011312 default:
11313 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011314 "Internal error: xmlSchemaBuildAContentModel, found "
11315 "unexpected term of type %d in content model of complex "
11316 "type '%s'.\n",
11317 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011318 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011319 }
11320}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011321
Daniel Veillard4255d502002-04-16 15:50:10 +000011322/**
11323 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011324 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011325 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011326 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011327 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011328 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011329 */
11330static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011331xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 const xmlChar * name)
11334{
Daniel Veillard4255d502002-04-16 15:50:10 +000011335 xmlAutomataStatePtr start;
11336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011337 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11338 (type->contModel != NULL) ||
11339 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11340 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011341 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011342
11343#ifdef DEBUG_CONTENT
11344 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011345 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011346#endif
11347
Daniel Veillard4255d502002-04-16 15:50:10 +000011348 ctxt->am = xmlNewAutomata();
11349 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011350 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011351 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011352 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011353 }
11354 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011355 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011356 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011357 type->contModel = xmlAutomataCompile(ctxt->am);
11358 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011359 xmlSchemaPCustomErr(ctxt,
11360 XML_SCHEMAP_INTERNAL,
11361 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011362 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011363 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011364 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011365 XML_SCHEMAP_NOT_DETERMINISTIC,
11366 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011367 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011368 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011369 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011370#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011371 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011372 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011373 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011374#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011375 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011376 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011377 xmlFreeAutomata(ctxt->am);
11378 ctxt->am = NULL;
11379}
11380
11381/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011382 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011383 * @elem: the schema element context
11384 * @ctxt: the schema parser context
11385 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011386 * Resolves the references of an element declaration
11387 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011388 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011389 */
11390static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011391xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011392 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011393 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011394 const xmlChar * context ATTRIBUTE_UNUSED,
11395 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011396{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011397 if ((ctxt == NULL) || (elemDecl == NULL) ||
11398 ((elemDecl != NULL) &&
11399 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011400 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011401 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011402
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011403 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011404 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011405
11406 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011407 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011408 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011409 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011410 elemDecl->namedTypeNs);
11411 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011412 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011413 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011414 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011415 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011416 XML_SCHEMA_TYPE_BASIC, "type definition");
11417 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011418 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011419 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011420 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011421 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011422
Daniel Veillardc0826a72004-08-10 14:17:33 +000011423 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011424 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011425 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011426 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011427 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11428 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011429 if (substHead == NULL) {
11430 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011431 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011432 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011433 "substitutionGroup", elemDecl->substGroup,
11434 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011435 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011437 /*
11438 * Set the "substitution group affiliation".
11439 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011440 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011441 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011442 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011443 * (type definition)...otherwise the {type definition} of the
11444 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011445 * the substitutionGroup [attribute], if present
11446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011447 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011448 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011449 }
11450 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011451 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11452 (elemDecl->substGroup == NULL))
11453 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011454}
11455
11456/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011457 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011458 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011459 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011460 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011461 * Checks and builds the "member type definitions" property of the union
11462 * simple type. This handles part (1), part (2) is done in
11463 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11464 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011465 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011466 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011467static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011468xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11469 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011470{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011471
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011472 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011473 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011474
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011475 /*
11476 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11477 * define the explicit members as the type definitions ·resolved·
11478 * to by the items in the ·actual value· of the memberTypes [attribute],
11479 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011480 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011481 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011482 /*
11483 * Resolve references.
11484 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011485 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011486 lastLink = NULL;
11487 while (link != NULL) {
11488 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011489
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011490 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11491 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11492
11493 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11494 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11495 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011496 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011497 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11498 /*
11499 * Remove the member type link.
11500 */
11501 if (lastLink == NULL)
11502 type->memberTypes = link->next;
11503 else
11504 lastLink->next = link->next;
11505 newLink = link;
11506 link = link->next;
11507 xmlFree(newLink);
11508 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011509 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011510 lastLink = link;
11511 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011512 }
11513 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011514 /*
11515 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011516 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011517 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011519 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11520 if (link == NULL) {
11521 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11522 return (-1);
11523 }
11524 link->type = memberType;
11525 link->next = NULL;
11526 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011527 type->memberTypes = link;
11528 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011529 lastLink->next = link;
11530 lastLink = link;
11531 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011532 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011533 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011534}
11535
Daniel Veillard4255d502002-04-16 15:50:10 +000011536/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011537 * xmlSchemaIsDerivedFromBuiltInType:
11538 * @ctxt: the schema parser context
11539 * @type: the type definition
11540 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011541 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011542 *
11543 * Returns 1 if the type has the given value type, or
11544 * is derived from such a type.
11545 */
William M. Brack803812b2004-06-03 02:11:24 +000011546static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011547xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011548{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011549 if (type == NULL)
11550 return (0);
11551 if (IS_COMPLEX_TYPE(type))
11552 return (0);
11553 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11554 if (type->builtInType == valType)
11555 return(1);
11556 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11557 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11558 return (0);
11559 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11560 } else
11561 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011562
11563 return (0);
11564}
11565
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011566#if 0
11567/**
11568 * xmlSchemaIsDerivedFromBuiltInType:
11569 * @ctxt: the schema parser context
11570 * @type: the type definition
11571 * @valType: the value type
11572 *
11573 *
11574 * Returns 1 if the type has the given value type, or
11575 * is derived from such a type.
11576 */
11577static int
11578xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11579{
11580 if (type == NULL)
11581 return (0);
11582 if (IS_COMPLEX_TYPE(type))
11583 return (0);
11584 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11585 if (type->builtInType == valType)
11586 return(1);
11587 return (0);
11588 } else
11589 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11590
11591 return (0);
11592}
11593#endif
11594
11595static xmlSchemaTypePtr
11596xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11597{
11598 if (type == NULL)
11599 return (NULL);
11600 if (IS_COMPLEX_TYPE(type))
11601 return (NULL);
11602 if (type->type == XML_SCHEMA_TYPE_BASIC)
11603 return(type);
11604 else
11605 return(xmlSchemaQueryBuiltInType(type->subtypes));
11606
11607 return (NULL);
11608}
11609
Daniel Veillard3646d642004-06-02 19:19:14 +000011610/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011611 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011612 * @type: the simpleType definition
11613 *
11614 * Returns the primitive type of the given type or
11615 * NULL in case of error.
11616 */
11617static xmlSchemaTypePtr
11618xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11619{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011620
Daniel Veillard01fa6152004-06-29 17:04:39 +000011621 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011622 /*
11623 * Note that anySimpleType is actually not a primitive type
11624 * but we need that here.
11625 */
11626 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11627 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011628 return (type);
11629 type = type->baseType;
11630 }
11631
11632 return (NULL);
11633}
11634
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011635#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011636/**
11637 * xmlSchemaGetBuiltInTypeAncestor:
11638 * @type: the simpleType definition
11639 *
11640 * Returns the primitive type of the given type or
11641 * NULL in case of error.
11642 */
11643static xmlSchemaTypePtr
11644xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11645{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011646 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011647 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011648 while (type != NULL) {
11649 if (type->type == XML_SCHEMA_TYPE_BASIC)
11650 return (type);
11651 type = type->baseType;
11652 }
11653
11654 return (NULL);
11655}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011656#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011657
Daniel Veillard01fa6152004-06-29 17:04:39 +000011658/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011659 * xmlSchemaBuildAttributeUsesOwned:
11660 * @ctxt: the schema parser context
11661 * @type: the complex type definition
11662 * @cur: the attribute declaration list
11663 * @lastUse: the top of the attribute use list
11664 *
11665 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011666 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011667 * xmlSchemaBuildAttributeValidation only.
11668 */
11669static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011670xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011671 xmlSchemaAttributePtr cur,
11672 xmlSchemaAttributeLinkPtr *uses,
11673 xmlSchemaAttributeLinkPtr *lastUse)
11674{
11675 xmlSchemaAttributeLinkPtr tmp;
11676 while (cur != NULL) {
11677 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011678 /*
11679 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11680 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011681 * <attributeGroup> [children], if any."
11682 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011683 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11684 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011685 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011686 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011687 }
11688 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011689 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011690 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011691 */
11692 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011693 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11694 if (tmp == NULL) {
11695 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11696 return (-1);
11697 }
11698 tmp->attr = cur;
11699 tmp->next = NULL;
11700 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011701 *uses = tmp;
11702 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011703 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011704 *lastUse = tmp;
11705 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011706 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011707 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011708 return (0);
11709}
11710
Daniel Veillard50355f02004-06-08 17:52:16 +000011711/**
11712 * xmlSchemaCloneWildcardNsConstraints:
11713 * @ctxt: the schema parser context
11714 * @dest: the destination wildcard
11715 * @source: the source wildcard
11716 *
11717 * Clones the namespace constraints of source
11718 * and assignes them to dest.
11719 * Returns -1 on internal error, 0 otherwise.
11720 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011721static int
11722xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11723 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011724 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011725{
11726 xmlSchemaWildcardNsPtr cur, tmp, last;
11727
11728 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011729 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011730 (*dest)->any = source->any;
11731 cur = source->nsSet;
11732 last = NULL;
11733 while (cur != NULL) {
11734 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11735 if (tmp == NULL)
11736 return(-1);
11737 tmp->value = cur->value;
11738 if (last == NULL)
11739 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011740 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011741 last->next = tmp;
11742 last = tmp;
11743 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011744 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011745 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011746 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011747 if (source->negNsSet != NULL) {
11748 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11749 if ((*dest)->negNsSet == NULL)
11750 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011751 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011752 } else
11753 (*dest)->negNsSet = NULL;
11754 return(0);
11755}
11756
Daniel Veillard50355f02004-06-08 17:52:16 +000011757/**
11758 * xmlSchemaUnionWildcards:
11759 * @ctxt: the schema parser context
11760 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011761 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011762 *
11763 * Unions the namespace constraints of the given wildcards.
11764 * @completeWild will hold the resulting union.
11765 * Returns a positive error code on failure, -1 in case of an
11766 * internal error, 0 otherwise.
11767 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011768static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011769xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011770 xmlSchemaWildcardPtr completeWild,
11771 xmlSchemaWildcardPtr curWild)
11772{
11773 xmlSchemaWildcardNsPtr cur, curB, tmp;
11774
11775 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011776 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011777 * value.
11778 */
11779 if ((completeWild->any == curWild->any) &&
11780 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11781 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011782
Daniel Veillard3646d642004-06-02 19:19:14 +000011783 if ((completeWild->negNsSet == NULL) ||
11784 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011785
Daniel Veillard3646d642004-06-02 19:19:14 +000011786 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011787 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011788
11789 /*
11790 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011791 */
11792 cur = completeWild->nsSet;
11793 while (cur != NULL) {
11794 found = 0;
11795 curB = curWild->nsSet;
11796 while (curB != NULL) {
11797 if (cur->value == curB->value) {
11798 found = 1;
11799 break;
11800 }
11801 curB = curB->next;
11802 }
11803 if (!found)
11804 break;
11805 cur = cur->next;
11806 }
11807 if (found)
11808 return(0);
11809 } else
11810 return(0);
11811 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011812 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011813 /*
11814 * 2 If either O1 or O2 is any, then any must be the value
11815 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011816 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011817 if (completeWild->any == 0) {
11818 completeWild->any = 1;
11819 if (completeWild->nsSet != NULL) {
11820 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11821 completeWild->nsSet = NULL;
11822 }
11823 if (completeWild->negNsSet != NULL) {
11824 xmlFree(completeWild->negNsSet);
11825 completeWild->negNsSet = NULL;
11826 }
11827 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011828 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011829 }
11830 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011831 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011832 * then the union of those sets must be the value.
11833 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011834 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011835 int found;
11836 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011837
Daniel Veillard3646d642004-06-02 19:19:14 +000011838 cur = curWild->nsSet;
11839 start = completeWild->nsSet;
11840 while (cur != NULL) {
11841 found = 0;
11842 curB = start;
11843 while (curB != NULL) {
11844 if (cur->value == curB->value) {
11845 found = 1;
11846 break;
11847 }
11848 curB = curB->next;
11849 }
11850 if (!found) {
11851 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011852 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011853 return (-1);
11854 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011855 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011856 completeWild->nsSet = tmp;
11857 }
11858 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859 }
11860
Daniel Veillard3646d642004-06-02 19:19:14 +000011861 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011862 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011863 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011864 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011865 * or ·absent·), then a pair of not and ·absent· must be the value.
11866 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011867 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011868 (curWild->negNsSet != NULL) &&
11869 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11870 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011871
11872 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011873 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011874 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011875 * 5.
11876 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011877 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011878 (completeWild->negNsSet->value != NULL) &&
11879 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011880 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011881 (curWild->negNsSet->value != NULL) &&
11882 (completeWild->nsSet != NULL))) {
11883
11884 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011885
Daniel Veillard3646d642004-06-02 19:19:14 +000011886 if (completeWild->nsSet != NULL) {
11887 cur = completeWild->nsSet;
11888 curB = curWild->negNsSet;
11889 } else {
11890 cur = curWild->nsSet;
11891 curB = completeWild->negNsSet;
11892 }
11893 nsFound = 0;
11894 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011895 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011896 absentFound = 1;
11897 else if (cur->value == curB->value)
11898 nsFound = 1;
11899 if (nsFound && absentFound)
11900 break;
11901 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011903
11904 if (nsFound && absentFound) {
11905 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011906 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011907 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011908 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011909 completeWild->any = 1;
11910 if (completeWild->nsSet != NULL) {
11911 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11912 completeWild->nsSet = NULL;
11913 }
11914 if (completeWild->negNsSet != NULL) {
11915 xmlFree(completeWild->negNsSet);
11916 completeWild->negNsSet = NULL;
11917 }
11918 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011919 /*
11920 * 5.2 If the set S includes the negated namespace name
11921 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011922 * be the value.
11923 */
11924 if (completeWild->nsSet != NULL) {
11925 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11926 completeWild->nsSet = NULL;
11927 }
11928 if (completeWild->negNsSet == NULL) {
11929 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11930 if (completeWild->negNsSet == NULL)
11931 return (-1);
11932 }
11933 completeWild->negNsSet->value = NULL;
11934 } else if ((!nsFound) && absentFound) {
11935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011936 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011937 * namespace name, then the union is not expressible.
11938 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011939 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011940 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011941 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011942 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011943 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011944 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011945 /*
11946 * 5.4 If the set S does not include either the negated namespace
11947 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011948 * and a namespace name must be the value.
11949 */
11950 if (completeWild->negNsSet == NULL) {
11951 if (completeWild->nsSet != NULL) {
11952 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11953 completeWild->nsSet = NULL;
11954 }
11955 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11956 if (completeWild->negNsSet == NULL)
11957 return (-1);
11958 completeWild->negNsSet->value = curWild->negNsSet->value;
11959 }
11960 }
11961 return (0);
11962 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011963 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011964 * 6.
11965 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011966 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 (completeWild->negNsSet->value == NULL) &&
11968 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011970 (curWild->negNsSet->value == NULL) &&
11971 (completeWild->nsSet != NULL))) {
11972
11973 if (completeWild->nsSet != NULL) {
11974 cur = completeWild->nsSet;
11975 } else {
11976 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011978 while (cur != NULL) {
11979 if (cur->value == NULL) {
11980 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011981 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011982 * value.
11983 */
11984 completeWild->any = 1;
11985 if (completeWild->nsSet != NULL) {
11986 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11987 completeWild->nsSet = NULL;
11988 }
11989 if (completeWild->negNsSet != NULL) {
11990 xmlFree(completeWild->negNsSet);
11991 completeWild->negNsSet = NULL;
11992 }
11993 return (0);
11994 }
11995 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011996 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011997 if (completeWild->negNsSet == NULL) {
11998 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011999 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012000 * and ·absent· must be the value.
12001 */
12002 if (completeWild->nsSet != NULL) {
12003 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12004 completeWild->nsSet = NULL;
12005 }
12006 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12007 if (completeWild->negNsSet == NULL)
12008 return (-1);
12009 completeWild->negNsSet->value = NULL;
12010 }
12011 return (0);
12012 }
12013 return (0);
12014
12015}
12016
Daniel Veillard50355f02004-06-08 17:52:16 +000012017/**
12018 * xmlSchemaIntersectWildcards:
12019 * @ctxt: the schema parser context
12020 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012021 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012022 *
12023 * Intersects the namespace constraints of the given wildcards.
12024 * @completeWild will hold the resulting intersection.
12025 * Returns a positive error code on failure, -1 in case of an
12026 * internal error, 0 otherwise.
12027 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012028static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012029xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012030 xmlSchemaWildcardPtr completeWild,
12031 xmlSchemaWildcardPtr curWild)
12032{
William M. Brack803812b2004-06-03 02:11:24 +000012033 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012034
12035 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012036 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012037 * value.
12038 */
12039 if ((completeWild->any == curWild->any) &&
12040 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12041 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012042
Daniel Veillard3646d642004-06-02 19:19:14 +000012043 if ((completeWild->negNsSet == NULL) ||
12044 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012045
Daniel Veillard3646d642004-06-02 19:19:14 +000012046 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012047 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012048
12049 /*
12050 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012051 */
12052 cur = completeWild->nsSet;
12053 while (cur != NULL) {
12054 found = 0;
12055 curB = curWild->nsSet;
12056 while (curB != NULL) {
12057 if (cur->value == curB->value) {
12058 found = 1;
12059 break;
12060 }
12061 curB = curB->next;
12062 }
12063 if (!found)
12064 break;
12065 cur = cur->next;
12066 }
12067 if (found)
12068 return(0);
12069 } else
12070 return(0);
12071 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012072 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012073 /*
12074 * 2 If either O1 or O2 is any, then the other must be the value.
12075 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012076 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012077 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012078 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012079 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012080 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012081 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012082 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12083 * name or ·absent·) and the other is a set of (namespace names or
12084 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012085 * the set, minus ·absent· if it was in the set, must be the value.
12086 */
12087 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12088 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12089 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012090
Daniel Veillard3646d642004-06-02 19:19:14 +000012091 if (completeWild->nsSet == NULL) {
12092 neg = completeWild->negNsSet->value;
12093 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12094 return(-1);
12095 } else
12096 neg = curWild->negNsSet->value;
12097 /*
12098 * Remove absent and negated.
12099 */
12100 prev = NULL;
12101 cur = completeWild->nsSet;
12102 while (cur != NULL) {
12103 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012104 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012105 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012106 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012107 prev->next = cur->next;
12108 xmlFree(cur);
12109 break;
12110 }
12111 prev = cur;
12112 cur = cur->next;
12113 }
12114 if (neg != NULL) {
12115 prev = NULL;
12116 cur = completeWild->nsSet;
12117 while (cur != NULL) {
12118 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012119 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012120 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012121 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012122 prev->next = cur->next;
12123 xmlFree(cur);
12124 break;
12125 }
12126 prev = cur;
12127 cur = cur->next;
12128 }
12129 }
12130
12131 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012132 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012133 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012134 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012135 * then the intersection of those sets must be the value.
12136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012137 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012138 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012139
Daniel Veillard3646d642004-06-02 19:19:14 +000012140 cur = completeWild->nsSet;
12141 prev = NULL;
12142 while (cur != NULL) {
12143 found = 0;
12144 curB = curWild->nsSet;
12145 while (curB != NULL) {
12146 if (cur->value == curB->value) {
12147 found = 1;
12148 break;
12149 }
12150 curB = curB->next;
12151 }
12152 if (!found) {
12153 if (prev == NULL)
12154 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012155 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012156 prev->next = cur->next;
12157 tmp = cur->next;
12158 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 continue;
12161 }
12162 prev = cur;
12163 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164 }
12165
Daniel Veillard3646d642004-06-02 19:19:14 +000012166 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012167 }
12168 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012169 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012170 */
12171 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012172 (curWild->negNsSet != NULL) &&
12173 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012174 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012175 (curWild->negNsSet->value != NULL)) {
12176
12177 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012178 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012179 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012180 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012181 }
12182 /*
12183 * 6 If the one is a negation of a namespace name and the other
12184 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012185 * of a namespace name must be the value.
12186 */
12187 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12188 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012189 (completeWild->negNsSet->value == NULL)) {
12190 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012191 }
12192 return(0);
12193}
12194
Daniel Veillard50355f02004-06-08 17:52:16 +000012195/**
12196 * xmlSchemaIsWildcardNsConstraintSubset:
12197 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012198 * @sub: the first wildcard
12199 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012200 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012201 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12202 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012203 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012204 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012205 */
12206static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012207xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12208 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012209{
Daniel Veillard50355f02004-06-08 17:52:16 +000012210 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012211 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012212 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012213 if (super->any)
12214 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012215 /*
12216 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12217 * 2.2 super must be a pair of not and the same value.
12218 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012219 if ((sub->negNsSet != NULL) &&
12220 (super->negNsSet != NULL) &&
12221 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012222 return (0);
12223 /*
12224 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012225 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012226 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012227 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012228 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012229 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012230 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012231 xmlSchemaWildcardNsPtr cur, curB;
12232 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012233
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012234 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012235 while (cur != NULL) {
12236 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012237 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012238 while (curB != NULL) {
12239 if (cur->value == curB->value) {
12240 found = 1;
12241 break;
12242 }
12243 curB = curB->next;
12244 }
12245 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012246 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012247 cur = cur->next;
12248 }
12249 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012250 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012251 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012252 xmlSchemaWildcardNsPtr cur;
12253 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012254 * 3.2.2 super must be a pair of not and a namespace name or
12255 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012256 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012257 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012258 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012259 if (cur->value == super->negNsSet->value)
12260 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012261 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012262 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012263 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012264 }
12265 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012266 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012267}
12268
12269/**
12270 * xmlSchemaBuildCompleteAttributeWildcard:
12271 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012272 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012273 * @completeWild: the resulting complete wildcard
12274 *
12275 * Returns -1 in case of an internal error, 0 otherwise.
12276 */
12277static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012278xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012279 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012280 xmlSchemaWildcardPtr *completeWild)
12281{
Daniel Veillard3646d642004-06-02 19:19:14 +000012282 while (attrs != NULL) {
12283 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12284 xmlSchemaAttributeGroupPtr group;
12285
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012286 group = (xmlSchemaAttributeGroupPtr) attrs;
12287 /*
12288 * Handle attribute group references.
12289 */
12290 if (group->ref != NULL) {
12291 if (group->refItem == NULL) {
12292 /*
12293 * TODO: Should we raise a warning here?
12294 */
12295 /*
12296 * The referenced attribute group definition could not
12297 * be resolved beforehand, so skip.
12298 */
12299 attrs = attrs->next;
12300 continue;
12301 } else
12302 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012303 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012304 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305 * For every attribute group definition, an intersected wildcard
12306 * will be created (assumed that a wildcard exists on the
12307 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012308 * at all).
12309 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12310 * that the intersection will be performed only once.
12311 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012312 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12313 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012314 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012315 group->attributes, &group->attributeWildcard) == -1)
12316 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012317 }
12318 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012319 }
12320 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012321 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012322 /*
12323 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012324 *
12325 * Although the complete wildcard might not correspond to any
12326 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012327 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012328 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12329 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12330 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012331 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012332 completeWild, group->attributeWildcard) == -1)
12333 return (-1);
12334 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012335 (*completeWild)->node = group->attributeWildcard->node;
12336 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012337 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012338 }
12339 }
12340 attrs = attrs->next;
12341 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012342
12343 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012344}
12345
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012346static int
12347xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12348 int *fixed,
12349 const xmlChar **value,
12350 xmlSchemaValPtr *val)
12351{
12352 *fixed = 0;
12353 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012354 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012355 *val = NULL;
12356
12357 if (item->defValue == NULL)
12358 item = item->refDecl;
12359
12360 if (item == NULL)
12361 return (0);
12362
12363 if (item->defValue != NULL) {
12364 *value = item->defValue;
12365 if (val != 0)
12366 *val = item->defVal;
12367 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12368 *fixed = 1;
12369 return (1);
12370 }
12371 return (0);
12372}
Daniel Veillard3646d642004-06-02 19:19:14 +000012373/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012374 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012375 * @wild: the wildcard
12376 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012377 *
12378 * Validation Rule: Wildcard allows Namespace Name
12379 * (cvc-wildcard-namespace)
12380 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012381 *
12382 * Returns 1 if the given namespace matches the wildcard,
12383 * 0 otherwise.
12384 */
12385static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012386xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12387 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012388{
12389 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012390 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012391
12392 if (wild->any)
12393 return(1);
12394 else if (wild->nsSet != NULL) {
12395 xmlSchemaWildcardNsPtr cur;
12396
12397 cur = wild->nsSet;
12398 while (cur != NULL) {
12399 if (xmlStrEqual(cur->value, ns))
12400 return(1);
12401 cur = cur->next;
12402 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012403 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012404 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012405 return(1);
12406
Daniel Veillard3646d642004-06-02 19:19:14 +000012407 return(0);
12408}
12409
12410/**
12411 * xmlSchemaBuildAttributeValidation:
12412 * @ctxt: the schema parser context
12413 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012414 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012415 *
12416 * Builds the wildcard and the attribute uses on the given complex type.
12417 * Returns -1 if an internal error occurs, 0 otherwise.
12418 */
12419static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012420xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12421 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012422{
12423 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012424 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12425 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012426 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012427 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012428 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012429 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012430
Daniel Veillard01fa6152004-06-29 17:04:39 +000012431 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012432 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012433 * Complex Type Definition with complex content Schema Component.
12434 *
12435 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012436 * TODO: Add checks for absent referenced attribute declarations and
12437 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012438 */
12439 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012440 PERROR_INT("xmlSchemaBuildAttributeValidation",
12441 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012442 return (-1);
12443 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012444 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012445 PERROR_INT("xmlSchemaBuildAttributeValidation",
12446 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012447 return (-1);
12448 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012449 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012450 /*
12451 * Inherit the attribute uses of the base type.
12452 */
12453 /*
12454 * NOTE: It is allowed to "extend" the anyType complex type.
12455 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012456 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012457 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012458 for (cur = baseType->attributeUses; cur != NULL;
12459 cur = cur->next) {
12460 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012461 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12462 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012463 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012464 "building attribute uses of complexType", NULL);
12465 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012466 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012467 tmp->attr = cur->attr;
12468 tmp->next = NULL;
12469 if (type->attributeUses == NULL) {
12470 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012471 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012472 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012473 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012474 }
12475 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012476 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012477 if ((type->subtypes != NULL) &&
12478 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012479 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012480 /*
12481 * type --> (<simpleContent>|<complexContent>)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012482 * --> (<restriction>|<extension>) --> attributes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012483 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012484 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012485 } else {
12486 /* Short hand form of the complexType. */
12487 attrs = type->attributes;
12488 }
12489 /*
12490 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012491 */
12492 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12493 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012494 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012495 * NOTE: During the parse time, the wildcard is created on the complexType
12496 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012497 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012498 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012499 PERROR_INT("xmlSchemaBuildAttributeValidation",
12500 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012501 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012502 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012503
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012504 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12505 ((IS_ANYTYPE(baseType)) ||
12506 ((baseType != NULL) &&
12507 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12508 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012509 if (type->attributeWildcard != NULL) {
12510 /*
12511 * Union the complete wildcard with the base wildcard.
12512 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012514 baseType->attributeWildcard) == -1)
12515 return (-1);
12516 } else {
12517 /*
12518 * Just inherit the wildcard.
12519 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012520 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012521 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012522 * wildcard is shared.
12523 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012524 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012525 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012526 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012527
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012528 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12529 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530 /*
12531 * Derivation Valid (Restriction, Complex)
12532 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012533 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012534 if (baseType->attributeWildcard == NULL) {
12535 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012536 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012537 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012538 "The type has an attribute wildcard, "
12539 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012541 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012542 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012543 } else if (xmlSchemaCheckCOSNSSubset(
12544 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012545 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012547 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012548 NULL, type, NULL,
12549 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012550 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12552 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012553 return (1);
12554 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012555 /* 4.3 Unless the {base type definition} is the ·ur-type
12556 * definition·, the complex type definition's {attribute
12557 * wildcard}'s {process contents} must be identical to or
12558 * stronger than the {base type definition}'s {attribute
12559 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012560 * than lax is stronger than skip.
12561 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012562 if ((! IS_ANYTYPE(baseType)) &&
12563 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012564 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012565 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012566 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 NULL, type, NULL,
12568 "The 'process contents' of the attribute wildcard is "
12569 "weaker than the one in the base type %s",
12570 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012571 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012572 return (1);
12573 }
12574 }
12575 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12576 /*
12577 * Derivation Valid (Extension)
12578 * At this point the type and the base have both, either
12579 * no wildcard or a wildcard.
12580 */
12581 if ((baseType->attributeWildcard != NULL) &&
12582 (baseType->attributeWildcard != type->attributeWildcard)) {
12583 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012584 if (xmlSchemaCheckCOSNSSubset(
12585 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012586 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012587 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012588 NULL, type, NULL,
12589 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012590 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012591 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12592 FREE_AND_NULL(str)
12593 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012594 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012595 }
12596 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012597
Daniel Veillard3646d642004-06-02 19:19:14 +000012598 /*
12599 * Gather attribute uses defined by this type.
12600 */
12601 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012602 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012603 &uses, &lastUse) == -1) {
12604 return (-1);
12605 }
12606 }
12607 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012609 * not have identical {name}s and {target namespace}s."
12610 *
12611 * For "extension" this is done further down.
12612 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012613 if ((uses != NULL) && ((type->flags &
12614 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012615 cur = uses;
12616 while (cur != NULL) {
12617 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 while (tmp != NULL) {
12619 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012620 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012621 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012622 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012624 xmlSchemaPAttrUseErr(pctxt,
12625 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12626 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012627 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012628 xmlSchemaFormatQName(&str,
12629 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12630 xmlSchemaGetAttrName(tmp->attr)));
12631 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012632 break;
12633 }
12634 tmp = tmp->next;
12635 }
12636 cur = cur->next;
12637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012638 }
12639 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012640 /*
12641 * Derive by restriction.
12642 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012643 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012644 type->attributeUses = uses;
12645 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012646 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012647 const xmlChar *bEffValue;
12648 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012649
12650 cur = uses;
12651 while (cur != NULL) {
12652 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012653 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012654 base = type->attributeUses;
12655 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012657 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012659 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012660
12661 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012662
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012663 if ((cur->attr->occurs ==
12664 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12665 (base->attr->occurs ==
12666 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012667 /*
12668 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012669 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012670 xmlSchemaPAttrUseErr(pctxt,
12671 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12672 type, cur->attr,
12673 "The 'optional' use is inconsistent with a "
12674 "matching 'required' use of the base type",
12675 NULL);
12676 } else if ((cur->attr->occurs ==
12677 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12678 (base->attr->occurs ==
12679 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12680 /*
12681 * derivation-ok-restriction 3
12682 */
12683 xmlSchemaPCustomErr(pctxt,
12684 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12685 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012686 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012687 "attribute use '%s' of the base type is "
12688 "missing",
12689 xmlSchemaFormatQName(&str,
12690 xmlSchemaGetAttrTargetNsURI(base->attr),
12691 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012693 } else if (xmlSchemaCheckCOSSTDerivedOK(
12694 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12695
12696 /*
12697 * SPEC (2.1.2) "R's {attribute declaration}'s
12698 * {type definition} must be validly derived from
12699 * B's {type definition} given the empty set as
12700 * defined in Type Derivation OK (Simple) (§3.14.6)."
12701 */
12702 xmlSchemaPAttrUseErr(pctxt,
12703 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12704 type, cur->attr,
12705 "The attribute declaration's type "
12706 "definition is not validly derived from "
12707 "the corresponding definition in the "
12708 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012709 } else {
12710 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012711 * 2.1.3 [Definition:] Let the effective value
12712 * constraint of an attribute use be its {value
12713 * constraint}, if present, otherwise its {attribute
12714 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012715 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012716 xmlSchemaGetEffectiveValueConstraint(base->attr,
12717 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012718 /*
12719 * 2.1.3 ... one of the following must be true
12720 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012721 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012722 * ·absent· or default.
12723 */
12724 if ((bEffValue != NULL) &&
12725 (effFixed == 1)) {
12726 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727
12728 xmlSchemaGetEffectiveValueConstraint(base->attr,
12729 &effFixed, &rEffValue, 0);
12730 /*
12731 * 2.1.3.2 R's ·effective value constraint· is
12732 * fixed with the same string as B's.
12733 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012734 */
12735 if ((effFixed == 0) ||
12736 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 xmlSchemaPAttrUseErr(pctxt,
12738 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12739 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012740 "The effective value constraint of the "
12741 "attribute use is inconsistent with "
12742 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012743 NULL);
12744 } else {
12745 /*
12746 * Override the attribute use.
12747 */
12748 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012749 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012750 } else
12751 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012752 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012753
Daniel Veillard3646d642004-06-02 19:19:14 +000012754 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012755 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012756 base = base->next;
12757 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012759 if ((!found) && (cur->attr->occurs !=
12760 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12761 /*
12762 * derivation-ok-restriction 2.2
12763 */
12764 if ((baseType->attributeWildcard == NULL) ||
12765 (xmlSchemaCheckCVCWildcardNamespace(
12766 baseType->attributeWildcard,
12767 cur->attr->targetNamespace) != 1)) {
12768 xmlSchemaPAttrUseErr(pctxt,
12769 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12770 type, cur->attr,
12771 "Neither a matching attribute use, "
12772 "nor a matching wildcard in the base type does exist",
12773 NULL);
12774 } else {
12775 /*
12776 * Add the attribute use.
12777 *
12778 * Note that this may lead to funny derivation error reports, if
12779 * multiple equal attribute uses exist; but this is not
12780 * allowed anyway, and it will be reported beforehand.
12781 */
12782 tmp = cur;
12783 if (prev != NULL)
12784 prev->next = cur->next;
12785 else
12786 uses = cur->next;
12787 cur = cur->next;
12788 tmp->next = NULL;
12789 if (type->attributeUses == NULL) {
12790 type->attributeUses = tmp;
12791 } else
12792 lastBaseUse->next = tmp;
12793 lastBaseUse = tmp;
12794
12795 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012796 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012797 }
12798 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012799 cur = cur->next;
12800 }
12801 if (uses != NULL)
12802 xmlSchemaFreeAttributeUseList(uses);
12803 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012804 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012805 /*
12806 * The spec allows only appending, and not other kinds of extensions.
12807 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012808 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012809 */
12810 if (uses != NULL) {
12811 if (type->attributeUses == NULL) {
12812 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012813 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012814 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012815 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012816 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012817 PERROR_INT("xmlSchemaBuildAttributeValidation",
12818 "no derivation method");
12819 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012820 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012821 /*
12822 * 3.4.6 -> Complex Type Definition Properties Correct
12823 */
12824 if (type->attributeUses != NULL) {
12825 cur = type->attributeUses;
12826 prev = NULL;
12827 while (cur != NULL) {
12828 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012829 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012830 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012831 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012832 * Note that this was already done for "restriction" and types derived from
12833 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012834 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012835 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12836 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012837 while (tmp != NULL) {
12838 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012839 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012840 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012841 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012842
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012843 xmlSchemaPAttrUseErr(pctxt,
12844 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12845 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012846 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012847 break;
12848 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012849 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012850 }
12851 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012852 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012853 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012854 * not have {type definition}s which are or are derived from ID.
12855 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012856 if ((cur->attr->subtypes != NULL) &&
12857 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12858 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012859 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012860 xmlSchemaPAttrUseErr(pctxt,
12861 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12862 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012863 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012864 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012865 NULL);
12866 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012867 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012868 id = cur;
12869 }
12870 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012871 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012872 * stage is to be able to catch dublicate attribute uses. So we had to keep
12873 * prohibited uses in the list as well.
12874 */
12875 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12876 tmp = cur;
12877 if (prev == NULL)
12878 type->attributeUses = cur->next;
12879 else
12880 prev->next = cur->next;
12881 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012882 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012883 } else {
12884 prev = cur;
12885 cur = cur->next;
12886 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012887 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012888 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012889 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012890 * TODO: This check should be removed if we are 100% sure of
12891 * the base type attribute uses already being built.
12892 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012893 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012894 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012895 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012896 PERROR_INT("xmlSchemaBuildAttributeValidation",
12897 "attribute uses not builded on base type");
12898 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012899 return (0);
12900}
12901
12902/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012903 * xmlSchemaTypeFinalContains:
12904 * @schema: the schema
12905 * @type: the type definition
12906 * @final: the final
12907 *
12908 * Evaluates if a type definition contains the given "final".
12909 * This does take "finalDefault" into account as well.
12910 *
12911 * Returns 1 if the type does containt the given "final",
12912 * 0 otherwise.
12913 */
12914static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012915xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012916{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012917 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012918 return (0);
12919 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012920 return (1);
12921 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012922 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012923}
12924
12925/**
12926 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12927 * @type: the Union Simple Type
12928 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012929 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012930 * returns NULL otherwise.
12931 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012932static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012933xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12934{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012935 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012936 if (type->memberTypes != NULL)
12937 return (type->memberTypes);
12938 else
12939 type = type->baseType;
12940 }
12941 return (NULL);
12942}
12943
12944/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012945 * xmlSchemaGetParticleTotalRangeMin:
12946 * @particle: the particle
12947 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012948 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012949 * (all and sequence) + (choice)
12950 *
12951 * Returns the minimun Effective Total Range.
12952 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012953static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012954xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012955{
12956 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012957 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012958 return (0);
12959 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012960 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012961 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012962 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012963
12964 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012965 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012966 while (part != NULL) {
12967 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12968 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012969 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012970 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012971 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012972 if (cur == 0)
12973 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012974 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012975 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012976 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012977 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012978 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012979 } else {
12980 /* <all> and <sequence> */
12981 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012982 xmlSchemaParticlePtr part =
12983 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012984
12985 if (part == NULL)
12986 return (0);
12987 do {
12988 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12989 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012990 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012991 else
12992 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012993 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012994 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012995 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012996 }
12997}
12998
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012999/**
13000 * xmlSchemaGetParticleTotalRangeMax:
13001 * @particle: the particle
13002 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013003 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013004 * (all and sequence) + (choice)
13005 *
13006 * Returns the maximum Effective Total Range.
13007 */
13008static int
13009xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13010{
13011 if ((particle->children == NULL) ||
13012 (particle->children->children == NULL))
13013 return (0);
13014 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13015 int max = -1, cur;
13016 xmlSchemaParticlePtr part =
13017 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013018
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013019 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13020 if (part->children == NULL)
13021 continue;
13022 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13023 (part->children->type == XML_SCHEMA_TYPE_ANY))
13024 cur = part->maxOccurs;
13025 else
13026 cur = xmlSchemaGetParticleTotalRangeMax(part);
13027 if (cur == UNBOUNDED)
13028 return (UNBOUNDED);
13029 if ((max < cur) || (max == -1))
13030 max = cur;
13031 }
13032 /* TODO: Handle overflows? */
13033 return (particle->maxOccurs * max);
13034 } else {
13035 /* <all> and <sequence> */
13036 int sum = 0, cur;
13037 xmlSchemaParticlePtr part =
13038 (xmlSchemaParticlePtr) particle->children->children;
13039
13040 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13041 if (part->children == NULL)
13042 continue;
13043 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13044 (part->children->type == XML_SCHEMA_TYPE_ANY))
13045 cur = part->maxOccurs;
13046 else
13047 cur = xmlSchemaGetParticleTotalRangeMax(part);
13048 if (cur == UNBOUNDED)
13049 return (UNBOUNDED);
13050 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13051 return (UNBOUNDED);
13052 sum += cur;
13053 }
13054 /* TODO: Handle overflows? */
13055 return (particle->maxOccurs * sum);
13056 }
13057}
13058
13059/**
13060 * xmlSchemaIsParticleEmptiable:
13061 * @particle: the particle
13062 *
13063 * Schema Component Constraint: Particle Emptiable
13064 * Checks whether the given particle is emptiable.
13065 *
13066 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013067 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013068static int
13069xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13070{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013071 /*
13072 * SPEC (1) "Its {min occurs} is 0."
13073 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013074 if ((particle == NULL) || (particle->minOccurs == 0) ||
13075 (particle->children == NULL))
13076 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013077 /*
13078 * SPEC (2) "Its {term} is a group and the minimum part of the
13079 * effective total range of that group, [...] is 0."
13080 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013081 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013082 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013083 return (1);
13084 }
13085 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013086}
13087
13088/**
13089 * xmlSchemaCheckCOSSTDerivedOK:
13090 * @type: the derived simple type definition
13091 * @baseType: the base type definition
13092 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013093 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013094 * Type Derivation OK (Simple) (cos-st-derived-OK)
13095 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013096 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013097 * derived from @baseType.
13098 *
13099 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013100 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013101static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013102xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13103 xmlSchemaTypePtr baseType,
13104 int subset)
13105{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013106 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013107 * 1 They are the same type definition.
13108 * TODO: The identy check might have to be more complex than this.
13109 */
13110 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013111 return (0);
13112 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013113 * 2.1 restriction is not in the subset, or in the {final}
13114 * of its own {base type definition};
13115 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013116 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013117 (xmlSchemaTypeFinalContains(type->baseType,
13118 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13119 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013120 }
13121 /* 2.2 */
13122 if (type->baseType == baseType) {
13123 /*
13124 * 2.2.1 D's ·base type definition· is B.
13125 */
13126 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013127 }
13128 /*
13129 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13130 * and is validly derived from B given the subset, as defined by this
13131 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013132 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013133 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013134 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013135 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013136 return (0);
13137 }
13138 /*
13139 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013140 * definition·.
13141 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013142 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013143 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013144 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013145 }
13146 /*
13147 * 2.2.4 B's {variety} is union and D is validly derived from a type
13148 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013149 * defined by this constraint.
13150 *
13151 * NOTE: This seems not to involve built-in types, since there is no
13152 * built-in Union Simple Type.
13153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013154 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013155 xmlSchemaTypeLinkPtr cur;
13156
13157 cur = baseType->memberTypes;
13158 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013159 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013160 return (0);
13161 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013162 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013164
Daniel Veillard01fa6152004-06-29 17:04:39 +000013165 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13166}
13167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013168/**
13169 * xmlSchemaCheckTypeDefCircularInternal:
13170 * @pctxt: the schema parser context
13171 * @ctxtType: the type definition
13172 * @ancestor: an ancestor of @ctxtType
13173 *
13174 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013175 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013176 *
13177 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13178 * circular, 0 otherwise.
13179 */
13180static int
13181xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13182 xmlSchemaTypePtr ctxtType,
13183 xmlSchemaTypePtr ancestor)
13184{
13185 int ret;
13186
13187 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13188 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013189
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013190 if (ctxtType == ancestor) {
13191 xmlSchemaPCustomErr(pctxt,
13192 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13193 NULL, ctxtType, GET_NODE(ctxtType),
13194 "The definition is circular", NULL);
13195 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13196 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013197 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13198 /*
13199 * Avoid inifinite recursion on circular types not yet checked.
13200 */
13201 return (0);
13202 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013203 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13204 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13205 ancestor->baseType);
13206 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13207 return (ret);
13208}
13209
13210/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013211 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013212 * @item: the complex/simple type definition
13213 * @ctxt: the parser context
13214 * @name: the name
13215 *
13216 * Checks for circular type definitions.
13217 */
13218static void
13219xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013220 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013221 const xmlChar * name ATTRIBUTE_UNUSED)
13222{
13223 if ((item == NULL) ||
13224 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13225 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13226 return;
13227 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13228
13229}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013230
13231/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013232 * xmlSchemaResolveTypeDefs:
13233 * @item: the complex/simple type definition
13234 * @ctxt: the parser context
13235 * @name: the name
13236 *
13237 * Checks for circular type definitions.
13238 */
13239static void
13240xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013241 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013242 const xmlChar * name ATTRIBUTE_UNUSED)
13243{
13244 if (typeDef == NULL)
13245 return;
13246
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013247 /*
13248 * Resolve the base type.
13249 */
13250 if (typeDef->baseType == NULL) {
13251 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13252 typeDef->base, typeDef->baseNs);
13253 if (typeDef->baseType == NULL) {
13254 xmlSchemaPResCompAttrErr(ctxt,
13255 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013256 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013257 "base", typeDef->base, typeDef->baseNs,
13258 XML_SCHEMA_TYPE_SIMPLE, NULL);
13259 return;
13260 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013261 }
13262 if (IS_SIMPLE_TYPE(typeDef)) {
13263 if (VARIETY_UNION(typeDef)) {
13264 /*
13265 * Resolve the memberTypes.
13266 */
13267 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13268 return;
13269 } else if (VARIETY_LIST(typeDef)) {
13270 /*
13271 * Resolve the itemType.
13272 */
13273 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13274 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13275 typeDef->ref, typeDef->refNs);
13276 if ((typeDef->subtypes == NULL) ||
13277 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13278 typeDef->subtypes = NULL;
13279 xmlSchemaPResCompAttrErr(ctxt,
13280 XML_SCHEMAP_SRC_RESOLVE,
13281 typeDef, typeDef->node,
13282 "itemType", typeDef->ref, typeDef->refNs,
13283 XML_SCHEMA_TYPE_SIMPLE, NULL);
13284 }
13285 }
13286 return;
13287 }
13288 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013289}
13290
13291
13292
13293/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013294 * xmlSchemaCheckSTPropsCorrect:
13295 * @ctxt: the schema parser context
13296 * @type: the simple type definition
13297 *
13298 * Checks st-props-correct.
13299 *
13300 * Returns 0 if the properties are correct,
13301 * if not, a positive error code and -1 on internal
13302 * errors.
13303 */
13304static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013305xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013306 xmlSchemaTypePtr type)
13307{
13308 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13309 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013310 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013311
Daniel Veillardc0826a72004-08-10 14:17:33 +000013312 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013313 /*
13314 * Schema Component Constraint: Simple Type Definition Properties Correct
13315 *
13316 * NOTE: This is somehow redundant, since we actually built a simple type
13317 * to have all the needed information; this acts as an self test.
13318 */
13319 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13320 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013321 /* Base type: If the datatype has been ·derived· by ·restriction·
13322 * then the Simple Type Definition component from which it is ·derived·,
13323 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013324 */
13325 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013326 /*
13327 * TODO: Think about: "modulo the impact of Missing
13328 * Sub-components (§5.3)."
13329 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013330 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013331 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013332 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013333 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013334 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013335
Daniel Veillard01fa6152004-06-29 17:04:39 +000013336 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013337 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013338 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013339 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013340 NULL, type, NULL,
13341 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013342 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013343 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013344 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13345 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013346 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13347 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13348 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013349 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013350 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013351 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013352 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013353 "the simple ur-type definition as base type, not '%s'",
13354 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013355 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013356 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13357 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013358 /*
13359 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013360 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013361 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13362 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013363 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013364 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013365 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013366 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013367 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13368 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013369 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013370
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013371 /*
13372 * 3 The {final} of the {base type definition} must not contain restriction.
13373 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013374 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013375 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13376 xmlSchemaPCustomErr(ctxt,
13377 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013378 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013379 "The 'final' of its base type '%s' must not contain "
13380 "'restriction'",
13381 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013382 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013383 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013385
13386 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013387 * 2 All simple type definitions must be derived ultimately from the ·simple
13388 * ur-type definition (so· circular definitions are disallowed). That is, it
13389 * must be possible to reach a built-in primitive datatype or the ·simple
13390 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013391 *
13392 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013393 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013394 return (0);
13395}
13396
13397/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013398 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013399 * @ctxt: the schema parser context
13400 * @type: the simple type definition
13401 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013402 * Schema Component Constraint:
13403 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13404
13405 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013406 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013407 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013409 * a positive error code otherwise.
13410 */
13411static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013412xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013413 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013414{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013415 xmlChar *str = NULL;
13416
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13419 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013420 return (-1);
13421 }
13422
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013423 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013424 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013425 /*
13426 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428 */
13429 if (! VARIETY_ATOMIC(type->baseType)) {
13430 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013431 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013433 "The base type '%s' is not an atomic simple type",
13434 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013435 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013436 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13437 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 * restriction.
13440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013441 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013442 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013445 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013447 "The final of its base type '%s' must not contain 'restriction'",
13448 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013449 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13451 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452
13453 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013454 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013455 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013456 * Primitive datatypes.
13457 */
13458 if (type->facets != NULL) {
13459 xmlSchemaFacetPtr facet;
13460 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013461
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 primitive = xmlSchemaGetPrimitiveType(type);
13463 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013464 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13465 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013467 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468 facet = type->facets;
13469 do {
13470 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013471 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013474 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013475 }
13476 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013477 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013478 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013479 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 }
13481 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013482 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13483 * of the {base type definition} (call this BF),then the DF's {value}
13484 * must be a valid restriction of BF's {value} as defined in
13485 * [XML Schemas: Datatypes]."
13486 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013488 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013489 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013491 xmlSchemaTypePtr itemType = NULL;
13492
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013493 itemType = type->subtypes;
13494 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13496 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013497 return (-1);
13498 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013499 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013502 * 2.1 The {item type definition} must have a {variety} of atomic or
13503 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013504 * must be atomic).
13505 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013506 if ((! VARIETY_ATOMIC(itemType)) &&
13507 (! VARIETY_UNION(itemType))) {
13508 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013509 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013510 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013511 "The item type '%s' does not have a variety of atomic or union",
13512 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013513 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013514 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013515 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013516 xmlSchemaTypeLinkPtr member;
13517
13518 member = itemType->memberTypes;
13519 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013520 if (! VARIETY_ATOMIC(member->type)) {
13521 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013524 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013525 "member type '%s' of this item type is not atomic",
13526 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013527 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013528 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13529 }
13530 member = member->next;
13531 }
13532 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013533
13534 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 xmlSchemaFacetPtr facet;
13536 /*
13537 * This is the case if we have: <simpleType><list ..
13538 */
13539 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 * 2.3.1
13541 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013542 * contain list.
13543 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 if (xmlSchemaTypeFinalContains(itemType,
13545 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13546 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013547 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013548 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013549 "The final of its item type '%s' must not contain 'list'",
13550 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013552 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13553 }
13554 /*
13555 * 2.3.1.2 The {facets} must only contain the whiteSpace
13556 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557 * OPTIMIZE TODO: the S4S already disallows any facet
13558 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013559 */
13560 if (type->facets != NULL) {
13561 facet = type->facets;
13562 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013563 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013565 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013566 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013567 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13568 }
13569 facet = facet->next;
13570 } while (facet != NULL);
13571 }
13572 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013573 * MAYBE TODO: (Hmm, not really) Datatypes states:
13574 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13575 * whose ·lexical space· allows space (such as string or anyURI)or
13576 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 * ·lexical space· allows space.
13578 */
13579 } else {
13580 /*
13581 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013582 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 */
13584 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013585 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013588 if (! VARIETY_LIST(type->baseType)) {
13589 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013590 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013591 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013592 "The base type '%s' must be a list type",
13593 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013594 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013595 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13596 }
13597 /*
13598 * 2.3.2.2 The {final} of the {base type definition} must not
13599 * contain restriction.
13600 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013601 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013602 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013603 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013604 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013605 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013606 "The 'final' of the base type '%s' must not contain 'restriction'",
13607 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013608 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13610 }
13611 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013613 * from the {base type definition}'s {item type definition} given
13614 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13615 */
13616 {
13617 xmlSchemaTypePtr baseItemType;
13618
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013619 baseItemType = type->baseType->subtypes;
13620 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013621 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13622 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 return (-1);
13624 }
13625 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13627 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013628 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013630 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 NULL, type, NULL,
13632 "The item type '%s' is not validly derived from "
13633 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013634 xmlSchemaGetComponentQName(&str, itemType),
13635 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13636 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013637
13638 FREE_AND_NULL(str)
13639 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013640 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013641 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13642 }
13643 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013644
Daniel Veillard01fa6152004-06-29 17:04:39 +000013645 if (type->facets != NULL) {
13646 xmlSchemaFacetPtr facet;
13647 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013648 /*
13649 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013650 * and enumeration facet components are allowed among the {facets}.
13651 */
13652 facet = type->facets;
13653 do {
13654 switch (facet->type) {
13655 case XML_SCHEMA_FACET_LENGTH:
13656 case XML_SCHEMA_FACET_MINLENGTH:
13657 case XML_SCHEMA_FACET_MAXLENGTH:
13658 case XML_SCHEMA_FACET_WHITESPACE:
13659 /*
13660 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013661 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013662 */
13663 case XML_SCHEMA_FACET_PATTERN:
13664 case XML_SCHEMA_FACET_ENUMERATION:
13665 break;
13666 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013667 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013668 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013669 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013670 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013671 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013672 * invalid facets.
13673 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013675 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013676 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013677 facet = facet->next;
13678 } while (facet != NULL);
13679 if (ok == 0)
13680 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13681 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013682 * SPEC (2.3.2.5) (same as 1.3.2)
13683 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013684 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013685 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013686 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013687 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013688 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013689 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013691 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013692 * atomic or list.
13693 */
13694 xmlSchemaTypeLinkPtr member;
13695
13696 member = type->memberTypes;
13697 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013698 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013700
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013701 if ((! VARIETY_ATOMIC(member->type)) &&
13702 (! VARIETY_LIST(member->type))) {
13703 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013704 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013705 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013706 "The member type '%s' is neither an atomic, nor a list type",
13707 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013708 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13710 }
13711 member = member->next;
13712 }
13713 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 * 3.3.1 If the {base type definition} is the ·simple ur-type
13715 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013717 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013719 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013720 * {final} which does not contain union.
13721 */
13722 member = type->memberTypes;
13723 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013726 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013728 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013729 "The 'final' of member type '%s' contains 'union'",
13730 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013731 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13733 }
13734 member = member->next;
13735 }
13736 /*
13737 * 3.3.1.2 The {facets} must be empty.
13738 */
13739 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013740 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013742 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013743 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013744 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13745 }
13746 } else {
13747 /*
13748 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013749 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013750 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013751 if (! VARIETY_UNION(type->baseType)) {
13752 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013754 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013755 "The base type '%s' is not a union type",
13756 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013757 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013758 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13759 }
13760 /*
13761 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13762 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013767 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013768 "The 'final' of its base type '%s' must not contain 'restriction'",
13769 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013770 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13772 }
13773 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774 * 3.3.2.3 The {member type definitions}, in order, must be validly
13775 * derived from the corresponding type definitions in the {base
13776 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013777 * as defined in Type Derivation OK (Simple) (§3.14.6).
13778 */
13779 {
13780 xmlSchemaTypeLinkPtr baseMember;
13781
13782 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013783 * OPTIMIZE: if the type is restricting, it has no local defined
13784 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 * thus a check for equality can be skipped.
13786 */
13787 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013788 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013789 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013790 * types of it's base type. This check seems not necessary with
13791 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013792 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013793 */
13794 if (type->memberTypes != NULL) {
13795 member = type->memberTypes;
13796 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 if ((member == NULL) && (baseMember != NULL)) {
13798 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13799 "different number of member types in base");
13800 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 while (member != NULL) {
13802 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13804 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 }
13806 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 (xmlSchemaCheckCOSSTDerivedOK(
13808 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013809 xmlChar *strBMT = NULL, *strBT = NULL;
13810
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013811 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013812 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13813 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013814 "The member type %s is not validly "
13815 "derived from its corresponding member "
13816 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013817 xmlSchemaGetComponentQName(&str, member->type),
13818 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13819 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013820 FREE_AND_NULL(str)
13821 FREE_AND_NULL(strBMT)
13822 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013823 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013824 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013825 member = member->next;
13826 baseMember = baseMember->next;
13827 }
13828 }
13829 }
13830 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013831 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013833 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013834 if (type->facets != NULL) {
13835 xmlSchemaFacetPtr facet;
13836 int ok = 1;
13837
13838 facet = type->facets;
13839 do {
13840 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13841 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013842 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013844 NULL, type, facet);
13845 ok = 0;
13846 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013847 facet = facet->next;
13848 } while (facet != NULL);
13849 if (ok == 0)
13850 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013851
Daniel Veillard01fa6152004-06-29 17:04:39 +000013852 }
13853 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013854 * SPEC (3.3.2.5) (same as 1.3.2)
13855 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013856 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013857 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858 */
13859 }
13860 }
13861
13862 return (0);
13863}
13864
13865/**
13866 * xmlSchemaCheckSRCSimpleType:
13867 * @ctxt: the schema parser context
13868 * @type: the simple type definition
13869 *
13870 * Checks crc-simple-type constraints.
13871 *
13872 * Returns 0 if the constraints are satisfied,
13873 * if not a positive error code and -1 on internal
13874 * errors.
13875 */
13876static int
13877xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13878 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013879{
13880 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013881 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013882 * must satisfy the conditions set out in Constraints on Simple Type
13883 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013884 */
13885 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13886 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13887 /*
13888 * TODO: Removed this, since it got annoying to get an
13889 * extra error report, if anything failed until now.
13890 * Enable this if needed.
13891 */
13892 /*
13893 xmlSchemaPErr(ctxt, type->node,
13894 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013895 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013896 "on simple type definitions.\n",
13897 type->name, NULL);
13898 */
13899 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13900 }
13901
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013902 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013903 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013904 * src-simple-type.2 If the <restriction> alternative is chosen,
13905 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013906 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013907 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013908 /*
13909 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013910 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013911 */
13912 } else if (VARIETY_LIST(type)) {
13913 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13914 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013915 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013916 *
13917 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013918 */
13919 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013920 xmlSchemaTypeLinkPtr member;
13921 xmlSchemaTypePtr ancestor, anySimpleType;
13922
13923 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13924
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013925 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13926 * the <union> alternative is chosen, there must not be any entries
13927 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013928 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013929 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013930 member = type->memberTypes;
13931 while (member != NULL) {
13932 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013933 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013934 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013935 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013936 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013937 NULL, type, NULL,
13938 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013939 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013940 }
13941 if (IS_NOT_TYPEFIXED(ancestor))
13942 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013943 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013944 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013945 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946 * type as item type, which in turn has a list ST as member
13947 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013948 * was not yet performed.
13949 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013950 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013951
Daniel Veillard01fa6152004-06-29 17:04:39 +000013952 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013953 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013954 member = member->next;
13955 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013956 }
13957
13958 return (0);
13959}
13960
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013961static int
13962xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13963{
13964 if (ctxt->vctxt == NULL) {
13965 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13966 if (ctxt->vctxt == NULL) {
13967 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013968 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013970 "failed to create a temp. validation context.\n",
13971 NULL, NULL);
13972 return (-1);
13973 }
13974 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013975 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013976 }
13977 return (0);
13978}
13979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013980static int
13981xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
13982 xmlNodePtr node,
13983 xmlSchemaTypePtr type,
13984 const xmlChar *value,
13985 xmlSchemaValPtr *retVal,
13986 int fireErrors,
13987 int normalize,
13988 int isNormalized);
13989
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013990/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013991 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013992 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013993 * @type: the simple type definition
13994 * @value: the default value
13995 * @node: an optional node (the holder of the value)
13996 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013997 * Schema Component Constraint: Element Default Valid (Immediate)
13998 * (cos-valid-default)
13999 * This will be used by the parser only. For the validator there's
14000 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014001 *
14002 * Returns 0 if the constraints are satisfied,
14003 * if not, a positive error code and -1 on internal
14004 * errors.
14005 */
14006static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014007xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14008 xmlNodePtr node,
14009 xmlSchemaTypePtr type,
14010 const xmlChar *value,
14011 xmlSchemaValPtr *val)
14012{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014013 int ret = 0;
14014
14015 /*
14016 * cos-valid-default:
14017 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014018 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014019 * definition the appropriate case among the following must be true:
14020 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014021 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014022 /*
14023 * Complex type.
14024 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014025 * SPEC (2.1) "its {content type} must be a simple type definition
14026 * or mixed."
14027 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014028 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014029 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014030 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014031 if ((! HAS_SIMPLE_CONTENT(type)) &&
14032 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14033 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014034 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014035 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014036 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014037 "For a string to be a valid default, the type definition "
14038 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014039 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014040 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14041 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014042 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014043 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014044 * 1 If the type definition is a simple type definition, then the string
14045 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014046 * Valid (§3.14.4).
14047 *
14048 * AND
14049 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014050 * 2.2.1 If the {content type} is a simple type definition, then the
14051 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014052 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014053 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014054 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014055 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14056 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014057 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014058 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14059 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014060 else
14061 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014062
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014063 if (ret < 0) {
14064 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14065 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014066 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014067
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014068 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014069}
14070
14071/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014072 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014073 * @ctxt: the schema parser context
14074 * @type: the complex type definition
14075 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014076 *.(4.6) Constraints on Complex Type Definition Schema Components
14077 * Schema Component Constraint:
14078 * Complex Type Definition Properties Correct (ct-props-correct)
14079 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014080 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014081 * Returns 0 if the constraints are satisfied, a positive
14082 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014083 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014084static int
14085xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14086 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014087{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014088 /*
14089 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14090 *
14091 * SPEC (1) "The values of the properties of a complex type definition must
14092 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014093 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014094 * Sub-components (§5.3)."
14095 */
14096 if ((type->baseType != NULL) &&
14097 (IS_SIMPLE_TYPE(type->baseType)) &&
14098 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14099 /*
14100 * SPEC (2) "If the {base type definition} is a simple type definition,
14101 * the {derivation method} must be extension."
14102 */
14103 xmlSchemaPCustomErr(pctxt,
14104 XML_SCHEMAP_SRC_CT_1,
14105 NULL, type, NULL,
14106 "If the base type is a simple type, the derivation method must be "
14107 "'extension'", NULL);
14108 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014110 /*
14111 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14112 * definition·. That is, it must be possible to reach the ·ur-type
14113 * definition by repeatedly following the {base type definition}."
14114 *
14115 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14116 *
14117 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014118 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014119 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14120 * must not have {type definition}s which are or are derived from ID."
14121 *
14122 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14123 */
14124 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014125}
14126
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014127static int
14128xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14129 xmlSchemaTypePtr typeB)
14130{
14131 /*
14132 * TODO: This should implement component-identity
14133 * in the future.
14134 */
14135 if ((typeA == NULL) || (typeB == NULL))
14136 return (0);
14137 return (typeA == typeB);
14138}
14139
14140/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014141 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014142 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014143 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014144 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014145 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014146 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014147 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014148 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14149 *
14150 * STATUS: completed
14151 *
14152 * Returns 0 if the constraints are satisfied, or 1
14153 * if not.
14154 */
14155static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014156xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014157 xmlSchemaTypePtr baseType,
14158 int set)
14159{
14160 int equal = xmlSchemaAreEqualTypes(type, baseType);
14161 /* TODO: Error codes. */
14162 /*
14163 * SPEC "For a complex type definition (call it D, for derived)
14164 * to be validly derived from a type definition (call this
14165 * B, for base) given a subset of {extension, restriction}
14166 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014167 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014168 if (! equal) {
14169 /*
14170 * SPEC (1) "If B and D are not the same type definition, then the
14171 * {derivation method} of D must not be in the subset."
14172 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014173 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014174 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014175 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014176 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014177 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014178 } else {
14179 /*
14180 * SPEC (2.1) "B and D must be the same type definition."
14181 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014182 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014183 }
14184 /*
14185 * SPEC (2.2) "B must be D's {base type definition}."
14186 */
14187 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014188 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014189 /*
14190 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14191 * definition·."
14192 */
14193 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014194 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014195
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014196 if (IS_COMPLEX_TYPE(type->baseType)) {
14197 /*
14198 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14199 * must be validly derived from B given the subset as defined by this
14200 * constraint."
14201 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014202 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014203 baseType, set));
14204 } else {
14205 /*
14206 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14207 * must be validly derived from B given the subset as defined in Type
14208 * Derivation OK (Simple) (§3.14.6).
14209 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014210 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14211 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014212}
14213
14214/**
14215 * xmlSchemaCheckCOSDerivedOK:
14216 * @type: the derived simple type definition
14217 * @baseType: the base type definition
14218 *
14219 * Calls:
14220 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014221 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014222 * Checks wheter @type can be validly derived from @baseType.
14223 *
14224 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014225 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014226static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014227xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014228 xmlSchemaTypePtr baseType,
14229 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014230{
14231 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014232 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014233 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014234 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014235}
14236
William M. Brack2f2a6632004-08-20 23:09:47 +000014237/**
14238 * xmlSchemaCheckCOSCTExtends:
14239 * @ctxt: the schema parser context
14240 * @type: the complex type definition
14241 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014242 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014243 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014244 * Derivation Valid (Extension) (cos-ct-extends)
14245 *
14246 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014247 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014248 * (1.5)
14249 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014250 *
14251 * Returns 0 if the constraints are satisfied, a positive
14252 * error code if not and -1 if an internal error occured.
14253 */
14254static int
14255xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14256 xmlSchemaTypePtr type)
14257{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014258 xmlSchemaTypePtr base = type->baseType;
14259 /*
14260 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14261 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014262 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014263 /*
14264 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014265 * then all of the following must be true:"
14266 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014267 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14268 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014269 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014270 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014271 */
14272 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14273 xmlSchemaPCustomErr(ctxt,
14274 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14275 NULL, type, NULL,
14276 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014277 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014278 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14279 }
14280 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014281 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014282 * uses}
14283 * of the complex type definition itself, that is, for every attribute
14284 * use in the {attribute uses} of the {base type definition}, there
14285 * must be an attribute use in the {attribute uses} of the complex
14286 * type definition itself whose {attribute declaration} has the same
14287 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014288 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014289 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014290 * NOTE (1.2): This will be already satisfied by the way the attribute
14291 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14292 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014293 */
14294
14295 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014296 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14297 * definition must also have one, and the base type definition's
14298 * {attribute wildcard}'s {namespace constraint} must be a subset
14299 * of the complex type definition's {attribute wildcard}'s {namespace
14300 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014301 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014302 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014303 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014304 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014305 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014306 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014307 if ((type->contentTypeDef != NULL) &&
14308 (type->contentTypeDef == base->contentTypeDef)) {
14309 /*
14310 * SPEC (1.4.1) "The {content type} of the {base type definition}
14311 * and the {content type} of the complex type definition itself
14312 * must be the same simple type definition"
14313 * PASS
14314 */
14315 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14316 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14317 /*
14318 * SPEC (1.4.2) "The {content type} of both the {base type
14319 * definition} and the complex type definition itself must
14320 * be empty."
14321 * PASS
14322 */
14323 } else {
14324 /*
14325 * SPEC (1.4.3) "All of the following must be true:"
14326 */
14327 if (type->subtypes == NULL) {
14328 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014329 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014330 * definition itself must specify a particle.
14331 */
14332 xmlSchemaPCustomErr(ctxt,
14333 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14334 NULL, type, NULL,
14335 "The content type must specify a particle", NULL);
14336 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14337 }
14338 /*
14339 * SPEC (1.4.3.2) "One of the following must be true:"
14340 */
14341 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14342 /*
14343 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14344 * definition} must be empty.
14345 * PASS
14346 */
14347 } else {
14348 /*
14349 * SPEC (1.4.3.2.2) "All of the following must be true:"
14350 */
14351 if ((type->contentType != base->contentType) ||
14352 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14353 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14354 /*
14355 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14356 * or both must be element-only."
14357 */
14358 xmlSchemaPCustomErr(ctxt,
14359 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14360 NULL, type, NULL,
14361 "The content type of both, the type and its base "
14362 "type, must either 'mixed' or 'element-only'", NULL);
14363 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014364 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014365 /*
14366 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14367 * complex type definition must be a ·valid extension·
14368 * of the {base type definition}'s particle, as defined
14369 * in Particle Valid (Extension) (§3.9.6)."
14370 *
14371 * NOTE that we won't check "Particle Valid (Extension)",
14372 * since it is ensured by the derivation process in
14373 * xmlSchemaTypeFixup(). We need to implement this when heading
14374 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014375 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014376 }
14377 /*
14378 * TODO (1.5)
14379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014380 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014381 } else {
14382 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014383 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014384 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014385 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014386 if (type->contentTypeDef != base) {
14387 /*
14388 * SPEC (2.1) "The {content type} must be the same simple type
14389 * definition."
14390 */
14391 xmlSchemaPCustomErr(ctxt,
14392 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14393 NULL, type, NULL,
14394 "The content type must be the simple base type", NULL);
14395 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14396 }
14397 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14398 /*
14399 * SPEC (2.2) "The {final} of the {base type definition} must not
14400 * contain extension"
14401 * NOTE that this is the same as (1.1).
14402 */
14403 xmlSchemaPCustomErr(ctxt,
14404 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14405 NULL, type, NULL,
14406 "The 'final' of the base type definition "
14407 "contains 'extension'", NULL);
14408 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014409 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014410 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014411 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014412}
14413
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014414/**
14415 * xmlSchemaCheckDerivationOKRestriction:
14416 * @ctxt: the schema parser context
14417 * @type: the complex type definition
14418 *
14419 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014420 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014421 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14422 *
14423 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014424 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014425 * (5.4.2), (5.2.2.1)
14426 *
14427 * Returns 0 if the constraints are satisfied, a positive
14428 * error code if not and -1 if an internal error occured.
14429 */
14430static int
14431xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14432 xmlSchemaTypePtr type)
14433{
14434 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014435
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014436 /*
14437 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14438 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014439 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014440 base = type->baseType;
14441 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14442 /*
14443 * SPEC (1) "The {base type definition} must be a complex type
14444 * definition whose {final} does not contain restriction."
14445 */
14446 xmlSchemaPCustomErr(ctxt,
14447 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14448 NULL, type, NULL,
14449 "The 'final' of the base type definition "
14450 "contains 'restriction'", NULL);
14451 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14452 }
14453 /*
14454 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14455 *
14456 * SPEC (5) "One of the following must be true:"
14457 */
14458 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14459 /*
14460 * SPEC (5.1) "The {base type definition} must be the
14461 * ·ur-type definition·."
14462 * PASS
14463 */
14464 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14465 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14466 /*
14467 * SPEC (5.2.1) "The {content type} of the complex type definition
14468 * must be a simple type definition"
14469 *
14470 * SPEC (5.2.2) "One of the following must be true:"
14471 */
14472 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14473 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14474 /*
14475 * SPEC (5.2.2.1) "The {content type} of the {base type
14476 * definition} must be a simple type definition from which
14477 * the {content type} is validly derived given the empty
14478 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14479 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014480 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014481 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14482 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014483 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014484 /*
14485 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14486 * and have a particle which is ·emptiable· as defined in
14487 * Particle Emptiable (§3.9.6)."
14488 * PASS
14489 */
14490 } else {
14491 xmlSchemaPCustomErr(ctxt,
14492 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14493 NULL, type, NULL,
14494 "The content type of the base type must be either "
14495 "a simple type or 'mixed' and an emptiable particle", NULL);
14496 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14497 }
14498 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14499 /*
14500 * SPEC (5.3.1) "The {content type} of the complex type itself must
14501 * be empty"
14502 */
14503 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14504 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014505 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014506 * definition} must also be empty."
14507 * PASS
14508 */
14509 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14510 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14511 xmlSchemaIsParticleEmptiable(
14512 (xmlSchemaParticlePtr) base->subtypes)) {
14513 /*
14514 * SPEC (5.3.2.2) "The {content type} of the {base type
14515 * definition} must be elementOnly or mixed and have a particle
14516 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14517 * PASS
14518 */
14519 } else {
14520 xmlSchemaPCustomErr(ctxt,
14521 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14522 NULL, type, NULL,
14523 "The content type of the base type must be either "
14524 "empty or 'mixed' (or 'elements-only') and an emptiable "
14525 "particle", NULL);
14526 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14527 }
14528 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014529 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014530 /*
14531 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14532 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014533 */
14534 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14535 /*
14536 * SPEC (5.4.1.2) "The {content type} of the complex type
14537 * definition itself and of the {base type definition} must be
14538 * mixed"
14539 */
14540 xmlSchemaPCustomErr(ctxt,
14541 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14542 NULL, type, NULL,
14543 "If the content type is 'mixed', then the content type of the "
14544 "base type must also be 'mixed'", NULL);
14545 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14546 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014547 /*
14548 * SPEC (5.4.2) "The particle of the complex type definition itself
14549 * must be a ·valid restriction· of the particle of the {content
14550 * type} of the {base type definition} as defined in Particle Valid
14551 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014552 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014553 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014554 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014555 } else {
14556 xmlSchemaPCustomErr(ctxt,
14557 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14558 NULL, type, NULL,
14559 "The type is not a valid restriction of its base type", NULL);
14560 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14561 }
14562 return (0);
14563}
14564
14565/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014566 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014567 * @ctxt: the schema parser context
14568 * @type: the complex type definition
14569 *
14570 * (3.4.6) Constraints on Complex Type Definition Schema Components
14571 *
14572 * Returns 0 if the constraints are satisfied, a positive
14573 * error code if not and -1 if an internal error occured.
14574 */
14575static int
14576xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14577 xmlSchemaTypePtr type)
14578{
14579 int ret;
14580 /*
14581 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014582 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014583 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14584 if (ret != 0)
14585 return (ret);
14586 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14587 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14588 else
14589 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14590 return (ret);
14591}
14592
14593/**
14594 * xmlSchemaCheckSRCCT:
14595 * @ctxt: the schema parser context
14596 * @type: the complex type definition
14597 *
14598 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014599 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014600 * Complex Type Definition Representation OK (src-ct)
14601 *
14602 * Returns 0 if the constraints are satisfied, a positive
14603 * error code if not and -1 if an internal error occured.
14604 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014605static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014606xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014607 xmlSchemaTypePtr type)
14608{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014609 xmlSchemaTypePtr base;
14610 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014611
14612 /*
14613 * TODO: Adjust the error codes here, as I used
14614 * XML_SCHEMAP_SRC_CT_1 only yet.
14615 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014616 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014617 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014618 /*
14619 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014620 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014621 * must be a complex type definition;
14622 */
14623 if (! IS_COMPLEX_TYPE(base)) {
14624 xmlChar *str = NULL;
14625 xmlSchemaPCustomErr(ctxt,
14626 XML_SCHEMAP_SRC_CT_1,
14627 NULL, type, type->node,
14628 "If using <complexContent>, the base type is expected to be "
14629 "a complex type. The base type '%s' is a simple type",
14630 xmlSchemaFormatQName(&str, base->targetNamespace,
14631 base->name));
14632 FREE_AND_NULL(str)
14633 return (XML_SCHEMAP_SRC_CT_1);
14634 }
14635 } else {
14636 /*
14637 * SPEC
14638 * 2 If the <simpleContent> alternative is chosen, all of the
14639 * following must be true:
14640 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14641 * base [attribute] must be one of the following:
14642 */
14643 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014644 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014645 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14646 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014647 /*
14648 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014649 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014650 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014651 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014652 xmlSchemaPCustomErr(ctxt,
14653 XML_SCHEMAP_SRC_CT_1,
14654 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014655 "If using <simpleContent> and <restriction>, the base "
14656 "type must be a complex type. The base type '%s' is "
14657 "a simple type",
14658 xmlSchemaFormatQName(&str, base->targetNamespace,
14659 base->name));
14660 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014661 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014662 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014663 } else {
14664 /* Base type is a complex type. */
14665 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14666 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14667 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014669 * simple type definition;
14670 * PASS
14671 */
14672 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014673 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014674 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014675 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014676 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014677 type->name);
14678 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014679 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014680 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14681 (type->flags &
14682 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014683
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014684 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014685 * 2.1.2 only if the <restriction> alternative is also
14686 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014687 * is mixed and a particle emptiable.
14688 */
14689 if (! xmlSchemaIsParticleEmptiable(
14690 (xmlSchemaParticlePtr) base->subtypes)) {
14691 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014692 } else
14693 /*
14694 * Attention: at this point the <simpleType> child is in
14695 * ->contentTypeDef (put there during parsing).
14696 */
14697 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014698 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014699 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014700 * 2.2 If clause 2.1.2 above is satisfied, then there
14701 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014702 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014703 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014704 /* TODO: Change error code to ..._SRC_CT_2_2. */
14705 xmlSchemaPCustomErr(ctxt,
14706 XML_SCHEMAP_SRC_CT_1,
14707 NULL, type, NULL,
14708 "A <simpleType> is expected among the children "
14709 "of <restriction>, if <simpleContent> is used and "
14710 "the base type '%s' is a complex type",
14711 xmlSchemaFormatQName(&str, base->targetNamespace,
14712 base->name));
14713 FREE_AND_NULL(str)
14714 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014715 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014716 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014717 ret = XML_SCHEMAP_SRC_CT_1;
14718 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014719 }
14720 if (ret > 0) {
14721 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014722 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014723 xmlSchemaPCustomErr(ctxt,
14724 XML_SCHEMAP_SRC_CT_1,
14725 NULL, type, NULL,
14726 "If <simpleContent> and <restriction> is used, the "
14727 "base type must be a simple type or a complex type with "
14728 "mixed content and particle emptiable. The base type "
14729 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014730 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014731 base->name));
14732 } else {
14733 xmlSchemaPCustomErr(ctxt,
14734 XML_SCHEMAP_SRC_CT_1,
14735 NULL, type, NULL,
14736 "If <simpleContent> and <extension> is used, the "
14737 "base type must be a simple type. The base type '%s' "
14738 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014739 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014740 base->name));
14741 }
14742 FREE_AND_NULL(str)
14743 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014744 }
14745 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 * SPEC (3) "The corresponding complex type definition component must
14747 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014748 * Definition Schema Components (§3.4.6);"
14749 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014750 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014751 /*
14752 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014753 * above for {attribute wildcard} is satisfied, the intensional
14754 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014755 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014756 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014757 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014758 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014759}
William M. Brack2f2a6632004-08-20 23:09:47 +000014760
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014761#ifdef ENABLE_PARTICLE_RESTRICTION
14762/**
14763 * xmlSchemaCheckParticleRangeOK:
14764 * @ctxt: the schema parser context
14765 * @type: the complex type definition
14766 *
14767 * (3.9.6) Constraints on Particle Schema Components
14768 * Schema Component Constraint:
14769 * Occurrence Range OK (range-ok)
14770 *
14771 * STATUS: complete
14772 *
14773 * Returns 0 if the constraints are satisfied, a positive
14774 * error code if not and -1 if an internal error occured.
14775 */
14776static int
14777xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14778 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014779{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014780 if (rmin < bmin)
14781 return (1);
14782 if ((bmax != UNBOUNDED) &&
14783 (rmax > bmax))
14784 return (1);
14785 return (0);
14786}
14787
14788/**
14789 * xmlSchemaCheckRCaseNameAndTypeOK:
14790 * @ctxt: the schema parser context
14791 * @r: the restricting element declaration particle
14792 * @b: the base element declaration particle
14793 *
14794 * (3.9.6) Constraints on Particle Schema Components
14795 * Schema Component Constraint:
14796 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14797 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014798 *
14799 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014800 * MISSING (3.2.3)
14801 * CLARIFY: (3.2.2)
14802 *
14803 * Returns 0 if the constraints are satisfied, a positive
14804 * error code if not and -1 if an internal error occured.
14805 */
14806static int
14807xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14808 xmlSchemaParticlePtr r,
14809 xmlSchemaParticlePtr b)
14810{
14811 xmlSchemaElementPtr elemR, elemB;
14812
14813 /* TODO: Error codes (rcase-NameAndTypeOK). */
14814 elemR = (xmlSchemaElementPtr) r->children;
14815 elemB = (xmlSchemaElementPtr) b->children;
14816 /*
14817 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14818 * the same."
14819 */
14820 if ((elemR != elemB) &&
14821 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14822 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14823 return (1);
14824 /*
14825 * SPEC (2) "R's occurrence range is a valid restriction of B's
14826 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14827 */
14828 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14829 b->minOccurs, b->maxOccurs) != 0)
14830 return (1);
14831 /*
14832 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14833 * {scope} are global."
14834 */
14835 if (elemR == elemB)
14836 return (0);
14837 /*
14838 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14839 */
14840 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14841 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14842 return (1);
14843 /*
14844 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14845 * or is not fixed, or R's declaration's {value constraint} is fixed
14846 * with the same value."
14847 */
14848 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14849 ((elemR->value == NULL) ||
14850 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14851 /* TODO: Equality of the initial value or normalized or canonical? */
14852 (! xmlStrEqual(elemR->value, elemB->value))))
14853 return (1);
14854 /*
14855 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14856 * definitions} is a subset of B's declaration's {identity-constraint
14857 * definitions}, if any."
14858 */
14859 if (elemB->idcs != NULL) {
14860 /* TODO */
14861 }
14862 /*
14863 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14864 * superset of B's declaration's {disallowed substitutions}."
14865 */
14866 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14867 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14868 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14869 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14870 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14871 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14872 return (1);
14873 /*
14874 * SPEC (3.2.5) "R's {type definition} is validly derived given
14875 * {extension, list, union} from B's {type definition}"
14876 *
14877 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14878 * set, if the corresponding constraints handle "restriction" and
14879 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014880 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014881 */
14882 {
14883 int set = 0;
14884
14885 set |= SUBSET_EXTENSION;
14886 set |= SUBSET_LIST;
14887 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014888 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014889 elemB->subtypes, set) != 0)
14890 return (1);
14891 }
14892 return (0);
14893}
14894
14895/**
14896 * xmlSchemaCheckRCaseNSCompat:
14897 * @ctxt: the schema parser context
14898 * @r: the restricting element declaration particle
14899 * @b: the base wildcard particle
14900 *
14901 * (3.9.6) Constraints on Particle Schema Components
14902 * Schema Component Constraint:
14903 * Particle Derivation OK (Elt:Any -- NSCompat)
14904 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014905 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014906 * STATUS: complete
14907 *
14908 * Returns 0 if the constraints are satisfied, a positive
14909 * error code if not and -1 if an internal error occured.
14910 */
14911static int
14912xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14913 xmlSchemaParticlePtr r,
14914 xmlSchemaParticlePtr b)
14915{
14916 /* TODO:Error codes (rcase-NSCompat). */
14917 /*
14918 * SPEC "For an element declaration particle to be a ·valid restriction·
14919 * of a wildcard particle all of the following must be true:"
14920 *
14921 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14922 * with respect to the wildcard's {namespace constraint} as defined by
14923 * Wildcard allows Namespace Name (§3.10.4)."
14924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014925 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014926 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14927 return (1);
14928 /*
14929 * SPEC (2) "R's occurrence range is a valid restriction of B's
14930 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14931 */
14932 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14933 b->minOccurs, b->maxOccurs) != 0)
14934 return (1);
14935
14936 return (0);
14937}
14938
14939/**
14940 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14941 * @ctxt: the schema parser context
14942 * @r: the restricting element declaration particle
14943 * @b: the base model group particle
14944 *
14945 * (3.9.6) Constraints on Particle Schema Components
14946 * Schema Component Constraint:
14947 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14948 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014949 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014950 * STATUS: TODO
14951 *
14952 * Returns 0 if the constraints are satisfied, a positive
14953 * error code if not and -1 if an internal error occured.
14954 */
14955static int
14956xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
14957 xmlSchemaParticlePtr r,
14958 xmlSchemaParticlePtr b)
14959{
14960 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
14961 TODO
14962 return (0);
14963}
14964
14965/**
14966 * xmlSchemaCheckRCaseNSSubset:
14967 * @ctxt: the schema parser context
14968 * @r: the restricting wildcard particle
14969 * @b: the base wildcard particle
14970 *
14971 * (3.9.6) Constraints on Particle Schema Components
14972 * Schema Component Constraint:
14973 * Particle Derivation OK (Any:Any -- NSSubset)
14974 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014975 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014976 * STATUS: complete
14977 *
14978 * Returns 0 if the constraints are satisfied, a positive
14979 * error code if not and -1 if an internal error occured.
14980 */
14981static int
14982xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
14983 xmlSchemaParticlePtr r,
14984 xmlSchemaParticlePtr b,
14985 int isAnyTypeBase)
14986{
14987 /* TODO: Error codes (rcase-NSSubset). */
14988 /*
14989 * SPEC (1) "R's occurrence range is a valid restriction of B's
14990 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14991 */
14992 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14993 b->minOccurs, b->maxOccurs))
14994 return (1);
14995 /*
14996 * SPEC (2) "R's {namespace constraint} must be an intensional subset
14997 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
14998 */
14999 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15000 (xmlSchemaWildcardPtr) b->children))
15001 return (1);
15002 /*
15003 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15004 * definition·, R's {process contents} must be identical to or stronger
15005 * than B's {process contents}, where strict is stronger than lax is
15006 * stronger than skip."
15007 */
15008 if (! isAnyTypeBase) {
15009 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15010 ((xmlSchemaWildcardPtr) b->children)->processContents)
15011 return (1);
15012 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015013
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015014 return (0);
15015}
15016
15017/**
15018 * xmlSchemaCheckCOSParticleRestrict:
15019 * @ctxt: the schema parser context
15020 * @type: the complex type definition
15021 *
15022 * (3.9.6) Constraints on Particle Schema Components
15023 * Schema Component Constraint:
15024 * Particle Valid (Restriction) (cos-particle-restrict)
15025 *
15026 * STATUS: TODO
15027 *
15028 * Returns 0 if the constraints are satisfied, a positive
15029 * error code if not and -1 if an internal error occured.
15030 */
15031static int
15032xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15033 xmlSchemaParticlePtr r,
15034 xmlSchemaParticlePtr b)
15035{
15036 int ret = 0;
15037
15038 /*part = GET_PARTICLE(type);
15039 basePart = GET_PARTICLE(base);
15040 */
15041
15042 TODO
15043
15044 /*
15045 * SPEC (1) "They are the same particle."
15046 */
15047 if (r == b)
15048 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015049
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015050
15051 return (0);
15052}
15053
15054/**
15055 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15056 * @ctxt: the schema parser context
15057 * @r: the model group particle
15058 * @b: the base wildcard particle
15059 *
15060 * (3.9.6) Constraints on Particle Schema Components
15061 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015062 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015063 * NSRecurseCheckCardinality)
15064 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015065 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015066 * STATUS: TODO: subst-groups
15067 *
15068 * Returns 0 if the constraints are satisfied, a positive
15069 * error code if not and -1 if an internal error occured.
15070 */
15071static int
15072xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15073 xmlSchemaParticlePtr r,
15074 xmlSchemaParticlePtr b)
15075{
15076 xmlSchemaParticlePtr part;
15077 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15078 if ((r->children == NULL) || (r->children->children == NULL))
15079 return (-1);
15080 /*
15081 * SPEC "For a group particle to be a ·valid restriction· of a
15082 * wildcard particle..."
15083 *
15084 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015085 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015086 * Particle Valid (Restriction) (§3.9.6)."
15087 */
15088 part = (xmlSchemaParticlePtr) r->children->children;
15089 do {
15090 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15091 return (1);
15092 part = (xmlSchemaParticlePtr) part->next;
15093 } while (part != NULL);
15094 /*
15095 * SPEC (2) "The effective total range of the group [...] is a
15096 * valid restriction of B's occurrence range as defined by
15097 * Occurrence Range OK (§3.9.6)."
15098 */
15099 if (xmlSchemaCheckParticleRangeOK(
15100 xmlSchemaGetParticleTotalRangeMin(r),
15101 xmlSchemaGetParticleTotalRangeMax(r),
15102 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015103 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015104 return (0);
15105}
15106
15107/**
15108 * xmlSchemaCheckRCaseRecurse:
15109 * @ctxt: the schema parser context
15110 * @r: the <all> or <sequence> model group particle
15111 * @b: the base <all> or <sequence> model group particle
15112 *
15113 * (3.9.6) Constraints on Particle Schema Components
15114 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015115 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015116 Recurse)
15117 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015118 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015119 * STATUS: ?
15120 * TODO: subst-groups
15121 *
15122 * Returns 0 if the constraints are satisfied, a positive
15123 * error code if not and -1 if an internal error occured.
15124 */
15125static int
15126xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15127 xmlSchemaParticlePtr r,
15128 xmlSchemaParticlePtr b)
15129{
15130 /* xmlSchemaParticlePtr part; */
15131 /* TODO: Error codes (rcase-Recurse). */
15132 if ((r->children == NULL) || (b->children == NULL) ||
15133 (r->children->type != b->children->type))
15134 return (-1);
15135 /*
15136 * SPEC "For an all or sequence group particle to be a ·valid
15137 * restriction· of another group particle with the same {compositor}..."
15138 *
15139 * SPEC (1) "R's occurrence range is a valid restriction of B's
15140 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15141 */
15142 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15143 b->minOccurs, b->maxOccurs))
15144 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015145
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015146
15147 return (0);
15148}
15149
15150#endif
15151
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015152#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15153 xmlSchemaPCustomErrExt(pctxt, \
15154 XML_SCHEMAP_INVALID_FACET_VALUE, \
15155 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15156 "It is an error for both '%s' and '%s' to be specified on the "\
15157 "same type definition", \
15158 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15159 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15160
15161#define FACET_RESTR_ERR(fac1, msg) \
15162 xmlSchemaPCustomErr(pctxt, \
15163 XML_SCHEMAP_INVALID_FACET_VALUE, \
15164 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015165 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015166
15167#define FACET_RESTR_FIXED_ERR(fac) \
15168 xmlSchemaPCustomErr(pctxt, \
15169 XML_SCHEMAP_INVALID_FACET_VALUE, \
15170 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15171 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015172 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015173
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015174static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015175xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15176 xmlSchemaFacetPtr facet1,
15177 xmlSchemaFacetPtr facet2,
15178 int lessGreater,
15179 int orEqual,
15180 int ofBase)
15181{
15182 xmlChar *msg = NULL;
15183
15184 msg = xmlStrdup(BAD_CAST "'");
15185 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15186 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15187 if (lessGreater == 0)
15188 msg = xmlStrcat(msg, BAD_CAST " equal to");
15189 if (lessGreater == 1)
15190 msg = xmlStrcat(msg, BAD_CAST " greater than");
15191 else
15192 msg = xmlStrcat(msg, BAD_CAST " less than");
15193
15194 if (orEqual)
15195 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15196 msg = xmlStrcat(msg, BAD_CAST " '");
15197 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15198 if (ofBase)
15199 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15200 else
15201 msg = xmlStrcat(msg, BAD_CAST "'");
15202
15203 xmlSchemaPCustomErr(pctxt,
15204 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015205 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015206 (const char *) msg, NULL);
15207
15208 if (msg != NULL)
15209 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015210}
15211
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015212static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015213xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15214 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015215{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015216 xmlSchemaTypePtr base = type->baseType;
15217 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015218 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015219 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15220 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15221 fmininc = NULL, fmaxinc = NULL,
15222 fminexc = NULL, fmaxexc = NULL,
15223 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15224 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15225 bfmininc = NULL, bfmaxinc = NULL,
15226 bfminexc = NULL, bfmaxexc = NULL;
15227 int res, err = 0, fixedErr;
15228 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015229 * 3 The {facets} of R are the union of S and the {facets}
15230 * of B, eliminating duplicates. To eliminate duplicates,
15231 * when a facet of the same kind occurs in both S and the
15232 * {facets} of B, the one in the {facets} of B is not
15233 * included, with the exception of enumeration and pattern
15234 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015235 * are allowed.
15236 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015237
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015238 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15239 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015240
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015241 last = type->facetSet;
15242 if (last != NULL)
15243 while (last->next != NULL)
15244 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015245
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015246 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15247 facet = cur->facet;
15248 switch (facet->type) {
15249 case XML_SCHEMA_FACET_LENGTH:
15250 flength = facet; break;
15251 case XML_SCHEMA_FACET_MINLENGTH:
15252 fminlen = facet; break;
15253 case XML_SCHEMA_FACET_MININCLUSIVE:
15254 fmininc = facet; break;
15255 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15256 fminexc = facet; break;
15257 case XML_SCHEMA_FACET_MAXLENGTH:
15258 fmaxlen = facet; break;
15259 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15260 fmaxinc = facet; break;
15261 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15262 fmaxexc = facet; break;
15263 case XML_SCHEMA_FACET_TOTALDIGITS:
15264 ftotdig = facet; break;
15265 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15266 ffracdig = facet; break;
15267 default:
15268 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015269 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015270 }
15271 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15272 facet = cur->facet;
15273 switch (facet->type) {
15274 case XML_SCHEMA_FACET_LENGTH:
15275 bflength = facet; break;
15276 case XML_SCHEMA_FACET_MINLENGTH:
15277 bfminlen = facet; break;
15278 case XML_SCHEMA_FACET_MININCLUSIVE:
15279 bfmininc = facet; break;
15280 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15281 bfminexc = facet; break;
15282 case XML_SCHEMA_FACET_MAXLENGTH:
15283 bfmaxlen = facet; break;
15284 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15285 bfmaxinc = facet; break;
15286 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15287 bfmaxexc = facet; break;
15288 case XML_SCHEMA_FACET_TOTALDIGITS:
15289 bftotdig = facet; break;
15290 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15291 bffracdig = facet; break;
15292 default:
15293 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015294 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015295 }
15296 err = 0;
15297 /*
15298 * length and minLength or maxLength (2.2) + (3.2)
15299 */
15300 if (flength && (fminlen || fmaxlen)) {
15301 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15302 "either of 'minLength' or 'maxLength' to be specified on "
15303 "the same type definition")
15304 }
15305 /*
15306 * Mutual exclusions in the same derivation step.
15307 */
15308 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015309 /*
15310 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015311 */
15312 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15313 }
15314 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015315 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015316 * SCC "minInclusive and minExclusive"
15317 */
15318 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015319 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015320
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015321 if (flength && bflength) {
15322 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015323 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015324 * The values have to be equal.
15325 */
15326 res = xmlSchemaCompareValues(flength->val, bflength->val);
15327 if (res == -2)
15328 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015329 if (res != 0)
15330 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15331 if ((res != 0) && (bflength->fixed)) {
15332 FACET_RESTR_FIXED_ERR(flength)
15333 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015334
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015335 }
15336 if (fminlen && bfminlen) {
15337 /*
15338 * SCC "minLength valid restriction"
15339 * minLength >= BASE minLength
15340 */
15341 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15342 if (res == -2)
15343 goto internal_error;
15344 if (res == -1)
15345 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15346 if ((res != 0) && (bfminlen->fixed)) {
15347 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015348 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015349 }
15350 if (fmaxlen && bfmaxlen) {
15351 /*
15352 * SCC "maxLength valid restriction"
15353 * maxLength <= BASE minLength
15354 */
15355 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15356 if (res == -2)
15357 goto internal_error;
15358 if (res == 1)
15359 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15360 if ((res != 0) && (bfmaxlen->fixed)) {
15361 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015362 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015363 }
15364 /*
15365 * SCC "length and minLength or maxLength"
15366 */
15367 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015368 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015369 if (flength) {
15370 if (! fminlen)
15371 flength = bflength;
15372 if (fminlen) {
15373 /* (1.1) length >= minLength */
15374 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15375 if (res == -2)
15376 goto internal_error;
15377 if (res == -1)
15378 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15379 }
15380 if (! fmaxlen)
15381 fmaxlen = bfmaxlen;
15382 if (fmaxlen) {
15383 /* (2.1) length <= maxLength */
15384 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15385 if (res == -2)
15386 goto internal_error;
15387 if (res == 1)
15388 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15389 }
15390 }
15391 if (fmaxinc) {
15392 /*
15393 * "maxInclusive"
15394 */
15395 if (fmininc) {
15396 /* SCC "maxInclusive >= minInclusive" */
15397 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15398 if (res == -2)
15399 goto internal_error;
15400 if (res == -1) {
15401 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15402 }
15403 }
15404 /*
15405 * SCC "maxInclusive valid restriction"
15406 */
15407 if (bfmaxinc) {
15408 /* maxInclusive <= BASE maxInclusive */
15409 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15410 if (res == -2)
15411 goto internal_error;
15412 if (res == 1)
15413 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15414 if ((res != 0) && (bfmaxinc->fixed)) {
15415 FACET_RESTR_FIXED_ERR(fmaxinc)
15416 }
15417 }
15418 if (bfmaxexc) {
15419 /* maxInclusive < BASE maxExclusive */
15420 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15421 if (res == -2)
15422 goto internal_error;
15423 if (res != -1) {
15424 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15425 }
15426 }
15427 if (bfmininc) {
15428 /* maxInclusive >= BASE minInclusive */
15429 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15430 if (res == -2)
15431 goto internal_error;
15432 if (res == -1) {
15433 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15434 }
15435 }
15436 if (bfminexc) {
15437 /* maxInclusive > BASE minExclusive */
15438 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15439 if (res == -2)
15440 goto internal_error;
15441 if (res != 1) {
15442 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15443 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015444 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015445 }
15446 if (fmaxexc) {
15447 /*
15448 * "maxExclusive >= minExclusive"
15449 */
15450 if (fminexc) {
15451 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15452 if (res == -2)
15453 goto internal_error;
15454 if (res == -1) {
15455 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15456 }
15457 }
15458 /*
15459 * "maxExclusive valid restriction"
15460 */
15461 if (bfmaxexc) {
15462 /* maxExclusive <= BASE maxExclusive */
15463 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15464 if (res == -2)
15465 goto internal_error;
15466 if (res == 1) {
15467 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15468 }
15469 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015470 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015471 }
15472 }
15473 if (bfmaxinc) {
15474 /* maxExclusive <= BASE maxInclusive */
15475 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15476 if (res == -2)
15477 goto internal_error;
15478 if (res == 1) {
15479 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15480 }
15481 }
15482 if (bfmininc) {
15483 /* maxExclusive > BASE minInclusive */
15484 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15485 if (res == -2)
15486 goto internal_error;
15487 if (res != 1) {
15488 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15489 }
15490 }
15491 if (bfminexc) {
15492 /* maxExclusive > BASE minExclusive */
15493 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15494 if (res == -2)
15495 goto internal_error;
15496 if (res != 1) {
15497 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15498 }
15499 }
15500 }
15501 if (fminexc) {
15502 /*
15503 * "minExclusive < maxInclusive"
15504 */
15505 if (fmaxinc) {
15506 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15507 if (res == -2)
15508 goto internal_error;
15509 if (res != -1) {
15510 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15511 }
15512 }
15513 /*
15514 * "minExclusive valid restriction"
15515 */
15516 if (bfminexc) {
15517 /* minExclusive >= BASE minExclusive */
15518 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15519 if (res == -2)
15520 goto internal_error;
15521 if (res == -1) {
15522 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15523 }
15524 if ((res != 0) && (bfminexc->fixed)) {
15525 FACET_RESTR_FIXED_ERR(fminexc)
15526 }
15527 }
15528 if (bfmaxinc) {
15529 /* minExclusive <= BASE maxInclusive */
15530 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15531 if (res == -2)
15532 goto internal_error;
15533 if (res == 1) {
15534 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15535 }
15536 }
15537 if (bfmininc) {
15538 /* minExclusive >= BASE minInclusive */
15539 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15540 if (res == -2)
15541 goto internal_error;
15542 if (res == -1) {
15543 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15544 }
15545 }
15546 if (bfmaxexc) {
15547 /* minExclusive < BASE maxExclusive */
15548 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15549 if (res == -2)
15550 goto internal_error;
15551 if (res != -1) {
15552 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15553 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015554 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015555 }
15556 if (fmininc) {
15557 /*
15558 * "minInclusive < maxExclusive"
15559 */
15560 if (fmaxexc) {
15561 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15562 if (res == -2)
15563 goto internal_error;
15564 if (res != -1) {
15565 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15566 }
15567 }
15568 /*
15569 * "minExclusive valid restriction"
15570 */
15571 if (bfmininc) {
15572 /* minInclusive >= BASE minInclusive */
15573 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15574 if (res == -2)
15575 goto internal_error;
15576 if (res == -1) {
15577 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15578 }
15579 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015580 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015581 }
15582 }
15583 if (bfmaxinc) {
15584 /* minInclusive <= BASE maxInclusive */
15585 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15586 if (res == -2)
15587 goto internal_error;
15588 if (res == -1) {
15589 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15590 }
15591 }
15592 if (bfminexc) {
15593 /* minInclusive > BASE minExclusive */
15594 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15595 if (res == -2)
15596 goto internal_error;
15597 if (res != 1)
15598 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15599 }
15600 if (bfmaxexc) {
15601 /* minInclusive < BASE maxExclusive */
15602 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15603 if (res == -2)
15604 goto internal_error;
15605 if (res != -1)
15606 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15607 }
15608 }
15609 if (ftotdig && bftotdig) {
15610 /*
15611 * SCC " totalDigits valid restriction"
15612 * totalDigits <= BASE totalDigits
15613 */
15614 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15615 if (res == -2)
15616 goto internal_error;
15617 if (res == 1)
15618 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15619 -1, 1, 1);
15620 if ((res != 0) && (bftotdig->fixed)) {
15621 FACET_RESTR_FIXED_ERR(ftotdig)
15622 }
15623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015624 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015625 /*
15626 * SCC "fractionDigits valid restriction"
15627 * fractionDigits <= BASE fractionDigits
15628 */
15629 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15630 if (res == -2)
15631 goto internal_error;
15632 if (res == 1)
15633 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15634 -1, 1, 1);
15635 if ((res != 0) && (bffracdig->fixed)) {
15636 FACET_RESTR_FIXED_ERR(ffracdig)
15637 }
15638 }
15639 /*
15640 * SCC "fractionDigits less than or equal to totalDigits"
15641 */
15642 if (! ftotdig)
15643 ftotdig = bftotdig;
15644 if (! ffracdig)
15645 ffracdig = bffracdig;
15646 if (ftotdig && ffracdig) {
15647 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15648 if (res == -2)
15649 goto internal_error;
15650 if (res == 1)
15651 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15652 -1, 1, 0);
15653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015654 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015655 * *Enumerations* won' be added here, since only the first set
15656 * of enumerations in the ancestor-or-self axis is used
15657 * for validation, plus we need to use the base type of those
15658 * enumerations for whitespace.
15659 *
15660 * *Patterns*: won't be add here, since they are ORed at
15661 * type level and ANDed at ancestor level. This will
15662 * happed during validation by walking the base axis
15663 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015664 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015665 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15666 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015667 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015668 * Special handling of enumerations and patterns.
15669 * TODO: hmm, they should not appear in the set, so remove this.
15670 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015671 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015672 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015673 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015674 /*
15675 * Search for a duplicate facet in the current type.
15676 */
15677 link = type->facetSet;
15678 err = 0;
15679 fixedErr = 0;
15680 while (link != NULL) {
15681 facet = link->facet;
15682 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015683 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015684 case XML_SCHEMA_FACET_WHITESPACE:
15685 /*
15686 * The whitespace must be stronger.
15687 */
15688 if (facet->whitespace < bfacet->whitespace) {
15689 FACET_RESTR_ERR(flength,
15690 "The 'whitespace' value has to be equal to "
15691 "or stronger than the 'whitespace' value of "
15692 "the base type")
15693 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015694 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015695 (facet->whitespace != bfacet->whitespace)) {
15696 FACET_RESTR_FIXED_ERR(facet)
15697 }
15698 break;
15699 default:
15700 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015701 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015702 /* Duplicate found. */
15703 break;
15704 }
15705 link = link->next;
15706 }
15707 /*
15708 * If no duplicate was found: add the base types's facet
15709 * to the set.
15710 */
15711 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015712 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015713 xmlMalloc(sizeof(xmlSchemaFacetLink));
15714 if (link == NULL) {
15715 xmlSchemaPErrMemory(pctxt,
15716 "deriving facets, creating a facet link", NULL);
15717 return (-1);
15718 }
15719 link->facet = cur->facet;
15720 link->next = NULL;
15721 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015722 type->facetSet = link;
15723 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015724 last->next = link;
15725 last = link;
15726 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015727
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015728 }
15729
15730 return (0);
15731internal_error:
15732 xmlSchemaPCustomErr(pctxt,
15733 XML_SCHEMAP_INVALID_FACET_VALUE,
15734 NULL, type, NULL,
15735 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15736 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015737}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015738
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015739static int
15740xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15741 xmlSchemaTypePtr type)
15742{
15743 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015745 * The actual value is then formed by replacing any union type
15746 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015747 * {member type definitions}, in order.
15748 */
15749 link = type->memberTypes;
15750 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015751
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015752 if (IS_NOT_TYPEFIXED(link->type))
15753 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15754
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015755 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015756 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015757 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015758 link->type = subLink->type;
15759 if (subLink->next != NULL) {
15760 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015761 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015762 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015763 while (subLink != NULL) {
15764 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015765 xmlMalloc(sizeof(xmlSchemaTypeLink));
15766 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015767 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015768 NULL);
15769 return (-1);
15770 }
15771 newLink->type = subLink->type;
15772 prevLink->next = newLink;
15773 prevLink = newLink;
15774 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015775
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015776 subLink = subLink->next;
15777 }
15778 }
15779 }
15780 }
15781 link = link->next;
15782 }
15783 return (0);
15784}
15785
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015786static void
15787xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15788{
15789 int has = 0, needVal = 0, normVal = 0;
15790
15791 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15792 if (has) {
15793 needVal = (type->baseType->flags &
15794 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15795 normVal = (type->baseType->flags &
15796 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15797 }
15798 if (type->facets != NULL) {
15799 xmlSchemaFacetPtr fac;
15800
15801 for (fac = type->facets; fac != NULL; fac = fac->next) {
15802 switch (fac->type) {
15803 case XML_SCHEMA_FACET_WHITESPACE:
15804 break;
15805 case XML_SCHEMA_FACET_PATTERN:
15806 normVal = 1;
15807 has = 1;
15808 break;
15809 case XML_SCHEMA_FACET_ENUMERATION:
15810 needVal = 1;
15811 normVal = 1;
15812 has = 1;
15813 break;
15814 default:
15815 has = 1;
15816 break;
15817 }
15818 }
15819 }
15820 if (normVal)
15821 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15822 if (needVal)
15823 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15824 if (has)
15825 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15826
15827 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15828 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15829 /*
15830 * OPTIMIZE VAL TODO: Some facets need a computed value.
15831 */
15832 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15833 (prim->builtInType != XML_SCHEMAS_STRING)) {
15834 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15835 }
15836 }
15837}
15838
15839static int
15840xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15841{
15842
15843
15844 /*
15845 * Evaluate the whitespace-facet value.
15846 */
15847 if (VARIETY_LIST(type)) {
15848 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15849 return (0);
15850 } else if (VARIETY_UNION(type))
15851 return (0);
15852
15853 if (type->facetSet != NULL) {
15854 xmlSchemaFacetLinkPtr lin;
15855
15856 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15857 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15858 switch (lin->facet->whitespace) {
15859 case XML_SCHEMAS_FACET_PRESERVE:
15860 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15861 break;
15862 case XML_SCHEMAS_FACET_REPLACE:
15863 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15864 break;
15865 case XML_SCHEMAS_FACET_COLLAPSE:
15866 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15867 break;
15868 default:
15869 return (-1);
15870 }
15871 return (0);
15872 }
15873 }
15874 }
15875 /*
15876 * For all ·atomic· datatypes other than string (and types ·derived·
15877 * by ·restriction· from it) the value of whiteSpace is fixed to
15878 * collapse
15879 */
15880 {
15881 xmlSchemaTypePtr anc;
15882
15883 for (anc = type->baseType; anc != NULL &&
15884 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15885 anc = anc->baseType) {
15886
15887 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15888 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15889 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15890
15891 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15892 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15893 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15894
15895 } else
15896 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15897 break;
15898 }
15899 }
15900 return (0);
15901 }
15902 return (0);
15903}
15904
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015905/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015906 * xmlSchemaTypeFixup:
15907 * @typeDecl: the schema type definition
15908 * @ctxt: the schema parser context
15909 *
15910 * Fixes the content model of the type.
15911 */
15912static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015913xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015914 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015915{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015916 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015917 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015918 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15919 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015920 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015921 if (! IS_NOT_TYPEFIXED(type))
15922 return;
15923 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015924 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015925 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015926
15927 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015928 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015929 XML_SCHEMAP_INTERNAL,
15930 NULL, type, NULL,
15931 "Internal error: xmlSchemaTypeFixup, "
15932 "baseType is missing on '%s'", type->name);
15933 return;
15934 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015935
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015936 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015937 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015938
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015939 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015940 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015941 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015942 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015943 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015944 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15945 /*
15946 * Skip fixup if the base type is invalid.
15947 * TODO: Generate a warning!
15948 */
15949 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015950 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015951 /*
15952 * This basically checks if the base type can be derived.
15953 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015954 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015955 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15956 return;
15957 }
15958 /*
15959 * Fixup the content type.
15960 */
15961 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15962 /*
15963 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015964 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 if ((IS_COMPLEX_TYPE(baseType)) &&
15966 (baseType->contentTypeDef != NULL) &&
15967 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015968 xmlSchemaTypePtr contentBase, content;
15969 char buf[30];
15970 const xmlChar *tmpname;
15971 /*
15972 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015973 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015974 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015975 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015977 * SPEC (1.1) "the simple type definition corresponding to the
15978 * <simpleType> among the [children] of <restriction> if there
15979 * is one;"
15980 * Note that this "<simpleType> among the [children]" was put
15981 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015983 contentBase = type->contentTypeDef;
15984 type->contentTypeDef = NULL;
15985 } else {
15986 /*
15987 * (1.2) "...otherwise (<restriction> has no <simpleType>
15988 * among its [children]), the simple type definition which
15989 * is the {content type} of the ... base type."
15990 */
15991 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015992 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015993 /*
15994 * SPEC
15995 * "... a simple type definition which restricts the simple
15996 * type definition identified in clause 1.1 or clause 1.2
15997 * with a set of facet components"
15998 *
15999 * Create the anonymous simple type, which will be the content
16000 * type of the complex type.
16001 */
16002 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16003 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16004 content = xmlSchemaAddType(pctxt,
16005 pctxt->schema, tmpname, tmpname, type->node);
16006 if (content == NULL)
16007 return;
16008 /*
16009 * We will use the same node as for the <complexType>
16010 * to have it somehow anchored in the schema doc.
16011 */
16012 content->node = type->node;
16013 content->type = XML_SCHEMA_TYPE_SIMPLE;
16014 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16015 content->baseType = contentBase;
16016 /*
16017 * Move the facets, previously anchored on the complexType.
16018 */
16019 content->facets = type->facets;
16020 type->facets = NULL;
16021 content->facetSet = type->facetSet;
16022 type->facetSet = NULL;
16023
16024 type->contentTypeDef = content;
16025 if (IS_NOT_TYPEFIXED(contentBase))
16026 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16027 xmlSchemaTypeFixup(content, pctxt, NULL);
16028
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016029 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16030 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16031 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16032 /*
16033 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16034 * an emptiable particle, then a simple type definition which
16035 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016037 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016038 (type->contentTypeDef->baseType == NULL)) {
16039 /*
16040 * TODO: Check if this ever happens.
16041 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016042 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016043 XML_SCHEMAP_INTERNAL,
16044 NULL, type, NULL,
16045 "Internal error: xmlSchemaTypeFixup, "
16046 "complex type '%s': the <simpleContent><restriction> "
16047 "is missing a <simpleType> child, but was not catched "
16048 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016049 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016050 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16051 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16052 /*
16053 * SPEC (3) If <extension> + base is <complexType> with
16054 * <simpleType> content, "...then the {content type} of that
16055 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016056 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016057 if (baseType->contentTypeDef == NULL) {
16058 /*
16059 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16060 * should have catched this already.
16061 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016062 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016063 XML_SCHEMAP_INTERNAL,
16064 NULL, type, NULL,
16065 "Internal error: xmlSchemaTypeFixup, "
16066 "complex type '%s': the <extension>ed base type is "
16067 "a complex type with no simple content type",
16068 type->name);
16069 }
16070 type->contentTypeDef = baseType->contentTypeDef;
16071 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16072 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16073 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016074 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016075 * "... then that simple type definition"
16076 */
16077 type->contentTypeDef = baseType;
16078 } else {
16079 /*
16080 * TODO: Check if this ever happens.
16081 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016082 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016083 XML_SCHEMAP_INTERNAL,
16084 NULL, type, NULL,
16085 "Internal error: xmlSchemaTypeFixup, "
16086 "complex type '%s' with <simpleContent>: unhandled "
16087 "derivation case", type->name);
16088 }
16089 } else {
16090 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016091 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016092 (xmlSchemaParticlePtr) type->subtypes;
16093 /*
16094 * Corresponds to <complexType><complexContent>...
16095 *
16096 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016097 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016098 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016099 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016100 * Compute the "effective content":
16101 * (2.1.1) + (2.1.2) + (2.1.3)
16102 */
16103 if ((particle == NULL) ||
16104 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16105 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16106 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16107 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16108 (particle->minOccurs == 0))) &&
16109 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016110 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016111 /*
16112 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16113 * a particle whose properties are as follows:..."
16114 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016115 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016116 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16117 * NOTE that we sill assign it the <complexType> node to
16118 * somehow anchor it in the doc.
16119 */
16120 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016121 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016122 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016123 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016124 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016125 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016126 type->node, 1, 1);
16127 if (particle == NULL)
16128 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016129 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016130 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016131 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016132 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016133 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016134 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16135 if (particle->children == NULL)
16136 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016137
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016138 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016139 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016140 dummySequence = 1;
16141 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16142 } else {
16143 /*
16144 * SPEC (2.1.5) "otherwise empty"
16145 */
16146 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016147 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016148 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016149 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 * SPEC (2.2) "otherwise the particle corresponding to the
16151 * <all>, <choice>, <group> or <sequence> among the
16152 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016153 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016154 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16155 }
16156 /*
16157 * Compute the "content type".
16158 */
16159 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016160 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 * SPEC (3.1) "If <restriction>..."
16162 * (3.1.1) + (3.1.2) */
16163 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16164 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16165 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16166 }
16167 } else {
16168 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016169 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016170 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016171 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16172 /*
16173 * SPEC (3.2.1)
16174 */
16175 type->contentType = baseType->contentType;
16176 type->subtypes = baseType->subtypes;
16177 /*
16178 * NOTE that the effective mixed is ignored here.
16179 */
16180 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16181 /*
16182 * SPEC (3.2.2)
16183 */
16184 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16185 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16186 } else {
16187 /*
16188 * SPEC (3.2.3)
16189 */
16190 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16191 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16192 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016193 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016194 * {particles} are..."
16195 */
16196 if (! dummySequence) {
16197 xmlSchemaTreeItemPtr effectiveContent =
16198 (xmlSchemaTreeItemPtr) type->subtypes;
16199 /*
16200 * Create the particle.
16201 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016202 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016203 type->node, 1, 1);
16204 if (particle == NULL)
16205 return;
16206 /*
16207 * Create the "sequence" model group.
16208 */
16209 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016210 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016211 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16212 if (particle->children == NULL)
16213 return;
16214 type->subtypes = (xmlSchemaTypePtr) particle;
16215 /*
16216 * SPEC "the particle of the {content type} of
16217 * the ... base ..."
16218 * Create a duplicate of the base type's particle
16219 * and assign its "term" to it.
16220 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016221 particle->children->children =
16222 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16223 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016224 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 if (particle->children->children == NULL)
16227 return;
16228 particle = (xmlSchemaParticlePtr)
16229 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016230 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016231 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16232 /*
16233 * SPEC "followed by the ·effective content·."
16234 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016235 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016236 } else {
16237 /*
16238 * This is the case when there is already an empty
16239 * <sequence> with minOccurs==maxOccurs==1.
16240 * Just add the base types's content type.
16241 * NOTE that, although we miss to add an intermediate
16242 * <sequence>, this should produce no difference to
16243 * neither the regex compilation of the content model,
16244 * nor to the complex type contraints.
16245 */
16246 particle->children->children =
16247 (xmlSchemaTreeItemPtr) baseType->subtypes;
16248 }
16249 }
16250 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016251 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 /*
16253 * Apply the complex type component constraints; this will not
16254 * check attributes, since this is done in
16255 * xmlSchemaBuildAttributeValidation().
16256 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016257 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16258 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016259 /*
16260 * Inherit & check constraints for attributes.
16261 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016262 xmlSchemaBuildAttributeValidation(pctxt, type);
16263 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 /*
16265 * Simple Type Definition Schema Component
16266 */
16267 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016268 if (VARIETY_LIST(type)) {
16269 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016270 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016271 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016272 if (type->subtypes == NULL) {
16273 /*
16274 * This one is really needed, so get out.
16275 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016276 PERROR_INT("xmlSchemaTypeFixup",
16277 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016278 return;
16279 }
16280 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016281 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16282 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016283 /*
16284 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016285 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016286 if (type->memberTypes == NULL) {
16287 /*
16288 * This one is really needed, so get out.
16289 */
16290 return;
16291 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016292 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016293 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016294 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016295 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016296 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016297 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016298 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016299 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016300 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16301 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016302 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016303 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016304 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016305 */
16306 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016307 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016308 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16310 /*
16311 * Inherit the itemType.
16312 */
16313 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016314 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016315 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16316 /*
16317 * NOTE that we won't assign the memberTypes of the base,
16318 * since this will make trouble when freeing them; we will
16319 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016320 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016321 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016322 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016323 /*
16324 * Check constraints.
16325 *
16326 * TODO: Split this somehow, we need to know first if we can derive
16327 * from the base type at all!
16328 */
16329 if (type->baseType != NULL) {
16330 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016331 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016332 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016333 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016334 * applied beforehand.
16335 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016336 xmlSchemaCheckSRCSimpleType(pctxt, type);
16337 xmlSchemaCheckFacetValues(type, pctxt);
16338 if ((type->facetSet != NULL) ||
16339 (type->baseType->facetSet != NULL))
16340 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16341 /*
16342 * Whitespace value.
16343 */
16344 xmlSchemaTypeFixupWhitespace(type);
16345 xmlSchemaTypeFixupOptimFacets(type);
16346 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016347 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348
Daniel Veillard8651f532002-04-17 09:06:27 +000016349#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016350 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016351 xmlGenericError(xmlGenericErrorContext,
16352 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016353 type->node->doc->URL,
16354 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016355 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016356 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016357 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16359 switch (type->contentType) {
16360 case XML_SCHEMA_CONTENT_SIMPLE:
16361 xmlGenericError(xmlGenericErrorContext, "simple\n");
16362 break;
16363 case XML_SCHEMA_CONTENT_ELEMENTS:
16364 xmlGenericError(xmlGenericErrorContext, "elements\n");
16365 break;
16366 case XML_SCHEMA_CONTENT_UNKNOWN:
16367 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16368 break;
16369 case XML_SCHEMA_CONTENT_EMPTY:
16370 xmlGenericError(xmlGenericErrorContext, "empty\n");
16371 break;
16372 case XML_SCHEMA_CONTENT_MIXED:
16373 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016374 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016375 xmlGenericError(xmlGenericErrorContext,
16376 "mixed as emptiable particle\n");
16377 else
16378 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16379 break;
16380 /* Removed, since not used. */
16381 /*
16382 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16383 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16384 break;
16385 */
16386 case XML_SCHEMA_CONTENT_BASIC:
16387 xmlGenericError(xmlGenericErrorContext, "basic\n");
16388 break;
16389 default:
16390 xmlGenericError(xmlGenericErrorContext,
16391 "not registered !!!\n");
16392 break;
16393 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016394 }
16395#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016396}
16397
16398/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016399 * xmlSchemaCheckFacet:
16400 * @facet: the facet
16401 * @typeDecl: the schema type definition
16402 * @ctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016403 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016404 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016405 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016406 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016407 * Returns 0 if valid, a positive error code if not valid and
16408 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016409 */
16410int
16411xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016412 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016413 xmlSchemaParserCtxtPtr pctxt,
16414 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016415{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016416 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016417
Daniel Veillardce682bc2004-11-05 17:22:25 +000016418 if ((facet == NULL) || (typeDecl == NULL))
16419 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016420 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016421 * TODO: will the parser context be given if used from
16422 * the relaxNG module?
16423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016424 if (pctxt == NULL)
16425 ctxtGiven = 0;
16426 else
16427 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016428
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016429 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016430 case XML_SCHEMA_FACET_MININCLUSIVE:
16431 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16432 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016433 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16434 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016435 /*
16436 * Okay we need to validate the value
16437 * at that point.
16438 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016439 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016440
16441 /* 4.3.5.5 Constraints on enumeration Schema Components
16442 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016443 * It is an ·error· if any member of {value} is not in the
16444 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016445 *
16446 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016447 * The value ·must· be in the
16448 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016449 */
16450 /*
16451 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016452 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016453 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016454 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016455 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016456 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016457 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016458 */
16459 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16460 base = typeDecl->baseType;
16461 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016462 PERROR_INT("xmlSchemaCheckFacet",
16463 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016464 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016465 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016466 } else
16467 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016468
16469 if (! ctxtGiven) {
16470 /*
16471 * A context is needed if called from RelaxNG.
16472 */
16473 pctxt = xmlSchemaNewParserCtxt("*");
16474 if (pctxt == NULL)
16475 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016476 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016477 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016478 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016479 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016480 * facet->node is just the node holding the facet
16481 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016482 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016483 */
16484 ret = xmlSchemaVCheckCVCSimpleType(
16485 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16486 facet->value, &(facet->val), 1, 1, 0);
16487 if (ret != 0) {
16488 if (ret < 0) {
16489 /* No error message for RelaxNG. */
16490 if (ctxtGiven) {
16491 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16492 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16493 "Internal error: xmlSchemaCheckFacet, "
16494 "failed to validate the value '%s' of the "
16495 "facet '%s' against the base type",
16496 facet->value, xmlSchemaFacetTypeToString(facet->type));
16497 }
16498 goto internal_error;
16499 }
16500 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16501 /* No error message for RelaxNG. */
16502 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016503 xmlChar *str = NULL;
16504
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016505 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16506 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016507 "The value '%s' of the facet does not validate "
16508 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016509 facet->value,
16510 xmlSchemaFormatQName(&str,
16511 base->targetNamespace, base->name));
16512 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016513 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016514 goto exit;
16515 } else if (facet->val == NULL) {
16516 if (ctxtGiven) {
16517 PERROR_INT("xmlSchemaCheckFacet",
16518 "value was not computed");
16519 }
16520 TODO
16521 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016522 break;
16523 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016524 case XML_SCHEMA_FACET_PATTERN:
16525 facet->regexp = xmlRegexpCompile(facet->value);
16526 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016527 ret = XML_SCHEMAP_REGEXP_INVALID;
16528 /* No error message for RelaxNG. */
16529 if (ctxtGiven) {
16530 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16531 ret, facet->node, typeDecl,
16532 "The value '%s' of the facet 'pattern' is not a "
16533 "valid regular expression",
16534 facet->value, NULL);
16535 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016536 }
16537 break;
16538 case XML_SCHEMA_FACET_TOTALDIGITS:
16539 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16540 case XML_SCHEMA_FACET_LENGTH:
16541 case XML_SCHEMA_FACET_MAXLENGTH:
16542 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016543 ret = xmlSchemaValidatePredefinedType(
16544 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16545 facet->value, &(facet->val));
16546 if (ret != 0) {
16547 if (ret < 0) {
16548 /* No error message for RelaxNG. */
16549 if (ctxtGiven) {
16550 PERROR_INT("xmlSchemaCheckFacet",
16551 "validating facet value");
16552 }
16553 goto internal_error;
16554 }
16555 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16556 /* No error message for RelaxNG. */
16557 if (ctxtGiven) {
16558 /* error code */
16559 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16560 ret, facet->node, typeDecl,
16561 "The value '%s' of the facet '%s' is not a valid "
16562 "'nonNegativeInteger'",
16563 facet->value,
16564 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016565 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016566 }
16567 break;
16568 }
16569 case XML_SCHEMA_FACET_WHITESPACE:{
16570 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16571 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16572 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16573 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16574 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16575 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16576 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016577 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16578 /* No error message for RelaxNG. */
16579 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016580 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016581 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16582 ret, facet->node, typeDecl,
16583 "The value '%s' of the facet 'whitespace' is not "
16584 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016585 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016586 }
16587 }
16588 default:
16589 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591exit:
16592 if ((! ctxtGiven) && (pctxt != NULL))
16593 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016594 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016595internal_error:
16596 if ((! ctxtGiven) && (pctxt != NULL))
16597 xmlSchemaFreeParserCtxt(pctxt);
16598 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016599}
16600
16601/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016602 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016603 * @typeDecl: the schema type definition
16604 * @ctxt: the schema parser context
16605 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016606 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016607 */
16608static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016609xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16610 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016611{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016612 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016613 /*
16614 * NOTE: It is intended to use the facets list, instead
16615 * of facetSet.
16616 */
16617 if (typeDecl->facets != NULL) {
16618 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016619
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016620 /*
16621 * Temporarily assign the "schema" to the validation context
16622 * of the parser context. This is needed for NOTATION validation.
16623 */
16624 if (ctxt->vctxt == NULL) {
16625 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16626 return;
16627 }
16628 ctxt->vctxt->schema = ctxt->schema;
16629
Daniel Veillard01fa6152004-06-29 17:04:39 +000016630 while (facet != NULL) {
16631 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16632 facet = facet->next;
16633 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016634
16635 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016636 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016637}
16638
16639/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016640 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016641 * @ctxtMGroup: the searched model group
16642 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016643 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016644 *
16645 * This one is intended to be used by
16646 * xmlSchemaCheckGroupDefCircular only.
16647 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016648 * Returns the particle with the circular model group definition reference,
16649 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016650 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016651static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016652xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016653 xmlSchemaTreeItemPtr particle)
16654{
16655 xmlSchemaTreeItemPtr circ = NULL;
16656 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016657 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016658
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016659 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016660 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016661 if (term == NULL)
16662 continue;
16663 switch (term->type) {
16664 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016665 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016666 if (gdef == groupDef)
16667 return (particle);
16668 /*
16669 * Mark this model group definition to avoid infinite
16670 * recursion on circular references not yet examined.
16671 */
16672 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16673 continue;
16674 if (gdef->children != NULL) {
16675 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16676 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16677 gdef->children->children);
16678 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16679 if (circ != NULL)
16680 return (circ);
16681 }
16682 break;
16683 case XML_SCHEMA_TYPE_SEQUENCE:
16684 case XML_SCHEMA_TYPE_CHOICE:
16685 case XML_SCHEMA_TYPE_ALL:
16686 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16687 if (circ != NULL)
16688 return (circ);
16689 break;
16690 default:
16691 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016692 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016693 }
16694 return (NULL);
16695}
16696
16697/**
16698 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016699 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016700 * @ctxt: the parser context
16701 * @name: the name
16702 *
16703 * Checks for circular references to model group definitions.
16704 */
16705static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016706xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016707 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016708 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016709{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016710 /*
16711 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016712 * 2 Circular groups are disallowed. That is, within the {particles}
16713 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016714 * is the group itself.
16715 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016716 if ((item == NULL) ||
16717 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16718 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016719 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016720 {
16721 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016722
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016723 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016724 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016725 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016726 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016727 * TODO: The error report is not adequate: this constraint
16728 * is defined for model groups but not definitions, but since
16729 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016730 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016731 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016732 */
16733 xmlSchemaPCustomErr(ctxt,
16734 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016735 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016736 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016737 "defined", xmlSchemaFormatQName(&str,
16738 item->targetNamespace, item->name));
16739 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016740 /*
16741 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016742 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016743 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016744 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016745 }
16746 }
16747}
16748
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016749/**
16750 * xmlSchemaGroupDefTermFixup:
16751 * @item: the particle with a model group definition as term
16752 * @ctxt: the parser context
16753 * @name: the name
16754 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016755 * Checks cos-all-limited.
16756 *
16757 * Assigns the model group of model group definitions to the "term"
16758 * of the referencing particle.
16759 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16760 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016761 */
16762static void
16763xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016764 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016765 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016766{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016767 if ((item == NULL) ||
16768 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16769 (item->children == NULL) ||
16770 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16771 (item->children->children == NULL))
16772 return;
16773 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016774 /*
16775 * TODO: Not nice, but we will anchor cos-all-limited here.
16776 */
16777 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16778 (item->maxOccurs != 1)) {
16779 /*
16780 * SPEC (1.2) "the {term} property of a particle with
16781 * {max occurs}=1which is part of a pair which constitutes the
16782 * {content type} of a complex type definition."
16783 */
16784 xmlSchemaPCustomErr(ctxt,
16785 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16786 NULL, (xmlSchemaTypePtr) item, item->node,
16787 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16788 "group is its term", NULL);
16789 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016790}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016791
16792/**
16793 * xmlSchemaGetCircAttrGrRef:
16794 * @ctxtGr: the searched attribute group
16795 * @attr: the current attribute list to be processed
16796 *
16797 * This one is intended to be used by
16798 * xmlSchemaCheckSRCAttributeGroupCircular only.
16799 *
16800 * Returns the circular attribute grou reference, otherwise NULL.
16801 */
16802static xmlSchemaAttributeGroupPtr
16803xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16804 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016805{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016806 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16807 int marked;
16808 /*
16809 * We will search for an attribute group reference which
16810 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016811 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016812 while (attr != NULL) {
16813 marked = 0;
16814 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16815 gr = (xmlSchemaAttributeGroupPtr) attr;
16816 if (gr->refItem != NULL) {
16817 if (gr->refItem == ctxtGr)
16818 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016819 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016820 XML_SCHEMAS_ATTRGROUP_MARKED) {
16821 attr = attr->next;
16822 continue;
16823 } else {
16824 /*
16825 * Mark as visited to avoid infinite recursion on
16826 * circular references not yet examined.
16827 */
16828 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16829 marked = 1;
16830 }
16831 }
16832 if (gr->attributes != NULL)
16833 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16834 /*
16835 * Unmark the visited group's attributes.
16836 */
16837 if (marked)
16838 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16839 if (circ != NULL)
16840 return (circ);
16841 }
16842 attr = attr->next;
16843 }
16844 return (NULL);
16845}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016846
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016847/**
16848 * xmlSchemaCheckSRCAttributeGroupCircular:
16849 * attrGr: the attribute group definition
16850 * @ctxt: the parser context
16851 * @name: the name
16852 *
16853 * Checks for circular references of attribute groups.
16854 */
16855static void
16856xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016857 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016858 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016859{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016860 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016861 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016862 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016863 * 3 Circular group reference is disallowed outside <redefine>.
16864 * That is, unless this element information item's parent is
16865 * <redefine>, then among the [children], if any, there must
16866 * not be an <attributeGroup> with ref [attribute] which resolves
16867 * to the component corresponding to this <attributeGroup>. Indirect
16868 * circularity is also ruled out. That is, when QName resolution
16869 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16870 * any <attributeGroup>s with a ref [attribute] among the [children],
16871 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016872 * which resolves to the component corresponding to this <attributeGroup>.
16873 */
16874 /*
16875 * Only global components can be referenced.
16876 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016877 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016878 (attrGr->attributes == NULL))
16879 return;
16880 else {
16881 xmlSchemaAttributeGroupPtr circ;
16882
16883 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16884 if (circ != NULL) {
16885 /*
16886 * TODO: Report the referenced attr group as QName.
16887 */
16888 xmlSchemaPCustomErr(ctxt,
16889 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16890 NULL, NULL, circ->node,
16891 "Circular reference to the attribute group '%s' "
16892 "defined", attrGr->name);
16893 /*
16894 * NOTE: We will cut the reference to avoid further
16895 * confusion of the processor.
16896 * BADSPEC: The spec should define how to process in this case.
16897 */
16898 circ->attributes = NULL;
16899 circ->refItem = NULL;
16900 }
16901 }
16902}
16903
16904/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016905 * xmlSchemaAttrGrpFixup:
16906 * @attrgrpDecl: the schema attribute definition
16907 * @ctxt: the schema parser context
16908 * @name: the attribute name
16909 *
16910 * Fixes finish doing the computations on the attributes definitions
16911 */
16912static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016913xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016914 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016915{
16916 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016917 name = attrgrp->name;
16918 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016919 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016920 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016921 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016923 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016924 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016925 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016926 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016927 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016928 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16929 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016930 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016931 return;
16932 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016933 attrgrp->refItem = ref;
16934 /*
16935 * Check for self reference!
16936 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016937 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016938 attrgrp->attributes = ref->attributes;
16939 attrgrp->attributeWildcard = ref->attributeWildcard;
16940 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016941}
16942
16943/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016944 * xmlSchemaAttrCheckValConstr:
16945 * @item: an schema attribute declaration/use
16946 * @ctxt: a schema parser context
16947 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016948 *
16949 *
16950 * Schema Component Constraint: Attribute Declaration Properties Correct
16951 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016952 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016953 *
16954 * Fixes finish doing the computations on the attributes definitions
16955 */
16956static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016957xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016958 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016959 const xmlChar * name ATTRIBUTE_UNUSED)
16960{
16961
16962 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016963 * 2 if there is a {value constraint}, the canonical lexical
16964 * representation of its value must be ·valid· with respect
16965 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016966 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016967 if (item->defValue != NULL) {
16968 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016969
16970 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016971 PERROR_INT("xmlSchemaCheckAttrValConstr",
16972 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016973 return;
16974 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016975 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
16976 item->node, item->subtypes, item->defValue, &(item->defVal),
16977 1, 1, 0);
16978 if (ret != 0) {
16979 if (ret < 0) {
16980 PERROR_INT("xmlSchemaAttrCheckValConstr",
16981 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016982 return;
16983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016984 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
16985 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16986 ret, item->node, (xmlSchemaTypePtr) item,
16987 "The value of the value constraint is not valid", NULL, NULL);
16988 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016989 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016990 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016991}
16992
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016993static xmlSchemaElementPtr
16994xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
16995 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016996{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016997 xmlSchemaElementPtr ret;
16998
16999 if (SUBST_GROUP_AFF(ancestor) == NULL)
17000 return (NULL);
17001 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17002 return (ancestor);
17003
17004 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17005 return (NULL);
17006 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17007 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17008 SUBST_GROUP_AFF(ancestor));
17009 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17010
17011 return (ret);
17012}
17013
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017014/**
17015 * xmlSchemaCheckElemPropsCorrect:
17016 * @ctxt: a schema parser context
17017 * @decl: the element declaration
17018 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017019 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017020 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017021 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017022 *
17023 * STATUS:
17024 * missing: (6)
17025 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017026static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017027xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17028 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017029{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017030 int ret = 0;
17031 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017032 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017033 * SPEC (1) "The values of the properties of an element declaration
17034 * must be as described in the property tableau in The Element
17035 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17036 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017037 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017038 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017039 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017040
17041 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017042 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017043 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017044 * affiliation}, then {scope} must be global."
17045 */
17046 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17047 xmlSchemaPCustomErr(pctxt,
17048 XML_SCHEMAP_E_PROPS_CORRECT_3,
17049 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17050 "Only global element declarations can have a "
17051 "substitution group affiliation", NULL);
17052 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017053 }
17054 /*
17055 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17056 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017057 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017058 * property."
17059 */
17060 if (head == elemDecl)
17061 circ = head;
17062 else if (SUBST_GROUP_AFF(head) != NULL)
17063 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17064 else
17065 circ = NULL;
17066 if (circ != NULL) {
17067 xmlChar *strA = NULL, *strB = NULL;
17068
17069 xmlSchemaPCustomErrExt(pctxt,
17070 XML_SCHEMAP_E_PROPS_CORRECT_6,
17071 NULL, (xmlSchemaTypePtr) circ, circ->node,
17072 "The element declaration '%s' defines a circular "
17073 "substitution group to element declaration '%s'",
17074 xmlSchemaGetComponentQName(&strA, circ),
17075 xmlSchemaGetComponentQName(&strB, head),
17076 NULL);
17077 FREE_AND_NULL(strA)
17078 FREE_AND_NULL(strB)
17079 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17080 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017081 /*
17082 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017083 * the {type definition}
17084 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017085 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017086 * of the {substitution group exclusions} of the {substitution group
17087 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17088 * (if the {type definition} is complex) or as defined in
17089 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017090 * simple)."
17091 *
17092 * NOTE: {substitution group exclusions} means the values of the
17093 * attribute "final".
17094 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017095
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017096 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017097 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017098
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017099 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17100 set |= SUBSET_EXTENSION;
17101 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17102 set |= SUBSET_RESTRICTION;
17103
17104 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17105 ELEM_TYPE(head), set) != 0) {
17106 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17107
17108 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017109 xmlSchemaPCustomErrExt(pctxt,
17110 XML_SCHEMAP_E_PROPS_CORRECT_4,
17111 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017112 "The type definition '%s' was "
17113 "either rejected by the substitution group "
17114 "affiliation '%s', or not validly derived from its type "
17115 "definition '%s'",
17116 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017117 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017118 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017119 FREE_AND_NULL(strA)
17120 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017121 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017122 }
17123 }
17124 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017125 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017126 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017127 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017128 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017129 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017130 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017131 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017132 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017133 ((IS_SIMPLE_TYPE(typeDef) &&
17134 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017135 (IS_COMPLEX_TYPE(typeDef) &&
17136 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017137 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17138 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017139
17140 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17141 xmlSchemaPCustomErr(pctxt,
17142 XML_SCHEMAP_E_PROPS_CORRECT_5,
17143 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17144 "The type definition (or type definition's content type) is or "
17145 "is derived from ID; value constraints are not allowed in "
17146 "conjunction with such a type definition", NULL);
17147 } else if (elemDecl->value != NULL) {
17148 int vcret;
17149 xmlNodePtr node = NULL;
17150
17151 /*
17152 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17153 * representation of its value must be ·valid· with respect to the
17154 * {type definition} as defined in Element Default Valid (Immediate)
17155 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017156 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017157 if (typeDef == NULL) {
17158 xmlSchemaPErr(pctxt, elemDecl->node,
17159 XML_SCHEMAP_INTERNAL,
17160 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17161 "type is missing... skipping validation of "
17162 "the value constraint", NULL, NULL);
17163 return (-1);
17164 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017165 if (elemDecl->node != NULL) {
17166 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17167 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17168 BAD_CAST "fixed");
17169 else
17170 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17171 BAD_CAST "default");
17172 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017173 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17174 typeDef, elemDecl->value, &(elemDecl->defVal));
17175 if (vcret != 0) {
17176 if (vcret < 0) {
17177 PERROR_INT("xmlSchemaElemCheckValConstr",
17178 "failed to validate the value constraint of an "
17179 "element declaration");
17180 return (-1);
17181 }
17182 return (vcret);
17183 }
17184 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017185
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017186 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017187}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017188
17189/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017190 * xmlSchemaCheckElemSubstGroup:
17191 * @ctxt: a schema parser context
17192 * @decl: the element declaration
17193 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017194 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017195 * Schema Component Constraint:
17196 * Substitution Group (cos-equiv-class)
17197 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017198 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017199 * a list will be built for each subst. group head, holding all direct
17200 * referents to this head.
17201 * NOTE that this function needs:
17202 * 1. circular subst. groups to be checked beforehand
17203 * 2. the declaration's type to be derived from the head's type
17204 *
17205 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017206 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017207 */
17208static void
17209xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17210 xmlSchemaElementPtr elemDecl)
17211{
17212 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17213 /* SPEC (1) "Its {abstract} is false." */
17214 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17215 return;
17216 {
17217 xmlSchemaElementPtr head;
17218 xmlSchemaTypePtr headType, type;
17219 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017220 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017221 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17222 * {disallowed substitutions} as the blocking constraint, as defined in
17223 * Substitution Group OK (Transitive) (§3.3.6)."
17224 */
17225 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17226 head = SUBST_GROUP_AFF(head)) {
17227 set = 0;
17228 methSet = 0;
17229 /*
17230 * The blocking constraints.
17231 */
17232 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17233 continue;
17234 headType = head->subtypes;
17235 type = elemDecl->subtypes;
17236 if (headType == type)
17237 goto add_member;
17238 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17239 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17240 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17241 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17242 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017243 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017244 * "The set of all {derivation method}s involved in the
17245 * derivation of D's {type definition} from C's {type definition}
17246 * does not intersect with the union of the blocking constraint,
17247 * C's {prohibited substitutions} (if C is complex, otherwise the
17248 * empty set) and the {prohibited substitutions} (respectively the
17249 * empty set) of any intermediate {type definition}s in the
17250 * derivation of D's {type definition} from C's {type definition}."
17251 */
17252 /*
17253 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17254 * subst.head axis, the methSet does not need to be computed for
17255 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017256 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017257 /*
17258 * The set of all {derivation method}s involved in the derivation
17259 */
17260 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017261 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017262 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17263 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17264 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017265
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017266 if ((type->flags &
17267 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17268 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17269 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17270
17271 type = type->baseType;
17272 }
17273 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017274 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017275 * the head's type.
17276 */
17277 type = elemDecl->subtypes->baseType;
17278 while (type != NULL) {
17279 if (IS_COMPLEX_TYPE(type)) {
17280 if ((type->flags &
17281 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17282 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17283 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17284 if ((type->flags &
17285 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17286 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17287 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17288 } else
17289 break;
17290 if (type == headType)
17291 break;
17292 type = type->baseType;
17293 }
17294 if ((set != 0) &&
17295 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17296 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17297 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17298 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17299 continue;
17300 }
17301add_member:
17302 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17303 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17304 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17305 }
17306 }
17307}
17308
17309/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017310 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017311 * @item: an schema element declaration/particle
17312 * @ctxt: a schema parser context
17313 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017314 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017315 * Validates the value constraints of an element declaration.
17316 *
17317 * Fixes finish doing the computations on the element declarations.
17318 */
17319static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017320xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017321 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017322 const xmlChar * name ATTRIBUTE_UNUSED)
17323{
17324 if (elemDecl == NULL)
17325 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017326 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17327 return;
17328 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017329 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17330 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017331}
17332
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017333/**
17334 * xmlSchemaMiscRefFixup:
17335 * @item: an schema component
17336 * @ctxt: a schema parser context
17337 * @name: the internal name of the component
17338 *
17339 * Resolves references of misc. schema components.
17340 */
17341static void
17342xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017343 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017344 const xmlChar * name ATTRIBUTE_UNUSED)
17345{
17346 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017347 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017348 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17349 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17350 xmlSchemaTreeItemPtr refItem;
17351 /*
17352 * Resolve the reference.
17353 */
17354 item->children = NULL;
17355 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17356 ref->itemType, ref->name, ref->targetNamespace);
17357 if (refItem == NULL) {
17358 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017359 NULL, GET_NODE(item), "ref", ref->name,
17360 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017361 } else {
17362 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17363 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017364 * NOTE that we will assign the model group definition
17365 * itself to the "term" of the particle. This will ease
17366 * the check for circular model group definitions. After
17367 * that the "term" will be assigned the model group of the
17368 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017369 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017370 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017371 } else
17372 item->children = refItem;
17373 }
17374 }
17375 }
17376}
17377
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017378static int
17379xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17380 xmlSchemaValPtr y)
17381{
17382 xmlSchemaTypePtr tx, ty, ptx, pty;
17383 int ret;
17384
17385 while (x != NULL) {
17386 /* Same types. */
17387 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17388 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17389 ptx = xmlSchemaGetPrimitiveType(tx);
17390 pty = xmlSchemaGetPrimitiveType(ty);
17391 /*
17392 * (1) if a datatype T' is ·derived· by ·restriction· from an
17393 * atomic datatype T then the ·value space· of T' is a subset of
17394 * the ·value space· of T. */
17395 /*
17396 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17397 * from a common atomic ancestor T then the ·value space·s of T'
17398 * and T'' may overlap.
17399 */
17400 if (ptx != pty)
17401 return(0);
17402 /*
17403 * We assume computed values to be normalized, so do a fast
17404 * string comparison for string based types.
17405 */
17406 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17407 IS_ANY_SIMPLE_TYPE(ptx)) {
17408 if (! xmlStrEqual(
17409 xmlSchemaValueGetAsString(x),
17410 xmlSchemaValueGetAsString(y)))
17411 return (0);
17412 } else {
17413 ret = xmlSchemaCompareValuesWhtsp(
17414 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17415 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17416 if (ret == -2)
17417 return(-1);
17418 if (ret != 0)
17419 return(0);
17420 }
17421 /*
17422 * Lists.
17423 */
17424 x = xmlSchemaValueGetNext(x);
17425 if (x != NULL) {
17426 y = xmlSchemaValueGetNext(y);
17427 if (y == NULL)
17428 return (0);
17429 } else if (xmlSchemaValueGetNext(y) != NULL)
17430 return (0);
17431 else
17432 return (1);
17433 }
17434 return (0);
17435}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017436
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017437/**
17438 * xmlSchemaAttrFixup:
17439 * @item: an schema attribute declaration/use.
17440 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017441 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017442 *
17443 * Fixes finish doing the computations on attribute declarations/uses.
17444 */
17445static void
17446xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017447 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017448 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017449{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017450 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017451 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017452 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017453 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017454 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017455 * The simple type definition corresponding to the <simpleType> element
17456 * information item in the [children], if present, otherwise the simple
17457 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017458 * [attribute], if present, otherwise the ·simple ur-type definition·.
17459 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017460 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017461 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017462 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17463 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017464 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017465 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017466 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017467
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017468 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17469 item->typeNs);
17470 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017471 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017472 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017473 (xmlSchemaTypePtr) item, item->node,
17474 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017475 XML_SCHEMA_TYPE_SIMPLE, NULL);
17476 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017477 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017478
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017479 } else if (item->ref != NULL) {
17480 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017481
Daniel Veillardc0826a72004-08-10 14:17:33 +000017482 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017483 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017484 * attribute declaration.
17485 */
17486 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017487 * TODO: Evaluate, what errors could occur if the declaration is not
17488 * found. It might be possible that the "typefixup" might crash if
17489 * no ref declaration was found.
17490 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017491 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017492 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017493 xmlSchemaPResCompAttrErr(ctxt,
17494 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017495 (xmlSchemaTypePtr) item, item->node,
17496 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017497 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017498 return;
17499 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017500 item->refDecl = decl;
17501 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017502
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017503 item->subtypes = decl->subtypes;
17504 /*
17505 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017506 * au-props-correct.2: If the {attribute declaration} has a fixed
17507 * {value constraint}, then if the attribute use itself has a
17508 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017509 * that of the {attribute declaration}'s {value constraint}.
17510 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017511 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017512 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017513 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017514 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017515 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17516 NULL, NULL, item->node,
17517 "The attribute declaration has a 'fixed' value constraint "
17518 ", thus it must be 'fixed' in attribute use as well",
17519 NULL);
17520 } else {
17521 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17522 xmlSchemaPCustomErr(ctxt,
17523 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17524 NULL, NULL, item->node,
17525 "The 'fixed' value constraint of the attribute use "
17526 "must match the attribute declaration's value "
17527 "constraint '%s'",
17528 decl->defValue);
17529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017530 }
17531 /*
17532 * FUTURE: One should change the values of the attr. use
17533 * if ever validation should be attempted even if the
17534 * schema itself was not fully valid.
17535 */
17536 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017537 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017538 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17539 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017540}
17541
17542/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017543 * xmlSchemaResolveIDCKeyRef:
17544 * @idc: the identity-constraint definition
17545 * @ctxt: the schema parser context
17546 * @name: the attribute name
17547 *
17548 * Resolve keyRef references to key/unique IDCs.
17549 */
17550static void
17551xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017552 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017553 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017554{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017555 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17556 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017557 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017558 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017559 ctxt->schema->idcDef,
17560 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017561 idc->ref->targetNamespace);
17562 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017563 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017564 * TODO: It is actually not an error to fail to resolve.
17565 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017566 xmlSchemaPResCompAttrErr(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017567 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017568 (xmlSchemaTypePtr) idc, idc->node,
17569 "refer", idc->ref->name,
17570 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017571 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17572 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017574 }
17575}
17576
17577/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017578 * xmlSchemaParse:
17579 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017580 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017581 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017582 * XML Shema struture which can be used to validate instances.
17583 * *WARNING* this interface is highly subject to change
17584 *
17585 * Returns the internal XML Schema structure built from the resource or
17586 * NULL in case of error
17587 */
17588xmlSchemaPtr
17589xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17590{
17591 xmlSchemaPtr ret = NULL;
17592 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017593 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017594 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017595
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017596 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017597 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017598 * the API; i.e. not automatically by the validated instance document.
17599 */
17600
Daniel Veillard4255d502002-04-16 15:50:10 +000017601 xmlSchemaInitTypes();
17602
Daniel Veillard6045c902002-10-09 21:13:59 +000017603 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017604 return (NULL);
17605
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017606 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017607 ctxt->counter = 0;
17608 ctxt->container = NULL;
17609
17610 /*
17611 * First step is to parse the input document into an DOM/Infoset
17612 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017613 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017614 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017615 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017616 if (doc == NULL) {
17617 xmlSchemaPErr(ctxt, NULL,
17618 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017619 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017620 ctxt->URL, NULL);
17621 return (NULL);
17622 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017623 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017624 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17625 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017626 if (doc == NULL) {
17627 xmlSchemaPErr(ctxt, NULL,
17628 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017629 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017630 NULL, NULL);
17631 return (NULL);
17632 }
17633 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017634 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017635 } else if (ctxt->doc != NULL) {
17636 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017637 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017638 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017639 xmlSchemaPErr(ctxt, NULL,
17640 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017641 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017642 NULL, NULL);
17643 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017644 }
17645
17646 /*
17647 * Then extract the root and Schema parse it
17648 */
17649 root = xmlDocGetRootElement(doc);
17650 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017651 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17652 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017653 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017654 if (!preserve) {
17655 xmlFreeDoc(doc);
17656 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017657 return (NULL);
17658 }
17659
17660 /*
17661 * Remove all the blank text nodes
17662 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017663 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017664
17665 /*
17666 * Then do the parsing for good
17667 */
17668 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017669 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017670 if (!preserve) {
17671 xmlFreeDoc(doc);
17672 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017673 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017674 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017675 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017676 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017677 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017678 ctxt->ctxtType = NULL;
17679 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017680
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017681 /*
17682 * Resolve base types of simple/complex types.
17683 */
17684 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017685
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017686 if (ctxt->nberrors != 0)
17687 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017688
17689 if (ret->volatiles != NULL) {
17690 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17691 int i;
17692 xmlSchemaTreeItemPtr item;
17693
17694 for (i = 0; i < list->nbItems; i++) {
17695 item = (xmlSchemaTreeItemPtr) list->items[i];
17696 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17697 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017698 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017699 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017700 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017701 * Then fixup all attributes declarations
17702 */
17703 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017704 /*
17705 * Then fixup all attributes group declarations
17706 */
17707 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17708 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017709 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017710 * Resolve identity-constraint keyRefs.
17711 */
17712 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017713 /*
17714 * Check type defnitions for circular references.
17715 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017716 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017717 xmlSchemaCheckTypeDefCircular, ctxt);
17718 /*
17719 * Check model groups defnitions for circular references.
17720 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017721 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017722 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017723 /*
17724 * Set the "term" of particles pointing to model group definitions
17725 * to the contained model group.
17726 */
17727 if (ret->volatiles != NULL) {
17728 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17729 int i;
17730 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017731
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017732 for (i = 0; i < list->nbItems; i++) {
17733 item = (xmlSchemaParticlePtr) list->items[i];
17734 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17735 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17736 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017737 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017738 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017739 * Check attribute groups for circular references.
17740 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017741 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17742 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017743 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017744 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017745 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017746 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017747 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017748 /*
17749 * We will stop here if the schema was not valid to avoid internal errors
17750 * on missing sub-components. This is not conforming to the spec, since it
17751 * allows missing components, but it might make further processing crash.
17752 * So see it as a very strict handling, which might be made more lax in the
17753 * future.
17754 */
17755 if (ctxt->nberrors != 0)
17756 goto exit;
17757 /*
17758 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017759 */
17760 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017761 /*
17762 * Validate the value constraint of attribute declarations/uses.
17763 */
17764 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017765 /*
17766 * Validate the value constraint of element declarations.
17767 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017768 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017769
17770 if (ctxt->nberrors != 0)
17771 goto exit;
17772
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017773 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017774 * TODO: cos-element-consistent, cos-all-limited
17775 *
17776 * Then build the content model for all complex types
17777 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017778 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017779 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017780
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017781exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017782 if (ctxt->nberrors != 0) {
17783 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017784 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017785 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017786 return (ret);
17787}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017788
Daniel Veillard4255d502002-04-16 15:50:10 +000017789/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017790 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017791 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017792 * @err: the error callback
17793 * @warn: the warning callback
17794 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017795 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017796 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017797 */
17798void
17799xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017800 xmlSchemaValidityErrorFunc err,
17801 xmlSchemaValidityWarningFunc warn, void *ctx)
17802{
Daniel Veillard4255d502002-04-16 15:50:10 +000017803 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017804 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017805 ctxt->error = err;
17806 ctxt->warning = warn;
17807 ctxt->userData = ctx;
17808}
17809
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017810/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017811 * xmlSchemaGetParserErrors:
17812 * @ctxt: a XMl-Schema parser context
17813 * @err: the error callback result
17814 * @warn: the warning callback result
17815 * @ctx: contextual data for the callbacks result
17816 *
17817 * Get the callback information used to handle errors for a parser context
17818 *
17819 * Returns -1 in case of failure, 0 otherwise
17820 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017821int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017822xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17823 xmlSchemaValidityErrorFunc * err,
17824 xmlSchemaValidityWarningFunc * warn, void **ctx)
17825{
17826 if (ctxt == NULL)
17827 return(-1);
17828 if (err != NULL)
17829 *err = ctxt->error;
17830 if (warn != NULL)
17831 *warn = ctxt->warning;
17832 if (ctx != NULL)
17833 *ctx = ctxt->userData;
17834 return(0);
17835}
17836
17837/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017838 * xmlSchemaFacetTypeToString:
17839 * @type: the facet type
17840 *
17841 * Convert the xmlSchemaTypeType to a char string.
17842 *
17843 * Returns the char string representation of the facet type if the
17844 * type is a facet and an "Internal Error" string otherwise.
17845 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017846static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017847xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17848{
17849 switch (type) {
17850 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017851 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017852 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017853 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017854 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017855 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017856 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017857 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017858 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017859 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017860 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017861 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017862 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017863 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017864 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017865 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017866 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017867 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017868 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017869 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017870 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017871 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017872 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017873 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017874 default:
17875 break;
17876 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017877 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017878}
17879
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017880static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017881xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17882{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017883 /*
17884 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017885 * from xsd:string.
17886 */
17887 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017888 /*
17889 * Note that we assume a whitespace of preserve for anySimpleType.
17890 */
17891 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17892 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17893 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017894 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017895 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017896 else {
17897 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017898 * For all ·atomic· datatypes other than string (and types ·derived·
17899 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017900 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017901 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017902 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017903 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017904 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017905 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017906 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017907 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017908 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017909 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17910 } else if (VARIETY_UNION(type)) {
17911 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17912 } else if (VARIETY_ATOMIC(type)) {
17913 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17914 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17915 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17916 return (XML_SCHEMA_WHITESPACE_REPLACE);
17917 else
17918 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017919 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017920 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017921}
17922
Daniel Veillard4255d502002-04-16 15:50:10 +000017923/************************************************************************
17924 * *
17925 * Simple type validation *
17926 * *
17927 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017928
Daniel Veillard4255d502002-04-16 15:50:10 +000017929
17930/************************************************************************
17931 * *
17932 * DOM Validation code *
17933 * *
17934 ************************************************************************/
17935
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017936static void
17937xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17938{
17939 int i, nbItems;
17940 xmlSchemaTypePtr item, *items;
17941
17942
17943 /*
17944 * During the Assemble of the schema ctxt->curItems has
17945 * been filled with the relevant new items. Fix those up.
17946 */
17947 nbItems = ctxt->assemble->nbItems;
17948 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017949
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017950 for (i = 0; i < nbItems; i++) {
17951 item = items[i];
17952 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017953 case XML_SCHEMA_TYPE_COMPLEX:
17954 case XML_SCHEMA_TYPE_SIMPLE:
17955 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
17956 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017957 case XML_SCHEMA_TYPE_ATTRIBUTE:
17958 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17959 break;
17960 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017961 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017962 NULL, NULL, NULL);
17963 break;
17964 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017965 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017966 ctxt, NULL);
17967 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017968 case XML_SCHEMA_TYPE_PARTICLE:
17969 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017970 default:
17971 break;
17972 }
17973 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017974 if (ctxt->nberrors != 0)
17975 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017976 /*
17977 * Circularity checks.
17978 */
17979 for (i = 0; i < nbItems; i++) {
17980 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017981 switch (item->type) {
17982 case XML_SCHEMA_TYPE_COMPLEX:
17983 case XML_SCHEMA_TYPE_SIMPLE:
17984 xmlSchemaCheckTypeDefCircular(
17985 (xmlSchemaTypePtr) item, ctxt, NULL);
17986 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017987 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017988 xmlSchemaCheckGroupDefCircular(
17989 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017990 break;
17991 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17992 xmlSchemaCheckAttributeGroupCircular(
17993 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
17994 break;
17995 default:
17996 break;
17997 }
17998 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017999 if (ctxt->nberrors != 0)
18000 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018001 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018002 * Set the "term" of particles pointing to model group definitions
18003 * to the contained model group.
18004 */
18005 for (i = 0; i < nbItems; i++) {
18006 item = items[i];
18007 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18008 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018009 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018010 XML_SCHEMA_TYPE_GROUP)) {
18011 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18012 ctxt, NULL);
18013 }
18014 }
18015 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018016 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018017 */
18018 for (i = 0; i < nbItems; i++) {
18019 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018020 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018021 case XML_SCHEMA_TYPE_SIMPLE:
18022 case XML_SCHEMA_TYPE_COMPLEX:
18023 xmlSchemaTypeFixup(item, ctxt, NULL);
18024 break;
18025 default:
18026 break;
18027 }
18028 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018029 if (ctxt->nberrors != 0)
18030 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018031 /*
18032 * Validate value contraint values.
18033 */
18034 for (i = 0; i < nbItems; i++) {
18035 item = items[i];
18036 switch (item->type) {
18037 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018038 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18039 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018040 break;
18041 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018042 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018043 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018044 break;
18045 default:
18046 break;
18047 }
18048 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018049 if (ctxt->nberrors != 0)
18050 return;
18051 /*
18052 * Build the content model for complex types.
18053 */
18054 for (i = 0; i < nbItems; i++) {
18055 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018056 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018057 case XML_SCHEMA_TYPE_COMPLEX:
18058 xmlSchemaBuildContentModel(item, ctxt, NULL);
18059 break;
18060 default:
18061 break;
18062 }
18063 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018064}
18065
18066/**
18067 * xmlSchemaAssembleByLocation:
18068 * @pctxt: a schema parser context
18069 * @vctxt: a schema validation context
18070 * @schema: the existing schema
18071 * @node: the node that fired the assembling
18072 * @nsName: the namespace name of the new schema
18073 * @location: the location of the schema
18074 *
18075 * Expands an existing schema by an additional schema.
18076 *
18077 * Returns 0 if the new schema is correct, a positive error code
18078 * number otherwise and -1 in case of an internal or API error.
18079 */
18080static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018081xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018082 xmlSchemaPtr schema,
18083 xmlNodePtr node,
18084 const xmlChar *nsName,
18085 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018086{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018087 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018088 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018089 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018090 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018091 xmlSchemaParserCtxtPtr pctxt;
18092
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018093 /*
18094 * This should be used:
18095 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018096 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018097 * 3. if requested via the API
18098 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018099 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018100 return (-1);
18101 /*
18102 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018103 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018104 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018105 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18106 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018107 pctxt = vctxt->pctxt;
18108 /*
18109 * Set the counter to produce unique names for anonymous items.
18110 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018111 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018112 /*
18113 * Acquire the schema document.
18114 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018115 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18116 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018117 if (ret != 0) {
18118 if (doc != NULL)
18119 xmlFreeDoc(doc);
18120 } else if (doc != NULL) {
18121 docElem = xmlDocGetRootElement(doc);
18122 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018123 * Create new assemble info.
18124 */
18125 if (pctxt->assemble == NULL) {
18126 pctxt->assemble = xmlSchemaNewAssemble();
18127 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018128 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018129 "Memory error: xmlSchemaAssembleByLocation, "
18130 "allocating assemble info", NULL);
18131 xmlFreeDoc(doc);
18132 return (-1);
18133 }
18134 }
18135 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018136 * Save and reset the context & schema.
18137 */
18138 oldflags = schema->flags;
18139 oldtns = schema->targetNamespace;
18140 olddoc = schema->doc;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018141
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018142 xmlSchemaClearSchemaDefaults(schema);
18143 schema->targetNamespace = targetNs;
18144 /* schema->nbCurItems = 0; */
18145 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018146 pctxt->ctxtType = NULL;
18147 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018148
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018149 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18150 if (pctxt->nberrors != 0) {
18151 vctxt->nberrors += pctxt->nberrors;
18152 goto finally;
18153 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018154 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018155 if (pctxt->nberrors != 0) {
18156 vctxt->nberrors += pctxt->nberrors;
18157 goto finally;
18158 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018159 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018160 if (pctxt->nberrors != 0)
18161 vctxt->nberrors += pctxt->nberrors;
18162finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018163 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018164 * Set the counter of items.
18165 */
18166 schema->counter = pctxt->counter;
18167 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018168 * Free the list of assembled components.
18169 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018170 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018171 /*
18172 * Restore the context & schema.
18173 */
18174 schema->flags = oldflags;
18175 schema->targetNamespace = oldtns;
18176 schema->doc = olddoc;
18177 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018178 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018179 return (ret);
18180}
18181
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018182static xmlSchemaAttrInfoPtr
18183xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18184 int metaType)
18185{
18186 if (vctxt->nbAttrInfos == 0)
18187 return (NULL);
18188 {
18189 int i;
18190 xmlSchemaAttrInfoPtr iattr;
18191
18192 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18193 iattr = vctxt->attrInfos[i];
18194 if (iattr->metaType == metaType)
18195 return (iattr);
18196 }
18197
18198 }
18199 return (NULL);
18200}
18201
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018202/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018203 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018204 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018205 *
18206 * Expands an existing schema by an additional schema using
18207 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18208 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18209 * must be set to 1.
18210 *
18211 * Returns 0 if the new schema is correct, a positive error code
18212 * number otherwise and -1 in case of an internal or API error.
18213 */
18214static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018215xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018216{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018217 const xmlChar *cur, *end;
18218 const xmlChar *nsname = NULL, *location;
18219 int count = 0;
18220 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018221 xmlSchemaAttrInfoPtr iattr;
18222
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018223 /*
18224 * Parse the value; we will assume an even number of values
18225 * to be given (this is how Xerces and XSV work).
18226 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018227 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18228 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18229 if (iattr == NULL)
18230 xmlSchemaGetMetaAttrInfo(vctxt,
18231 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18232 if (iattr == NULL)
18233 return (0);
18234 cur = iattr->value;
18235 do {
18236 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018237 /*
18238 * Get the namespace name.
18239 */
18240 while (IS_BLANK_CH(*cur))
18241 cur++;
18242 end = cur;
18243 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18244 end++;
18245 if (end == cur)
18246 break;
18247 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018248 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 cur = end;
18250 }
18251 /*
18252 * Get the URI.
18253 */
18254 while (IS_BLANK_CH(*cur))
18255 cur++;
18256 end = cur;
18257 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18258 end++;
18259 if (end == cur)
18260 break;
18261 count++;
18262 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018263 cur = end;
18264 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18265 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018266 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018267 VERROR_INT("xmlSchemaAssembleByXSI",
18268 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018269 return (-1);
18270 }
18271 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018272 return (ret);
18273}
18274
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018275#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018276
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018277static const xmlChar *
18278xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18279 const xmlChar *prefix)
18280{
18281 if (vctxt->sax != NULL) {
18282 int i, j;
18283 xmlSchemaNodeInfoPtr inode;
18284
18285 for (i = vctxt->depth; i >= 0; i--) {
18286 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18287 inode = vctxt->elemInfos[i];
18288 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18289 if (((prefix == NULL) &&
18290 (inode->nsBindings[j] == NULL)) ||
18291 ((prefix != NULL) && xmlStrEqual(prefix,
18292 inode->nsBindings[j]))) {
18293
18294 /*
18295 * Note that the namespace bindings are already
18296 * in a string dict.
18297 */
18298 return (inode->nsBindings[j+1]);
18299 }
18300 }
18301 }
18302 }
18303 return (NULL);
18304 } else if (vctxt->reader != NULL) {
18305 xmlChar *nsName;
18306
18307 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18308 if (nsName != NULL) {
18309 const xmlChar *ret;
18310
18311 VAL_CREATE_DICT;
18312 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18313 xmlFree(nsName);
18314 return (ret);
18315 } else
18316 return (NULL);
18317 } else {
18318 xmlNsPtr ns;
18319
18320 if ((vctxt->inode->node == NULL) ||
18321 (vctxt->inode->node->doc == NULL)) {
18322 VERROR_INT("xmlSchemaLookupNamespace",
18323 "no node or node's doc avaliable");
18324 return (NULL);
18325 }
18326 ns = xmlSearchNs(vctxt->inode->node->doc,
18327 vctxt->inode->node, prefix);
18328 if (ns != NULL)
18329 return (ns->href);
18330 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018331 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018332}
18333
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018334/*
18335* This one works on the schema of the validation context.
18336*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018337static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018338xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18339 xmlSchemaPtr schema,
18340 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018341 const xmlChar *value,
18342 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018343 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018344{
18345 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018346
18347 if (vctxt && (vctxt->schema == NULL)) {
18348 VERROR_INT("xmlSchemaValidateNotation",
18349 "a schema is needed on the validation context");
18350 return (-1);
18351 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018352 ret = xmlValidateQName(value, 1);
18353 if (ret != 0)
18354 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018355 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018356 xmlChar *localName = NULL;
18357 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018358
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018359 localName = xmlSplitQName2(value, &prefix);
18360 if (prefix != NULL) {
18361 const xmlChar *nsName = NULL;
18362
18363 if (vctxt != NULL)
18364 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18365 else if (node != NULL) {
18366 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18367 if (ns != NULL)
18368 nsName = ns->href;
18369 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018370 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018371 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018372 return (1);
18373 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018374 if (nsName == NULL) {
18375 xmlFree(prefix);
18376 xmlFree(localName);
18377 return (1);
18378 }
18379 if (xmlHashLookup2(schema->notaDecl, localName,
18380 nsName) != NULL) {
18381 if (valNeeded && (val != NULL)) {
18382 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18383 BAD_CAST xmlStrdup(nsName));
18384 if (*val == NULL)
18385 ret = -1;
18386 }
18387 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018388 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018389 xmlFree(prefix);
18390 xmlFree(localName);
18391 } else {
18392 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18393 if (valNeeded && (val != NULL)) {
18394 (*val) = xmlSchemaNewNOTATIONValue(
18395 BAD_CAST xmlStrdup(value), NULL);
18396 if (*val == NULL)
18397 ret = -1;
18398 }
18399 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018400 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018401 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018402 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018403 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018404}
18405
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018406/************************************************************************
18407 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018408 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018409 * *
18410 ************************************************************************/
18411
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018412/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018413 * xmlSchemaAugmentIDC:
18414 * @idcDef: the IDC definition
18415 *
18416 * Creates an augmented IDC definition item.
18417 *
18418 * Returns the item, or NULL on internal errors.
18419 */
18420static void
18421xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18422 xmlSchemaValidCtxtPtr vctxt)
18423{
18424 xmlSchemaIDCAugPtr aidc;
18425
18426 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18427 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018428 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018429 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18430 NULL);
18431 return;
18432 }
18433 aidc->bubbleDepth = -1;
18434 aidc->def = idcDef;
18435 aidc->next = NULL;
18436 if (vctxt->aidcs == NULL)
18437 vctxt->aidcs = aidc;
18438 else {
18439 aidc->next = vctxt->aidcs;
18440 vctxt->aidcs = aidc;
18441 }
18442}
18443
18444/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018445 * xmlSchemaIDCNewBinding:
18446 * @idcDef: the IDC definition of this binding
18447 *
18448 * Creates a new IDC binding.
18449 *
18450 * Returns the new binding in case of succeeded, NULL on internal errors.
18451 */
18452static xmlSchemaPSVIIDCBindingPtr
18453xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18454{
18455 xmlSchemaPSVIIDCBindingPtr ret;
18456
18457 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18458 sizeof(xmlSchemaPSVIIDCBinding));
18459 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018460 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018461 "allocating a PSVI IDC binding item", NULL);
18462 return (NULL);
18463 }
18464 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18465 ret->definition = idcDef;
18466 return (ret);
18467}
18468
18469/**
18470 * xmlSchemaIDCStoreNodeTableItem:
18471 * @vctxt: the WXS validation context
18472 * @item: the IDC node table item
18473 *
18474 * The validation context is used to store an IDC node table items.
18475 * They are stored to avoid copying them if IDC node-tables are merged
18476 * with corresponding parent IDC node-tables (bubbling).
18477 *
18478 * Returns 0 if succeeded, -1 on internal errors.
18479 */
18480static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018481xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018482 xmlSchemaPSVIIDCNodePtr item)
18483{
18484 /*
18485 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018486 */
18487 if (vctxt->idcNodes == NULL) {
18488 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018489 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18490 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018491 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018492 "allocating the IDC node table item list", NULL);
18493 return (-1);
18494 }
18495 vctxt->sizeIdcNodes = 20;
18496 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18497 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018498 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18499 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018500 sizeof(xmlSchemaPSVIIDCNodePtr));
18501 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018502 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018503 "re-allocating the IDC node table item list", NULL);
18504 return (-1);
18505 }
18506 }
18507 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018508
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018509 return (0);
18510}
18511
18512/**
18513 * xmlSchemaIDCStoreKey:
18514 * @vctxt: the WXS validation context
18515 * @item: the IDC key
18516 *
18517 * The validation context is used to store an IDC key.
18518 *
18519 * Returns 0 if succeeded, -1 on internal errors.
18520 */
18521static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018522xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018523 xmlSchemaPSVIIDCKeyPtr key)
18524{
18525 /*
18526 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018527 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018528 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018529 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018530 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18531 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018532 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018533 "allocating the IDC key storage list", NULL);
18534 return (-1);
18535 }
18536 vctxt->sizeIdcKeys = 40;
18537 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18538 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018539 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18540 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018541 sizeof(xmlSchemaPSVIIDCKeyPtr));
18542 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018543 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018544 "re-allocating the IDC key storage list", NULL);
18545 return (-1);
18546 }
18547 }
18548 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018549
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018550 return (0);
18551}
18552
18553/**
18554 * xmlSchemaIDCAppendNodeTableItem:
18555 * @bind: the IDC binding
18556 * @ntItem: the node-table item
18557 *
18558 * Appends the IDC node-table item to the binding.
18559 *
18560 * Returns 0 on success and -1 on internal errors.
18561 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018562static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018563xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18564 xmlSchemaPSVIIDCNodePtr ntItem)
18565{
18566 if (bind->nodeTable == NULL) {
18567 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018568 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018569 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18570 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018571 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018572 "allocating an array of IDC node-table items", NULL);
18573 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018574 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018575 } else if (bind->sizeNodes <= bind->nbNodes) {
18576 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018577 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18578 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018579 sizeof(xmlSchemaPSVIIDCNodePtr));
18580 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018581 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018582 "re-allocating an array of IDC node-table items", NULL);
18583 return(-1);
18584 }
18585 }
18586 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018587 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018588}
18589
18590/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018591 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018592 * @vctxt: the WXS validation context
18593 * @matcher: the IDC matcher
18594 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018595 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018596 * of the given matcher. If none found, a new one is created
18597 * and added to the IDC table.
18598 *
18599 * Returns an IDC binding or NULL on internal errors.
18600 */
18601static xmlSchemaPSVIIDCBindingPtr
18602xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18603 xmlSchemaIDCMatcherPtr matcher)
18604{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018605 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018606
18607 info = vctxt->elemInfos[matcher->depth];
18608
18609 if (info->idcTable == NULL) {
18610 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18611 if (info->idcTable == NULL)
18612 return (NULL);
18613 return(info->idcTable);
18614 } else {
18615 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018616
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018617 bind = info->idcTable;
18618 do {
18619 if (bind->definition == matcher->aidc->def)
18620 return(bind);
18621 if (bind->next == NULL) {
18622 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18623 if (bind->next == NULL)
18624 return (NULL);
18625 return(bind->next);
18626 }
18627 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018628 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018629 }
18630 return (NULL);
18631}
18632
18633/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018634 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018635 * @key: the IDC key
18636 *
18637 * Frees an IDC key together with its compiled value.
18638 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018639static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018640xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18641{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018642 if (key->val != NULL)
18643 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018644 xmlFree(key);
18645}
18646
18647/**
18648 * xmlSchemaIDCFreeBinding:
18649 *
18650 * Frees an IDC binding. Note that the node table-items
18651 * are not freed.
18652 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018653static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018654xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18655{
18656 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018657 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18658 int i;
18659 /*
18660 * Node-table items for keyrefs are not stored globally
18661 * to the validation context, since they are not bubbled.
18662 * We need to free them here.
18663 */
18664 for (i = 0; i < bind->nbNodes; i++) {
18665 xmlFree(bind->nodeTable[i]->keys);
18666 xmlFree(bind->nodeTable[i]);
18667 }
18668 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018669 xmlFree(bind->nodeTable);
18670 }
18671 xmlFree(bind);
18672}
18673
18674/**
18675 * xmlSchemaIDCFreeIDCTable:
18676 * @bind: the first IDC binding in the list
18677 *
18678 * Frees an IDC table, i.e. all the IDC bindings in the list.
18679 */
18680static void
18681xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18682{
18683 xmlSchemaPSVIIDCBindingPtr prev;
18684
18685 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018686 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018687 bind = bind->next;
18688 xmlSchemaIDCFreeBinding(prev);
18689 }
18690}
18691
18692/**
18693 * xmlSchemaIDCFreeMatcherList:
18694 * @matcher: the first IDC matcher in the list
18695 *
18696 * Frees a list of IDC matchers.
18697 */
18698static void
18699xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18700{
18701 xmlSchemaIDCMatcherPtr next;
18702
18703 while (matcher != NULL) {
18704 next = matcher->next;
18705 if (matcher->keySeqs != NULL) {
18706 int i;
18707 for (i = 0; i < matcher->sizeKeySeqs; i++)
18708 if (matcher->keySeqs[i] != NULL)
18709 xmlFree(matcher->keySeqs[i]);
18710 xmlFree(matcher->keySeqs);
18711 }
18712 xmlFree(matcher);
18713 matcher = next;
18714 }
18715}
18716
18717/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018718 * xmlSchemaIDCAddStateObject:
18719 * @vctxt: the WXS validation context
18720 * @matcher: the IDC matcher
18721 * @sel: the XPath information
18722 * @parent: the parent "selector" state object if any
18723 * @type: "selector" or "field"
18724 *
18725 * Creates/reuses and activates state objects for the given
18726 * XPath information; if the XPath expression consists of unions,
18727 * multiple state objects are created for every unioned expression.
18728 *
18729 * Returns 0 on success and -1 on internal errors.
18730 */
18731static int
18732xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18733 xmlSchemaIDCMatcherPtr matcher,
18734 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018735 int type)
18736{
18737 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018738
18739 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018740 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018741 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018742 if (vctxt->xpathStatePool != NULL) {
18743 sto = vctxt->xpathStatePool;
18744 vctxt->xpathStatePool = sto->next;
18745 sto->next = NULL;
18746 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018747 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018748 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018749 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018750 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18751 if (sto == NULL) {
18752 xmlSchemaVErrMemory(NULL,
18753 "allocating an IDC state object", NULL);
18754 return (-1);
18755 }
18756 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18757 }
18758 /*
18759 * Add to global list.
18760 */
18761 if (vctxt->xpathStates != NULL)
18762 sto->next = vctxt->xpathStates;
18763 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018764
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018765 /*
18766 * Free the old xpath validation context.
18767 */
18768 if (sto->xpathCtxt != NULL)
18769 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18770
18771 /*
18772 * Create a new XPath (pattern) validation context.
18773 */
18774 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18775 (xmlPatternPtr) sel->xpathComp);
18776 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018777 VERROR_INT("xmlSchemaIDCAddStateObject",
18778 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018779 return (-1);
18780 }
18781 sto->type = type;
18782 sto->depth = vctxt->depth;
18783 sto->matcher = matcher;
18784 sto->sel = sel;
18785 sto->nbHistory = 0;
18786
18787#if DEBUG_IDC
18788 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18789 sto->sel->xpath);
18790#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018791 return (0);
18792}
18793
18794/**
18795 * xmlSchemaXPathEvaluate:
18796 * @vctxt: the WXS validation context
18797 * @nodeType: the nodeType of the current node
18798 *
18799 * Evaluates all active XPath state objects.
18800 *
18801 * Returns the number of IC "field" state objects which resolved to
18802 * this node, 0 if none resolved and -1 on internal errors.
18803 */
18804static int
18805xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018806 xmlElementType nodeType)
18807{
18808 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018809 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018810
18811 if (vctxt->xpathStates == NULL)
18812 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018813
18814 if (nodeType == XML_ATTRIBUTE_NODE)
18815 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018816#if DEBUG_IDC
18817 {
18818 xmlChar *str = NULL;
18819 xmlGenericError(xmlGenericErrorContext,
18820 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018821 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18822 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018823 FREE_AND_NULL(str)
18824 }
18825#endif
18826 /*
18827 * Process all active XPath state objects.
18828 */
18829 first = vctxt->xpathStates;
18830 sto = first;
18831 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018832#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018833 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018834 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18835 sto->matcher->aidc->def->name, sto->sel->xpath);
18836 else
18837 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18838 sto->matcher->aidc->def->name, sto->sel->xpath);
18839#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018840 if (nodeType == XML_ELEMENT_NODE)
18841 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018842 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018843 else
18844 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018845 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018846
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018847 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018848 VERROR_INT("xmlSchemaXPathEvaluate",
18849 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018850 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018851 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018852 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018853 goto next_sto;
18854 /*
18855 * Full match.
18856 */
18857#if DEBUG_IDC
18858 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018859 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018860#endif
18861 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018862 * Register a match in the state object history.
18863 */
18864 if (sto->history == NULL) {
18865 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18866 if (sto->history == NULL) {
18867 xmlSchemaVErrMemory(NULL,
18868 "allocating the state object history", NULL);
18869 return(-1);
18870 }
18871 sto->sizeHistory = 10;
18872 } else if (sto->sizeHistory <= sto->nbHistory) {
18873 sto->sizeHistory *= 2;
18874 sto->history = (int *) xmlRealloc(sto->history,
18875 sto->sizeHistory * sizeof(int));
18876 if (sto->history == NULL) {
18877 xmlSchemaVErrMemory(NULL,
18878 "re-allocating the state object history", NULL);
18879 return(-1);
18880 }
18881 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018882 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018883
18884#ifdef DEBUG_IDC
18885 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18886 vctxt->depth);
18887#endif
18888
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018889 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18890 xmlSchemaIDCSelectPtr sel;
18891 /*
18892 * Activate state objects for the IDC fields of
18893 * the IDC selector.
18894 */
18895#if DEBUG_IDC
18896 xmlGenericError(xmlGenericErrorContext, "IDC: "
18897 "activating field states\n");
18898#endif
18899 sel = sto->matcher->aidc->def->fields;
18900 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018901 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18902 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18903 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018904 sel = sel->next;
18905 }
18906 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18907 /*
18908 * An IDC key node was found.
18909 */
18910#if DEBUG_IDC
18911 xmlGenericError(xmlGenericErrorContext,
18912 "IDC: key found\n");
18913#endif
18914 /*
18915 * Notify that the character value of this node is
18916 * needed.
18917 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018918 if (resolved == 0) {
18919 if ((vctxt->inode->flags &
18920 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
18921 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
18922 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018923 resolved++;
18924 }
18925next_sto:
18926 if (sto->next == NULL) {
18927 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018928 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018929 */
18930 head = first;
18931 sto = vctxt->xpathStates;
18932 } else
18933 sto = sto->next;
18934 }
18935 return (resolved);
18936}
18937
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018938static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018939xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018940 xmlChar **buf,
18941 xmlSchemaPSVIIDCKeyPtr *seq,
18942 int count)
18943{
18944 int i, res;
18945 const xmlChar *value = NULL;
18946
18947 *buf = xmlStrdup(BAD_CAST "[");
18948 for (i = 0; i < count; i++) {
18949 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018950 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
18951 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018952 if (res == 0)
18953 *buf = xmlStrcat(*buf, value);
18954 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018955 VERROR_INT("xmlSchemaFormatIDCKeySequence",
18956 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018957 *buf = xmlStrcat(*buf, BAD_CAST "???");
18958 }
18959 if (i < count -1)
18960 *buf = xmlStrcat(*buf, BAD_CAST "', ");
18961 else
18962 *buf = xmlStrcat(*buf, BAD_CAST "'");
18963 if (value != NULL) {
18964 xmlFree((xmlChar *) value);
18965 value = NULL;
18966 }
18967 }
18968 *buf = xmlStrcat(*buf, BAD_CAST "]");
18969
18970 return (BAD_CAST *buf);
18971}
18972
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018973/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018974 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018975 * @vctxt: the WXS validation context
18976 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018977 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018978 *
18979 * Processes and pops the history items of the IDC state objects.
18980 * IDC key-sequences are validated/created on IDC bindings.
18981 *
18982 * Returns 0 on success and -1 on internal errors.
18983 */
18984static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018985xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018986 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018987{
18988 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018989 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018990 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018991 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018992
18993 if (vctxt->xpathStates == NULL)
18994 return (0);
18995 sto = vctxt->xpathStates;
18996
18997#if DEBUG_IDC
18998 {
18999 xmlChar *str = NULL;
19000 xmlGenericError(xmlGenericErrorContext,
19001 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019002 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19003 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019004 FREE_AND_NULL(str)
19005 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019006#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019007 /*
19008 * Evaluate the state objects.
19009 */
19010 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019011 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019012#if DEBUG_IDC
19013 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19014 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019015#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019016 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019017 goto deregister_check;
19018
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019019 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019020
19021 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019022 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019023 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019024 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019025 sto = sto->next;
19026 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019027 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019028 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19029 if (! IS_SIMPLE_TYPE(type)) {
19030 /*
19031 * Not qualified if the field resolves to a node of non
19032 * simple type.
19033 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019034 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19035 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019036 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19037 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019038 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019039
19040 sto->nbHistory--;
19041 goto deregister_check;
19042 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019043 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019044 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019045 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019046 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019048 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019049 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19050 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019051 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019052 sto->nbHistory--;
19053 goto deregister_check;
19054 } else {
19055 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19056 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019057 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019058
19059 /*
19060 * The key will be anchored on the matcher's list of
19061 * key-sequences. The position in this list is determined
19062 * by the target node's depth relative to the matcher's
19063 * depth of creation (i.e. the depth of the scope element).
19064 */
19065 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019066 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019067
19068 /*
19069 * Create/grow the array of key-sequences.
19070 */
19071 if (matcher->keySeqs == NULL) {
19072 if (pos > 9)
19073 matcher->sizeKeySeqs = pos * 2;
19074 else
19075 matcher->sizeKeySeqs = 10;
19076 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19077 xmlMalloc(matcher->sizeKeySeqs *
19078 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19079 if (matcher->keySeqs == NULL) {
19080 xmlSchemaVErrMemory(NULL,
19081 "allocating an array of key-sequences",
19082 NULL);
19083 return(-1);
19084 }
19085 memset(matcher->keySeqs, 0,
19086 matcher->sizeKeySeqs *
19087 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19088 } else if (pos >= matcher->sizeKeySeqs) {
19089 int i = matcher->sizeKeySeqs;
19090
19091 matcher->sizeKeySeqs *= 2;
19092 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19093 xmlRealloc(matcher->keySeqs,
19094 matcher->sizeKeySeqs *
19095 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019096 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019097 xmlSchemaVErrMemory(NULL,
19098 "reallocating an array of key-sequences",
19099 NULL);
19100 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019101 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019102 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019103 * The array needs to be NULLed.
19104 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019105 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019106 for (; i < matcher->sizeKeySeqs; i++)
19107 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019108 }
19109
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019110 /*
19111 * Get/create the key-sequence.
19112 */
19113 keySeq = matcher->keySeqs[pos];
19114 if (keySeq == NULL) {
19115 goto create_sequence;
19116 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019117 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019118 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019119 * cvc-identity-constraint:
19120 * 3 For each node in the ·target node set· all
19121 * of the {fields}, with that node as the context
19122 * node, evaluate to either an empty node-set or
19123 * a node-set with exactly one member, which must
19124 * have a simple type.
19125 *
19126 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019127 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019128 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19129 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019130 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019131 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019132 "with more than one member",
19133 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019134 sto->nbHistory--;
19135 goto deregister_check;
19136 } else {
19137 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019138 }
19139 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019140
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019141create_sequence:
19142 /*
19143 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019144 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019145 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19146 matcher->aidc->def->nbFields *
19147 sizeof(xmlSchemaPSVIIDCKeyPtr));
19148 if (keySeq == NULL) {
19149 xmlSchemaVErrMemory(NULL,
19150 "allocating an IDC key-sequence", NULL);
19151 return(-1);
19152 }
19153 memset(keySeq, 0, matcher->aidc->def->nbFields *
19154 sizeof(xmlSchemaPSVIIDCKeyPtr));
19155 matcher->keySeqs[pos] = keySeq;
19156create_key:
19157 /*
19158 * Created a key once per node only.
19159 */
19160 if (key == NULL) {
19161 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19162 sizeof(xmlSchemaPSVIIDCKey));
19163 if (key == NULL) {
19164 xmlSchemaVErrMemory(NULL,
19165 "allocating a IDC key", NULL);
19166 xmlFree(keySeq);
19167 matcher->keySeqs[pos] = NULL;
19168 return(-1);
19169 }
19170 /*
19171 * Consume the compiled value.
19172 */
19173 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019174 key->val = vctxt->inode->val;
19175 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019176 /*
19177 * Store the key in a global list.
19178 */
19179 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19180 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019181 return (-1);
19182 }
19183 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019184 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019185 }
19186 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019187
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019188 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19189 xmlSchemaPSVIIDCBindingPtr bind;
19190 xmlSchemaPSVIIDCNodePtr ntItem;
19191 xmlSchemaIDCMatcherPtr matcher;
19192 xmlSchemaIDCPtr idc;
19193 int pos, i, j, nbKeys;
19194 /*
19195 * Here we have the following scenario:
19196 * An IDC 'selector' state object resolved to a target node,
19197 * during the time this target node was in the
19198 * ancestor-or-self axis, the 'field' state object(s) looked
19199 * out for matching nodes to create a key-sequence for this
19200 * target node. Now we are back to this target node and need
19201 * to put the key-sequence, together with the target node
19202 * itself, into the node-table of the corresponding IDC
19203 * binding.
19204 */
19205 matcher = sto->matcher;
19206 idc = matcher->aidc->def;
19207 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019208 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019209 /*
19210 * Check if the matcher has any key-sequences at all, plus
19211 * if it has a key-sequence for the current target node.
19212 */
19213 if ((matcher->keySeqs == NULL) ||
19214 (matcher->sizeKeySeqs <= pos)) {
19215 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19216 goto selector_key_error;
19217 else
19218 goto selector_leave;
19219 }
19220
19221 keySeq = &(matcher->keySeqs[pos]);
19222 if (*keySeq == NULL) {
19223 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19224 goto selector_key_error;
19225 else
19226 goto selector_leave;
19227 }
19228
19229 for (i = 0; i < nbKeys; i++) {
19230 if ((*keySeq)[i] == NULL) {
19231 /*
19232 * Not qualified, if not all fields did resolve.
19233 */
19234 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19235 /*
19236 * All fields of a "key" IDC must resolve.
19237 */
19238 goto selector_key_error;
19239 }
19240 goto selector_leave;
19241 }
19242 }
19243 /*
19244 * All fields did resolve.
19245 */
19246
19247 /*
19248 * 4.1 If the {identity-constraint category} is unique(/key),
19249 * then no two members of the ·qualified node set· have
19250 * ·key-sequences· whose members are pairwise equal, as
19251 * defined by Equal in [XML Schemas: Datatypes].
19252 *
19253 * Get the IDC binding from the matcher and check for
19254 * duplicate key-sequences.
19255 */
19256 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19257 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19258 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019259 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019260
19261 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019262 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019263 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019264 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019265 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019266 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019267 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019268 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019269 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019270 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019271 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019272 if (res == -1) {
19273 return (-1);
19274 } else if (res == 0)
19275 break;
19276 }
19277 if (res == 1) {
19278 /*
19279 * Duplicate found.
19280 */
19281 break;
19282 }
19283 i++;
19284 } while (i < bind->nbNodes);
19285 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019286 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019287 /*
19288 * TODO: Try to report the key-sequence.
19289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019290 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19291 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019292 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019293 "Duplicate key-sequence %s",
19294 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19295 (*keySeq), nbKeys), NULL);
19296 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019297 goto selector_leave;
19298 }
19299 }
19300 /*
19301 * Add a node-table item to the IDC binding.
19302 */
19303 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19304 sizeof(xmlSchemaPSVIIDCNode));
19305 if (ntItem == NULL) {
19306 xmlSchemaVErrMemory(NULL,
19307 "allocating an IDC node-table item", NULL);
19308 xmlFree(*keySeq);
19309 *keySeq = NULL;
19310 return(-1);
19311 }
19312 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19313
19314 /*
19315 * Store the node-table item on global list.
19316 */
19317 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19318 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19319 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019320 xmlFree(*keySeq);
19321 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019322 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019323 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019324 }
19325 /*
19326 * Init the node-table item. Consume the key-sequence.
19327 */
19328 ntItem->node = vctxt->node;
19329 ntItem->keys = *keySeq;
19330 *keySeq = NULL;
19331 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19332 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19333 /*
19334 * Free the item, since keyref items won't be
19335 * put on a global list.
19336 */
19337 xmlFree(ntItem->keys);
19338 xmlFree(ntItem);
19339 }
19340 return (-1);
19341 }
19342
19343 goto selector_leave;
19344selector_key_error:
19345 /*
19346 * 4.2.1 (KEY) The ·target node set· and the
19347 * ·qualified node set· are equal, that is, every
19348 * member of the ·target node set· is also a member
19349 * of the ·qualified node set· and vice versa.
19350 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019351 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19352 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019353selector_leave:
19354 /*
19355 * Free the key-sequence if not added to the IDC table.
19356 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019357 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019358 xmlFree(*keySeq);
19359 *keySeq = NULL;
19360 }
19361 } /* if selector */
19362
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019363 sto->nbHistory--;
19364
19365deregister_check:
19366 /*
19367 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019368 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019369 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019370#if DEBUG_IDC
19371 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19372 sto->sel->xpath);
19373#endif
19374 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019375 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019376 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019377 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019378 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019379 nextsto = sto->next;
19380 /*
19381 * Unlink from the list of active XPath state objects.
19382 */
19383 vctxt->xpathStates = sto->next;
19384 sto->next = vctxt->xpathStatePool;
19385 /*
19386 * Link it to the pool of reusable state objects.
19387 */
19388 vctxt->xpathStatePool = sto;
19389 sto = nextsto;
19390 } else
19391 sto = sto->next;
19392 } /* while (sto != NULL) */
19393 return (0);
19394}
19395
19396/**
19397 * xmlSchemaIDCRegisterMatchers:
19398 * @vctxt: the WXS validation context
19399 * @elemDecl: the element declaration
19400 *
19401 * Creates helper objects to evaluate IDC selectors/fields
19402 * successively.
19403 *
19404 * Returns 0 if OK and -1 on internal errors.
19405 */
19406static int
19407xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19408 xmlSchemaElementPtr elemDecl)
19409{
19410 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19411 xmlSchemaIDCPtr idc, refIdc;
19412 xmlSchemaIDCAugPtr aidc;
19413
19414 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19415 if (idc == NULL)
19416 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019417
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019418#if DEBUG_IDC
19419 {
19420 xmlChar *str = NULL;
19421 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019422 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019423 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19424 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019425 FREE_AND_NULL(str)
19426 }
19427#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019428 if (vctxt->inode->idcMatchers != NULL) {
19429 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19430 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019431 return (-1);
19432 }
19433 do {
19434 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19435 /*
19436 * Since IDCs bubbles are expensive we need to know the
19437 * depth at which the bubbles should stop; this will be
19438 * the depth of the top-most keyref IDC. If no keyref
19439 * references a key/unique IDC, the bubbleDepth will
19440 * be -1, indicating that no bubbles are needed.
19441 */
19442 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19443 if (refIdc != NULL) {
19444 /*
19445 * Lookup the augmented IDC.
19446 */
19447 aidc = vctxt->aidcs;
19448 while (aidc != NULL) {
19449 if (aidc->def == refIdc)
19450 break;
19451 aidc = aidc->next;
19452 }
19453 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019454 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019455 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019456 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019457 return (-1);
19458 }
19459 if ((aidc->bubbleDepth == -1) ||
19460 (vctxt->depth < aidc->bubbleDepth))
19461 aidc->bubbleDepth = vctxt->depth;
19462 }
19463 }
19464 /*
19465 * Lookup the augmented IDC item for the IDC definition.
19466 */
19467 aidc = vctxt->aidcs;
19468 while (aidc != NULL) {
19469 if (aidc->def == idc)
19470 break;
19471 aidc = aidc->next;
19472 }
19473 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019474 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19475 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019476 return (-1);
19477 }
19478 /*
19479 * Create an IDC matcher for every IDC definition.
19480 */
19481 matcher = (xmlSchemaIDCMatcherPtr)
19482 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19483 if (matcher == NULL) {
19484 xmlSchemaVErrMemory(vctxt,
19485 "allocating an IDC matcher", NULL);
19486 return (-1);
19487 }
19488 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19489 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019490 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019491 else
19492 last->next = matcher;
19493 last = matcher;
19494
19495 matcher->type = IDC_MATCHER;
19496 matcher->depth = vctxt->depth;
19497 matcher->aidc = aidc;
19498#if DEBUG_IDC
19499 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19500#endif
19501 /*
19502 * Init the automaton state object.
19503 */
19504 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019505 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019506 return (-1);
19507
19508 idc = idc->next;
19509 } while (idc != NULL);
19510 return (0);
19511}
19512
19513/**
19514 * xmlSchemaBubbleIDCNodeTables:
19515 * @depth: the current tree depth
19516 *
19517 * Merges IDC bindings of an element at @depth into the corresponding IDC
19518 * bindings of its parent element. If a duplicate note-table entry is found,
19519 * both, the parent node-table entry and child entry are discarded from the
19520 * node-table of the parent.
19521 *
19522 * Returns 0 if OK and -1 on internal errors.
19523 */
19524static int
19525xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19526{
19527 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019528 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19529 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019530 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19531 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019532 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019533 int duplTop;
19534
19535 /*
19536 * The node table has the following sections:
19537 *
19538 * O --> old node-table entries (first)
19539 * O
19540 * + --> new node-table entries
19541 * +
19542 * % --> new duplicate node-table entries
19543 * %
19544 * # --> old duplicate node-table entries
19545 * # (last)
19546 *
19547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019548 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019549 if (bind == NULL) {
19550 /* Fine, no table, no bubbles. */
19551 return (0);
19552 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019553
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019554 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19555 /*
19556 * Walk all bindings; create new or add to existing bindings.
19557 * Remove duplicate key-sequences.
19558 */
19559start_binding:
19560 while (bind != NULL) {
19561 /*
19562 * Skip keyref IDCs.
19563 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019564 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19565 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019566 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019567 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019568 /*
19569 * Check if the key/unique IDC table needs to be bubbled.
19570 */
19571 aidc = vctxt->aidcs;
19572 do {
19573 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019574 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019575 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019576 bind = bind->next;
19577 goto start_binding;
19578 }
19579 break;
19580 }
19581 aidc = aidc->next;
19582 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019583
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019584 if (parTable != NULL)
19585 parBind = *parTable;
19586 while (parBind != NULL) {
19587 /*
19588 * Search a matching parent binding for the
19589 * IDC definition.
19590 */
19591 if (parBind->definition == bind->definition) {
19592
19593 /*
19594 * Compare every node-table entry of the child node,
19595 * i.e. the key-sequence within, ...
19596 */
19597 oldNum = parBind->nbNodes; /* Skip newly added items. */
19598 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019599 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019600
19601 for (i = 0; i < bind->nbNodes; i++) {
19602 node = bind->nodeTable[i];
19603 if (node == NULL)
19604 continue;
19605 /*
19606 * ...with every key-sequence of the parent node, already
19607 * evaluated to be a duplicate key-sequence.
19608 */
19609 if (parBind->nbDupls != 0) {
19610 j = bind->nbNodes + newDupls;
19611 while (j < duplTop) {
19612 parNode = parBind->nodeTable[j];
19613 for (k = 0; k < bind->definition->nbFields; k++) {
19614 key = node->keys[k];
19615 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019616 ret = xmlSchemaAreValuesEqual(key->val,
19617 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019618 if (ret == -1) {
19619 /* TODO: Internal error */
19620 return(-1);
19621 } else if (ret == 0)
19622 break;
19623
19624 }
19625 if (ret == 1)
19626 /* Duplicate found. */
19627 break;
19628 j++;
19629 }
19630 if (j != duplTop) {
19631 /* Duplicate found. */
19632 continue;
19633 }
19634 }
19635 /*
19636 * ... and with every key-sequence of the parent node.
19637 */
19638 j = 0;
19639 while (j < oldNum) {
19640 parNode = parBind->nodeTable[j];
19641 /*
19642 * Compare key by key.
19643 */
19644 for (k = 0; k < parBind->definition->nbFields; k++) {
19645 key = node->keys[k];
19646 parKey = parNode->keys[k];
19647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019648 ret = xmlSchemaAreValuesEqual(key->val,
19649 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019650 if (ret == -1) {
19651 /* TODO: Internal error */
19652 } else if (ret == 0)
19653 break;
19654
19655 }
19656 if (ret == 1)
19657 /*
19658 * The key-sequences are equal.
19659 */
19660 break;
19661 j++;
19662 }
19663 if (j != oldNum) {
19664 /*
19665 * Handle duplicates.
19666 */
19667 newDupls++;
19668 oldNum--;
19669 parBind->nbNodes--;
19670 /*
19671 * Move last old item to pos of duplicate.
19672 */
19673 parBind->nodeTable[j] =
19674 parBind->nodeTable[oldNum];
19675
19676 if (parBind->nbNodes != oldNum) {
19677 /*
19678 * If new items exist, move last new item to
19679 * last of old items.
19680 */
19681 parBind->nodeTable[oldNum] =
19682 parBind->nodeTable[parBind->nbNodes];
19683 }
19684 /*
19685 * Move duplicate to last pos of new/old items.
19686 */
19687 parBind->nodeTable[parBind->nbNodes] = parNode;
19688
19689 } else {
19690 /*
19691 * Add the node-table entry (node and key-sequence) of
19692 * the child node to the node table of the parent node.
19693 */
19694 if (parBind->nodeTable == NULL) {
19695 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019696 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019697 if (parBind->nodeTable == NULL) {
19698 xmlSchemaVErrMemory(NULL,
19699 "allocating IDC list of node-table items", NULL);
19700 return(-1);
19701 }
19702 parBind->sizeNodes = 1;
19703 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019704 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019705 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19706 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19707 sizeof(xmlSchemaPSVIIDCNodePtr));
19708 if (parBind->nodeTable == NULL) {
19709 xmlSchemaVErrMemory(NULL,
19710 "re-allocating IDC list of node-table items", NULL);
19711 return(-1);
19712 }
19713 }
19714
19715 /*
19716 * Move first old duplicate to last position
19717 * of old duplicates +1.
19718 */
19719 if (parBind->nbDupls != 0) {
19720 parBind->nodeTable[duplTop] =
19721 parBind->nodeTable[parBind->nbNodes + newDupls];
19722 }
19723 /*
19724 * Move first new duplicate to last position of
19725 * new duplicates +1.
19726 */
19727 if (newDupls != 0) {
19728 parBind->nodeTable[parBind->nbNodes + newDupls] =
19729 parBind->nodeTable[parBind->nbNodes];
19730 }
19731 /*
19732 * Append the new node-table entry to the 'new node-table
19733 * entries' section.
19734 */
19735 parBind->nodeTable[parBind->nbNodes] = node;
19736 parBind->nbNodes++;
19737 duplTop++;
19738 }
19739 }
19740 parBind->nbDupls += newDupls;
19741 break;
19742 }
19743 if (parBind->next == NULL)
19744 lastParBind = parBind;
19745 parBind = parBind->next;
19746 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019747 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019748 /*
19749 * No binding for the IDC was found: create a new one and
19750 * copy all node-tables.
19751 */
19752 parBind = xmlSchemaIDCNewBinding(bind->definition);
19753 if (parBind == NULL)
19754 return(-1);
19755
19756 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19757 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19758 if (parBind->nodeTable == NULL) {
19759 xmlSchemaVErrMemory(NULL,
19760 "allocating an array of IDC node-table items", NULL);
19761 xmlSchemaIDCFreeBinding(parBind);
19762 return(-1);
19763 }
19764 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019765 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019766 memcpy(parBind->nodeTable, bind->nodeTable,
19767 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019768 if (*parTable == NULL)
19769 *parTable = parBind;
19770 else
19771 lastParBind->next = parBind;
19772 }
19773 bind = bind->next;
19774 }
19775 return (0);
19776}
19777
19778/**
19779 * xmlSchemaCheckCVCIDCKeyRef:
19780 * @vctxt: the WXS validation context
19781 * @elemDecl: the element declaration
19782 *
19783 * Check the cvc-idc-keyref constraints.
19784 */
19785static int
19786xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19787{
19788 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19789
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019790 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019791 /*
19792 * Find a keyref.
19793 */
19794 while (refbind != NULL) {
19795 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19796 int i, j, k, res;
19797 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19798 xmlSchemaPSVIIDCKeyPtr refKey, key;
19799
19800 /*
19801 * Find the referred key/unique.
19802 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019803 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019804 do {
19805 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19806 bind->definition)
19807 break;
19808 bind = bind->next;
19809 } while (bind != NULL);
19810
19811 /*
19812 * Search for a matching key-sequences.
19813 */
19814 for (i = 0; i < refbind->nbNodes; i++) {
19815 res = 0;
19816 if (bind != NULL) {
19817 refKeys = refbind->nodeTable[i]->keys;
19818 for (j = 0; j < bind->nbNodes; j++) {
19819 keys = bind->nodeTable[j]->keys;
19820 for (k = 0; k < bind->definition->nbFields; k++) {
19821 refKey = refKeys[k];
19822 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019823 res = xmlSchemaAreValuesEqual(key->val,
19824 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019825 if (res == 0)
19826 break;
19827 else if (res == -1) {
19828 return (-1);
19829 }
19830 }
19831 if (res == 1) {
19832 /*
19833 * Match found.
19834 */
19835 break;
19836 }
19837 }
19838 }
19839 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019840 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019841 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019842 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19843 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019844 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019845 "No match found for key-sequence %s of key "
19846 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019847 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019848 refbind->nodeTable[i]->keys,
19849 refbind->definition->nbFields),
19850 xmlSchemaFormatQName(&strB,
19851 refbind->definition->targetNamespace,
19852 refbind->definition->name));
19853 FREE_AND_NULL(str);
19854 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019855 }
19856 }
19857 }
19858 refbind = refbind->next;
19859 }
19860 return (0);
19861}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019862
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019863/************************************************************************
19864 * *
19865 * XML Reader validation code *
19866 * *
19867 ************************************************************************/
19868
19869static xmlSchemaAttrInfoPtr
19870xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019871{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019872 xmlSchemaAttrInfoPtr iattr;
19873 /*
19874 * Grow/create list of attribute infos.
19875 */
19876 if (vctxt->attrInfos == NULL) {
19877 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19878 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19879 vctxt->sizeAttrInfos = 1;
19880 if (vctxt->attrInfos == NULL) {
19881 xmlSchemaVErrMemory(vctxt,
19882 "allocating attribute info list", NULL);
19883 return (NULL);
19884 }
19885 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19886 vctxt->sizeAttrInfos++;
19887 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19888 xmlRealloc(vctxt->attrInfos,
19889 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19890 if (vctxt->attrInfos == NULL) {
19891 xmlSchemaVErrMemory(vctxt,
19892 "re-allocating attribute info list", NULL);
19893 return (NULL);
19894 }
19895 } else {
19896 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19897 if (iattr->localName != NULL) {
19898 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19899 "attr info not cleared");
19900 return (NULL);
19901 }
19902 iattr->nodeType = XML_ATTRIBUTE_NODE;
19903 return (iattr);
19904 }
19905 /*
19906 * Create an attribute info.
19907 */
19908 iattr = (xmlSchemaAttrInfoPtr)
19909 xmlMalloc(sizeof(xmlSchemaAttrInfo));
19910 if (iattr == NULL) {
19911 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
19912 return (NULL);
19913 }
19914 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
19915 iattr->nodeType = XML_ATTRIBUTE_NODE;
19916 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
19917
19918 return (iattr);
19919}
19920
19921static int
19922xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
19923 xmlNodePtr attrNode,
19924 const xmlChar *localName,
19925 const xmlChar *nsName,
19926 int ownedNames,
19927 xmlChar *value,
19928 int ownedValue)
19929{
19930 xmlSchemaAttrInfoPtr attr;
19931
19932 attr = xmlSchemaGetFreshAttrInfo(vctxt);
19933 if (attr == NULL) {
19934 VERROR_INT("xmlSchemaPushAttribute",
19935 "calling xmlSchemaGetFreshAttrInfo()");
19936 return (-1);
19937 }
19938 attr->node = attrNode;
19939 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
19940 attr->localName = localName;
19941 attr->nsName = nsName;
19942 if (ownedNames)
19943 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
19944 /*
19945 * Evaluate if it's an XSI attribute.
19946 */
19947 if (nsName != NULL) {
19948 if (xmlStrEqual(localName, BAD_CAST "nil")) {
19949 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19950 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
19951 }
19952 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
19953 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19954 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
19955 }
19956 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
19957 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19958 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
19959 }
19960 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
19961 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19962 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
19963 }
19964 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
19965 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
19966 }
19967 }
19968 attr->value = value;
19969 if (ownedValue)
19970 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
19971 if (attr->metaType != 0)
19972 attr->state = XML_SCHEMAS_ATTR_META;
19973 return (0);
19974}
19975
19976static void
19977xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
19978{
19979 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
19980 FREE_AND_NULL(ielem->localName);
19981 FREE_AND_NULL(ielem->nsName);
19982 } else {
19983 ielem->localName = NULL;
19984 ielem->nsName = NULL;
19985 }
19986 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
19987 FREE_AND_NULL(ielem->value);
19988 } else {
19989 ielem->value = NULL;
19990 }
19991 if (ielem->val != NULL) {
19992 xmlSchemaFreeValue(ielem->val);
19993 ielem->val = NULL;
19994 }
19995 if (ielem->idcMatchers != NULL) {
19996 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
19997 ielem->idcMatchers = NULL;
19998 }
19999 if (ielem->idcTable != NULL) {
20000 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20001 ielem->idcTable = NULL;
20002 }
20003 if (ielem->regexCtxt != NULL) {
20004 xmlRegFreeExecCtxt(ielem->regexCtxt);
20005 ielem->regexCtxt = NULL;
20006 }
20007 if (ielem->nsBindings != NULL) {
20008 xmlFree((xmlChar **)ielem->nsBindings);
20009 ielem->nsBindings = NULL;
20010 ielem->nbNsBindings = 0;
20011 ielem->sizeNsBindings = 0;
20012 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020013}
20014
20015/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020016 * xmlSchemaGetFreshElemInfo:
20017 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020018 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020019 * Creates/reuses and initializes the element info item for
20020 * the currect tree depth.
20021 *
20022 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020023 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020024static xmlSchemaNodeInfoPtr
20025xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020026{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020027 xmlSchemaNodeInfoPtr info = NULL;
20028
20029 if (vctxt->depth > vctxt->sizeElemInfos) {
20030 VERROR_INT("xmlSchemaGetFreshElemInfo",
20031 "inconsistent depth encountered");
20032 return (NULL);
20033 }
20034 if (vctxt->elemInfos == NULL) {
20035 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20036 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20037 if (vctxt->elemInfos == NULL) {
20038 xmlSchemaVErrMemory(vctxt,
20039 "allocating the element info array", NULL);
20040 return (NULL);
20041 }
20042 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20043 vctxt->sizeElemInfos = 10;
20044 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20045 int i = vctxt->sizeElemInfos;
20046
20047 vctxt->sizeElemInfos *= 2;
20048 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20049 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20050 sizeof(xmlSchemaNodeInfoPtr));
20051 if (vctxt->elemInfos == NULL) {
20052 xmlSchemaVErrMemory(vctxt,
20053 "re-allocating the element info array", NULL);
20054 return (NULL);
20055 }
20056 /*
20057 * We need the new memory to be NULLed.
20058 * TODO: Use memset instead?
20059 */
20060 for (; i < vctxt->sizeElemInfos; i++)
20061 vctxt->elemInfos[i] = NULL;
20062 } else
20063 info = vctxt->elemInfos[vctxt->depth];
20064
20065 if (info == NULL) {
20066 info = (xmlSchemaNodeInfoPtr)
20067 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20068 if (info == NULL) {
20069 xmlSchemaVErrMemory(vctxt,
20070 "allocating an element info", NULL);
20071 return (NULL);
20072 }
20073 vctxt->elemInfos[vctxt->depth] = info;
20074 } else {
20075 if (info->localName != NULL) {
20076 VERROR_INT("xmlSchemaGetFreshElemInfo",
20077 "elem info has not been cleared");
20078 return (NULL);
20079 }
20080 }
20081 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20082 info->nodeType = XML_ELEMENT_NODE;
20083 info->depth = vctxt->depth;
20084
20085 return (info);
20086}
20087
20088#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20089#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20090#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20091
20092static int
20093xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20094 xmlNodePtr node,
20095 xmlSchemaTypePtr type,
20096 xmlSchemaValType valType,
20097 const xmlChar * value,
20098 xmlSchemaValPtr val,
20099 unsigned long length,
20100 int fireErrors)
20101{
20102 int ret, error = 0;
20103
20104 xmlSchemaTypePtr tmpType;
20105 xmlSchemaFacetLinkPtr facetLink;
20106 xmlSchemaFacetPtr facet;
20107 unsigned long len = 0;
20108 xmlSchemaWhitespaceValueType ws;
20109
20110 /*
20111 * In Libxml2, derived built-in types have currently no explicit facets.
20112 */
20113 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020114 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020115
20116 /*
20117 * NOTE: Do not jump away, if the facetSet of the given type is
20118 * empty: until now, "pattern" and "enumeration" facets of the
20119 * *base types* need to be checked as well.
20120 */
20121 if (type->facetSet == NULL)
20122 goto pattern_and_enum;
20123
20124 if (! VARIETY_ATOMIC(type)) {
20125 if (VARIETY_LIST(type))
20126 goto variety_list;
20127 else
20128 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020129 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020130 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020131 * Whitespace handling is only of importance for string-based
20132 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020133 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020134 tmpType = xmlSchemaGetPrimitiveType(type);
20135 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20136 IS_ANY_SIMPLE_TYPE(tmpType)) {
20137 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20138 } else
20139 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20140 /*
20141 * If the value was not computed (for string or
20142 * anySimpleType based types), then use the provided
20143 * type.
20144 */
20145 if (val == NULL)
20146 valType = valType;
20147 else
20148 valType = xmlSchemaGetValType(val);
20149
20150 ret = 0;
20151 for (facetLink = type->facetSet; facetLink != NULL;
20152 facetLink = facetLink->next) {
20153 /*
20154 * Skip the pattern "whiteSpace": it is used to
20155 * format the character content beforehand.
20156 */
20157 switch (facetLink->facet->type) {
20158 case XML_SCHEMA_FACET_WHITESPACE:
20159 case XML_SCHEMA_FACET_PATTERN:
20160 case XML_SCHEMA_FACET_ENUMERATION:
20161 continue;
20162 case XML_SCHEMA_FACET_LENGTH:
20163 case XML_SCHEMA_FACET_MINLENGTH:
20164 case XML_SCHEMA_FACET_MAXLENGTH:
20165 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20166 valType, value, val, &len, ws);
20167 break;
20168 default:
20169 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20170 valType, value, val, ws);
20171 break;
20172 }
20173 if (ret < 0) {
20174 AERROR_INT("xmlSchemaValidateFacets",
20175 "validating against a atomic type facet");
20176 return (-1);
20177 } else if (ret > 0) {
20178 if (fireErrors)
20179 xmlSchemaFacetErr(actxt, ret, node,
20180 value, len, type, facetLink->facet, NULL, NULL, NULL);
20181 else
20182 return (ret);
20183 if (error == 0)
20184 error = ret;
20185 }
20186 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020188
20189variety_list:
20190 if (! VARIETY_LIST(type))
20191 goto pattern_and_enum;
20192 /*
20193 * "length", "minLength" and "maxLength" of list types.
20194 */
20195 ret = 0;
20196 for (facetLink = type->facetSet; facetLink != NULL;
20197 facetLink = facetLink->next) {
20198
20199 switch (facetLink->facet->type) {
20200 case XML_SCHEMA_FACET_LENGTH:
20201 case XML_SCHEMA_FACET_MINLENGTH:
20202 case XML_SCHEMA_FACET_MAXLENGTH:
20203 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20204 value, length, NULL);
20205 break;
20206 default:
20207 continue;
20208 }
20209 if (ret < 0) {
20210 AERROR_INT("xmlSchemaValidateFacets",
20211 "validating against a list type facet");
20212 return (-1);
20213 } else if (ret > 0) {
20214 if (fireErrors)
20215 xmlSchemaFacetErr(actxt, ret, node,
20216 value, length, type, facetLink->facet, NULL, NULL, NULL);
20217 else
20218 return (ret);
20219 if (error == 0)
20220 error = ret;
20221 }
20222 ret = 0;
20223 }
20224
20225pattern_and_enum:
20226 if (error >= 0) {
20227 int found = 0;
20228 /*
20229 * Process enumerations. Facet values are in the value space
20230 * of the defining type's base type. This seems to be a bug in the
20231 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20232 * Only the first set of enumerations in the ancestor-or-self axis
20233 * is used for validation.
20234 */
20235 ret = 0;
20236 tmpType = type;
20237 do {
20238 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20239 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20240 continue;
20241 found = 1;
20242 ret = xmlSchemaAreValuesEqual(facet->val, val);
20243 if (ret == 1)
20244 break;
20245 else if (ret < 0) {
20246 AERROR_INT("xmlSchemaValidateFacets",
20247 "validating against an enumeration facet");
20248 return (-1);
20249 }
20250 }
20251 if (ret != 0)
20252 break;
20253 tmpType = tmpType->baseType;
20254 } while ((tmpType != NULL) &&
20255 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20256 if (found && (ret == 0)) {
20257 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20258 if (fireErrors) {
20259 xmlSchemaFacetErr(actxt, ret, node,
20260 value, 0, type, NULL, NULL, NULL, NULL);
20261 } else
20262 return (ret);
20263 if (error == 0)
20264 error = ret;
20265 }
20266 }
20267
20268 if (error >= 0) {
20269 int found;
20270 /*
20271 * Process patters. Pattern facets are ORed at type level
20272 * and ANDed if derived. Walk the base type axis.
20273 */
20274 tmpType = type;
20275 facet = NULL;
20276 do {
20277 found = 0;
20278 for (facetLink = tmpType->facetSet; facetLink != NULL;
20279 facetLink = facetLink->next) {
20280 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20281 continue;
20282 found = 1;
20283 /*
20284 * NOTE that for patterns, @value needs to be the
20285 * normalized vaule.
20286 */
20287 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20288 if (ret == 1)
20289 break;
20290 else if (ret < 0) {
20291 AERROR_INT("xmlSchemaValidateFacets",
20292 "validating against a pattern facet");
20293 return (-1);
20294 } else {
20295 /*
20296 * Save the last non-validating facet.
20297 */
20298 facet = facetLink->facet;
20299 }
20300 }
20301 if (found && (ret != 1)) {
20302 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20303 if (fireErrors) {
20304 xmlSchemaFacetErr(actxt, ret, node,
20305 value, 0, type, facet, NULL, NULL, NULL);
20306 } else
20307 return (ret);
20308 if (error == 0)
20309 error = ret;
20310 break;
20311 }
20312 tmpType = tmpType->baseType;
20313 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20314 }
20315
20316 return (error);
20317}
20318
20319static xmlChar *
20320xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20321 const xmlChar *value)
20322{
20323 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20324 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20325 return (xmlSchemaCollapseString(value));
20326 case XML_SCHEMA_WHITESPACE_REPLACE:
20327 return (xmlSchemaWhiteSpaceReplace(value));
20328 default:
20329 return (NULL);
20330 }
20331}
20332
20333static int
20334xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20335 const xmlChar *value,
20336 xmlSchemaValPtr *val,
20337 int valNeeded)
20338{
20339 int ret;
20340 const xmlChar *nsName;
20341 xmlChar *local, *prefix = NULL;
20342
20343 ret = xmlValidateQName(value, 1);
20344 if (ret != 0) {
20345 if (ret == -1) {
20346 VERROR_INT("xmlSchemaValidateQName",
20347 "calling xmlValidateQName()");
20348 return (-1);
20349 }
20350 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20351 }
20352 /*
20353 * NOTE: xmlSplitQName2 will always return a duplicated
20354 * strings.
20355 */
20356 local = xmlSplitQName2(value, &prefix);
20357 if (local == NULL)
20358 local = xmlStrdup(value);
20359 /*
20360 * OPTIMIZE TODO: Use flags for:
20361 * - is there any namespace binding?
20362 * - is there a default namespace?
20363 */
20364 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20365
20366 if (prefix != NULL) {
20367 xmlFree(prefix);
20368 /*
20369 * A namespace must be found if the prefix is
20370 * NOT NULL.
20371 */
20372 if (nsName == NULL) {
20373 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20374 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20375 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20376 "The QName value '%s' has no "
20377 "corresponding namespace declaration in "
20378 "scope", value, NULL);
20379 if (local != NULL)
20380 xmlFree(local);
20381 return (ret);
20382 }
20383 }
20384 if (valNeeded && val) {
20385 if (nsName != NULL)
20386 *val = xmlSchemaNewQNameValue(
20387 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20388 else
20389 *val = xmlSchemaNewQNameValue(NULL,
20390 BAD_CAST local);
20391 } else
20392 xmlFree(local);
20393 return (0);
20394}
20395
20396/*
20397* cvc-simple-type
20398*/
20399static int
20400xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20401 xmlNodePtr node,
20402 xmlSchemaTypePtr type,
20403 const xmlChar *value,
20404 xmlSchemaValPtr *retVal,
20405 int fireErrors,
20406 int normalize,
20407 int isNormalized)
20408{
20409 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20410 xmlSchemaValPtr val = NULL;
20411 xmlSchemaWhitespaceValueType ws;
20412 xmlChar *normValue = NULL;
20413
20414#define NORMALIZE(atype) \
20415 if ((! isNormalized) && \
20416 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20417 normValue = xmlSchemaNormalizeValue(atype, value); \
20418 if (normValue != NULL) \
20419 value = normValue; \
20420 isNormalized = 1; \
20421 }
20422
20423 if ((retVal != NULL) && (*retVal != NULL)) {
20424 xmlSchemaFreeValue(*retVal);
20425 *retVal = NULL;
20426 }
20427 /*
20428 * 3.14.4 Simple Type Definition Validation Rules
20429 * Validation Rule: String Valid
20430 */
20431 /*
20432 * 1 It is schema-valid with respect to that definition as defined
20433 * by Datatype Valid in [XML Schemas: Datatypes].
20434 */
20435 /*
20436 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20437 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20438 * the string must be a ·declared entity name·.
20439 */
20440 /*
20441 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20442 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20443 * then every whitespace-delimited substring of the string must be a ·declared
20444 * entity name·.
20445 */
20446 /*
20447 * 2.3 otherwise no further condition applies.
20448 */
20449 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20450 valNeeded = 1;
20451 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20452 xmlSchemaTypePtr biType; /* The built-in type. */
20453 /*
20454 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20455 * a literal in the ·lexical space· of {base type definition}"
20456 */
20457 /*
20458 * Whitespace-normalize.
20459 */
20460 NORMALIZE(type);
20461 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20462 /*
20463 * Get the built-in type.
20464 */
20465 biType = type->baseType;
20466 while ((biType != NULL) &&
20467 (biType->type != XML_SCHEMA_TYPE_BASIC))
20468 biType = biType->baseType;
20469
20470 if (biType == NULL) {
20471 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20472 "could not get the built-in type");
20473 goto internal_error;
20474 }
20475 } else
20476 biType = type;
20477 /*
20478 * NOTATIONs need to be processed here, since they need
20479 * to lookup in the hashtable of NOTATION declarations of the schema.
20480 */
20481 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20482 switch (biType->builtInType) {
20483 case XML_SCHEMAS_NOTATION:
20484 ret = xmlSchemaValidateNotation(
20485 (xmlSchemaValidCtxtPtr) actxt,
20486 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20487 NULL, value, &val, valNeeded);
20488 break;
20489 case XML_SCHEMAS_QNAME:
20490 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20491 value, &val, valNeeded);
20492 break;
20493 default:
20494 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20495 if (valNeeded)
20496 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20497 value, &val, NULL);
20498 else
20499 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20500 value, NULL, NULL);
20501 break;
20502 }
20503 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20504 switch (biType->builtInType) {
20505 case XML_SCHEMAS_NOTATION:
20506 ret = xmlSchemaValidateNotation(NULL,
20507 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20508 value, &val, valNeeded);
20509 break;
20510 default:
20511 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20512 if (valNeeded)
20513 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20514 value, &val, node);
20515 else
20516 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20517 value, NULL, node);
20518 break;
20519 }
20520 } else {
20521 /*
20522 * Validation via a public API is not implemented yet.
20523 */
20524 TODO
20525 goto internal_error;
20526 }
20527 if (ret != 0) {
20528 if (ret < 0) {
20529 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20530 "validating against a built-in type");
20531 goto internal_error;
20532 }
20533 if (VARIETY_LIST(type))
20534 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20535 else
20536 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20537 }
20538 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20539 /*
20540 * Check facets.
20541 */
20542 ret = xmlSchemaValidateFacets(actxt, node, type,
20543 (xmlSchemaValType) biType->builtInType, value, val,
20544 0, fireErrors);
20545 if (ret != 0) {
20546 if (ret < 0) {
20547 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20548 "validating facets of atomic simple type");
20549 goto internal_error;
20550 }
20551 if (VARIETY_LIST(type))
20552 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20553 else
20554 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20555 }
20556 }
20557 if (fireErrors && (ret > 0))
20558 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20559 } else if (VARIETY_LIST(type)) {
20560
20561 xmlSchemaTypePtr itemType;
20562 const xmlChar *cur, *end;
20563 xmlChar *tmpValue = NULL;
20564 unsigned long len = 0;
20565 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20566 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20567 * of white space separated tokens, each of which ·match·es a literal
20568 * in the ·lexical space· of {item type definition}
20569 */
20570 /*
20571 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20572 * the list type has an enum or pattern facet.
20573 */
20574 NORMALIZE(type);
20575 /*
20576 * VAL TODO: Optimize validation of empty values.
20577 * VAL TODO: We do not have computed values for lists.
20578 */
20579 itemType = GET_LIST_ITEM_TYPE(type);
20580 if (value == NULL)
20581 value = BAD_CAST "";
20582 cur = value;
20583 do {
20584 while (IS_BLANK_CH(*cur))
20585 cur++;
20586 end = cur;
20587 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20588 end++;
20589 if (end == cur)
20590 break;
20591 tmpValue = xmlStrndup(cur, end - cur);
20592 len++;
20593
20594 if (valNeeded)
20595 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20596 tmpValue, &curVal, fireErrors, 0, 1);
20597 else
20598 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20599 tmpValue, NULL, fireErrors, 0, 1);
20600 FREE_AND_NULL(tmpValue);
20601 if (curVal != NULL) {
20602 /*
20603 * Add to list of computed values.
20604 */
20605 if (val == NULL)
20606 val = curVal;
20607 else
20608 xmlSchemaValueAppend(prevVal, curVal);
20609 prevVal = curVal;
20610 curVal = NULL;
20611 }
20612 if (ret != 0) {
20613 if (ret < 0) {
20614 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20615 "validating an item of list simple type");
20616 goto internal_error;
20617 }
20618 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20619 break;
20620 }
20621 cur = end;
20622 } while (*cur != 0);
20623 FREE_AND_NULL(tmpValue);
20624 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20625 /*
20626 * Apply facets (pattern, enumeration).
20627 */
20628 ret = xmlSchemaValidateFacets(actxt, node, type,
20629 XML_SCHEMAS_UNKNOWN, value, val,
20630 len, fireErrors);
20631 if (ret != 0) {
20632 if (ret < 0) {
20633 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20634 "validating facets of list simple type");
20635 goto internal_error;
20636 }
20637 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20638 }
20639 }
20640 if (fireErrors && (ret > 0)) {
20641 /*
20642 * Report the normalized value.
20643 */
20644 normalize = 1;
20645 NORMALIZE(type);
20646 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20647 }
20648 } else if (VARIETY_UNION(type)) {
20649 xmlSchemaTypeLinkPtr memberLink;
20650 /*
20651 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20652 * not apply directly; however, the normalization behavior of ·union·
20653 * types is controlled by the value of whiteSpace on that one of the
20654 * ·memberTypes· against which the ·union· is successfully validated.
20655 *
20656 * This means that the value is normalized by the first validating
20657 * member type, then the facets of the union type are applied. This
20658 * needs changing of the value!
20659 */
20660
20661 /*
20662 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20663 * literal in the ·lexical space· of at least one member of
20664 * {member type definitions}
20665 */
20666 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20667 if (memberLink == NULL) {
20668 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20669 "union simple type has no member types");
20670 goto internal_error;
20671 }
20672 /*
20673 * Always normalize union type values, since we currently
20674 * cannot store the whitespace information with the value
20675 * itself; otherwise a later value-comparison would be
20676 * not possible.
20677 */
20678 while (memberLink != NULL) {
20679 if (valNeeded)
20680 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20681 memberLink->type, value, &val, 0, 1, 0);
20682 else
20683 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20684 memberLink->type, value, NULL, 0, 1, 0);
20685 if (ret <= 0)
20686 break;
20687 memberLink = memberLink->next;
20688 }
20689 if (ret != 0) {
20690 if (ret < 0) {
20691 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20692 "validating members of union simple type");
20693 goto internal_error;
20694 }
20695 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20696 }
20697 /*
20698 * Apply facets (pattern, enumeration).
20699 */
20700 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20701 /*
20702 * The normalization behavior of ·union· types is controlled by
20703 * the value of whiteSpace on that one of the ·memberTypes·
20704 * against which the ·union· is successfully validated.
20705 */
20706 NORMALIZE(memberLink->type);
20707 ret = xmlSchemaValidateFacets(actxt, node, type,
20708 XML_SCHEMAS_UNKNOWN, value, val,
20709 0, fireErrors);
20710 if (ret != 0) {
20711 if (ret < 0) {
20712 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20713 "validating facets of union simple type");
20714 goto internal_error;
20715 }
20716 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20717 }
20718 }
20719 if (fireErrors && (ret > 0))
20720 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20721 }
20722
20723 if (normValue != NULL)
20724 xmlFree(normValue);
20725 if (ret == 0) {
20726 if (retVal != NULL)
20727 *retVal = val;
20728 else if (val != NULL)
20729 xmlSchemaFreeValue(val);
20730 } else if (val != NULL)
20731 xmlSchemaFreeValue(val);
20732 return (ret);
20733internal_error:
20734 if (normValue != NULL)
20735 xmlFree(normValue);
20736 if (val != NULL)
20737 xmlSchemaFreeValue(val);
20738 return (-1);
20739}
20740
20741static int
20742xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20743 const xmlChar *value,
20744 const xmlChar **nsName,
20745 const xmlChar **localName)
20746{
20747 int ret = 0;
20748
20749 if ((nsName == NULL) || (localName == NULL))
20750 return (-1);
20751 *nsName = NULL;
20752 *localName = NULL;
20753
20754 ret = xmlValidateQName(value, 1);
20755 if (ret == -1)
20756 return (-1);
20757 if (ret > 0) {
20758 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20759 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20760 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20761 return (1);
20762 }
20763 {
20764 xmlChar *local = NULL;
20765 xmlChar *prefix;
20766
20767 /*
20768 * NOTE: xmlSplitQName2 will return a duplicated
20769 * string.
20770 */
20771 local = xmlSplitQName2(value, &prefix);
20772 VAL_CREATE_DICT;
20773 if (local == NULL)
20774 *localName = xmlDictLookup(vctxt->dict, value, -1);
20775 else {
20776 *localName = xmlDictLookup(vctxt->dict, local, -1);
20777 xmlFree(local);
20778 }
20779
20780 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20781
20782 if (prefix != NULL) {
20783 xmlFree(prefix);
20784 /*
20785 * A namespace must be found if the prefix is NOT NULL.
20786 */
20787 if (*nsName == NULL) {
20788 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20789 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20790 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20791 "The QName value '%s' has no "
20792 "corresponding namespace declaration in scope",
20793 value, NULL);
20794 return (2);
20795 }
20796 }
20797 }
20798 return (0);
20799}
20800
20801static int
20802xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20803 xmlSchemaAttrInfoPtr iattr,
20804 xmlSchemaTypePtr *localType,
20805 xmlSchemaElementPtr elemDecl)
20806{
20807 int ret = 0;
20808 /*
20809 * cvc-elt (3.3.4) : (4)
20810 * AND
20811 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20812 * (1.2.1.2.1) - (1.2.1.2.4)
20813 * Handle 'xsi:type'.
20814 */
20815 if (localType == NULL)
20816 return (-1);
20817 *localType = NULL;
20818 if (iattr == NULL)
20819 return (0);
20820 else {
20821 const xmlChar *nsName = NULL, *local = NULL;
20822 /*
20823 * TODO: We should report a *warning* that the type was overriden
20824 * by the instance.
20825 */
20826 ACTIVATE_ATTRIBUTE(iattr);
20827 /*
20828 * (cvc-elt) (3.3.4) : (4.1)
20829 * (cvc-assess-elt) (1.2.1.2.2)
20830 */
20831 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20832 &nsName, &local);
20833 if (ret != 0) {
20834 if (ret < 0) {
20835 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20836 "calling xmlSchemaQNameExpand() to validate the "
20837 "attribute 'xsi:type'");
20838 goto internal_error;
20839 }
20840 goto exit;
20841 }
20842 /*
20843 * (cvc-elt) (3.3.4) : (4.2)
20844 * (cvc-assess-elt) (1.2.1.2.3)
20845 */
20846 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20847 if (*localType == NULL) {
20848 xmlChar *str = NULL;
20849
20850 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20851 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20852 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20853 "The QName value '%s' of the xsi:type attribute does not "
20854 "resolve to a type definition",
20855 xmlSchemaFormatQName(&str, nsName, local), NULL);
20856 FREE_AND_NULL(str);
20857 ret = vctxt->err;
20858 goto exit;
20859 }
20860 if (elemDecl != NULL) {
20861 int set = 0;
20862
20863 /*
20864 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20865 * "The ·local type definition· must be validly
20866 * derived from the {type definition} given the union of
20867 * the {disallowed substitutions} and the {type definition}'s
20868 * {prohibited substitutions}, as defined in
20869 * Type Derivation OK (Complex) (§3.4.6)
20870 * (if it is a complex type definition),
20871 * or given {disallowed substitutions} as defined in Type
20872 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20873 * definition)."
20874 *
20875 * {disallowed substitutions}: the "block" on the element decl.
20876 * {prohibited substitutions}: the "block" on the type def.
20877 */
20878 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20879 (elemDecl->subtypes->flags &
20880 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20881 set |= SUBSET_EXTENSION;
20882
20883 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20884 (elemDecl->subtypes->flags &
20885 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20886 set |= SUBSET_RESTRICTION;
20887
20888 if (xmlSchemaCheckCOSDerivedOK(*localType,
20889 elemDecl->subtypes, set) != 0) {
20890 xmlChar *str = NULL;
20891
20892 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20893 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20894 "The type definition '%s', specified by xsi:type, is "
20895 "blocked or not validly derived from the type definition "
20896 "of the element declaration",
20897 xmlSchemaFormatQName(&str,
20898 (*localType)->targetNamespace,
20899 (*localType)->name),
20900 NULL);
20901 FREE_AND_NULL(str);
20902 ret = vctxt->err;
20903 *localType = NULL;
20904 }
20905 }
20906 }
20907exit:
20908 ACTIVATE_ELEM;
20909 return (ret);
20910internal_error:
20911 ACTIVATE_ELEM;
20912 return (-1);
20913}
20914
20915static int
20916xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
20917{
20918 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
20919 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
20920
20921 /*
20922 * cvc-elt (3.3.4) : 1
20923 */
20924 if (elemDecl == NULL) {
20925 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
20926 "No matching declaration available");
20927 return (vctxt->err);
20928 }
20929 /*
20930 * cvc-elt (3.3.4) : 2
20931 */
20932 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20933 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
20934 "The element declaration is abstract");
20935 return (vctxt->err);
20936 }
20937 if (actualType == NULL) {
20938 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
20939 "The type definition is absent");
20940 return (XML_SCHEMAV_CVC_TYPE_1);
20941 }
20942 if (vctxt->nbAttrInfos != 0) {
20943 int ret;
20944 xmlSchemaAttrInfoPtr iattr;
20945 /*
20946 * cvc-elt (3.3.4) : 3
20947 * Handle 'xsi:nil'.
20948 */
20949 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
20950 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
20951 if (iattr) {
20952 ACTIVATE_ATTRIBUTE(iattr);
20953 /*
20954 * Validate the value.
20955 */
20956 ret = xmlSchemaVCheckCVCSimpleType(
20957 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
20958 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20959 iattr->value, &(iattr->val), 1, 0, 0);
20960 ACTIVATE_ELEM;
20961 if (ret < 0) {
20962 VERROR_INT("xmlSchemaValidateElemDecl",
20963 "calling xmlSchemaVCheckCVCSimpleType() to "
20964 "validate the attribute 'xsi:nil'");
20965 return (-1);
20966 }
20967 if (ret == 0) {
20968 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
20969 /*
20970 * cvc-elt (3.3.4) : 3.1
20971 */
20972 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
20973 "The element is not 'nillable'");
20974 /* Does not return an error on purpose. */
20975 } else {
20976 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
20977 /*
20978 * cvc-elt (3.3.4) : 3.2.2
20979 */
20980 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
20981 (elemDecl->value != NULL)) {
20982 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
20983 "The element cannot be 'nilled' because "
20984 "there is a fixed value constraint defined "
20985 "for it");
20986 /* Does not return an error on purpose. */
20987 } else
20988 vctxt->inode->flags |=
20989 XML_SCHEMA_ELEM_INFO_NILLED;
20990 }
20991 }
20992 }
20993 }
20994 /*
20995 * cvc-elt (3.3.4) : 4
20996 * Handle 'xsi:type'.
20997 */
20998 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
20999 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21000 if (iattr) {
21001 xmlSchemaTypePtr localType = NULL;
21002
21003 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21004 elemDecl);
21005 if (ret != 0) {
21006 if (ret == -1) {
21007 VERROR_INT("xmlSchemaValidateElemDecl",
21008 "calling xmlSchemaProcessXSIType() to "
21009 "process the attribute 'xsi:type'");
21010 return (-1);
21011 }
21012 /* Does not return an error on purpose. */
21013 }
21014 if (localType != NULL) {
21015 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21016 actualType = localType;
21017 }
21018 }
21019 }
21020 /*
21021 * IDC: Register identity-constraint XPath matchers.
21022 */
21023 if ((elemDecl->idcs != NULL) &&
21024 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21025 return (-1);
21026 /*
21027 * No actual type definition.
21028 */
21029 if (actualType == NULL) {
21030 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21031 "The type definition is absent");
21032 return (XML_SCHEMAV_CVC_TYPE_1);
21033 }
21034 /*
21035 * Remember the actual type definition.
21036 */
21037 vctxt->inode->typeDef = actualType;
21038
21039 return (0);
21040}
21041
21042static int
21043xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21044{
21045 xmlSchemaAttrInfoPtr iattr;
21046 int ret = 0, i;
21047
21048 /*
21049 * SPEC cvc-type (3.1.1)
21050 * "The attributes of must be empty, excepting those whose namespace
21051 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21052 * whose local name is one of type, nil, schemaLocation or
21053 * noNamespaceSchemaLocation."
21054 */
21055 if (vctxt->nbAttrInfos == 0)
21056 return (0);
21057 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21058 iattr = vctxt->attrInfos[i];
21059 if (! iattr->metaType) {
21060 ACTIVATE_ATTRIBUTE(iattr)
21061 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21062 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21063 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21064 }
21065 }
21066 ACTIVATE_ELEM
21067 return (ret);
21068}
21069
21070/*
21071* Cleanup currently used attribute infos.
21072*/
21073static void
21074xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21075{
21076 int i;
21077 xmlSchemaAttrInfoPtr attr;
21078
21079 if (vctxt->nbAttrInfos == 0)
21080 return;
21081 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21082 attr = vctxt->attrInfos[i];
21083 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21084 if (attr->localName != NULL)
21085 xmlFree((xmlChar *) attr->localName);
21086 if (attr->nsName != NULL)
21087 xmlFree((xmlChar *) attr->nsName);
21088 }
21089 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21090 if (attr->value != NULL)
21091 xmlFree((xmlChar *) attr->value);
21092 }
21093 if (attr->val != NULL) {
21094 xmlSchemaFreeValue(attr->val);
21095 attr->val = NULL;
21096 }
21097 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21098 }
21099 vctxt->nbAttrInfos = 0;
21100}
21101
21102/*
21103* 3.4.4 Complex Type Definition Validation Rules
21104* Element Locally Valid (Complex Type) (cvc-complex-type)
21105* 3.2.4 Attribute Declaration Validation Rules
21106* Validation Rule: Attribute Locally Valid (cvc-attribute)
21107* Attribute Locally Valid (Use) (cvc-au)
21108*
21109* Only "assessed" attribute information items will be visible to
21110* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21111*/
21112static int
21113xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21114{
21115 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21116 xmlSchemaAttributeLinkPtr attrUseLink;
21117 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21118 xmlSchemaAttrInfoPtr attr, tmpAttr;
21119 int i, found, nbAttrs;
21120 int xpathRes = 0, res, wildIDs = 0, fixed;
21121
21122 /*
21123 * SPEC (cvc-attribute)
21124 * (1) "The declaration must not be ·absent· (see Missing
21125 * Sub-components (§5.3) for how this can fail to be
21126 * the case)."
21127 * (2) "Its {type definition} must not be absent."
21128 *
21129 * NOTE (1) + (2): This is not handled here, since we currently do not
21130 * allow validation against schemas which have missing sub-components.
21131 *
21132 * SPEC (cvc-complex-type)
21133 * (3) "For each attribute information item in the element information
21134 * item's [attributes] excepting those whose [namespace name] is
21135 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21136 * [local name] is one of type, nil, schemaLocation or
21137 * noNamespaceSchemaLocation, the appropriate case among the following
21138 * must be true:
21139 *
21140 */
21141 nbAttrs = vctxt->nbAttrInfos;
21142 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21143 attrUseLink = attrUseLink->next) {
21144
21145 found = 0;
21146 attrUse = attrUseLink->attr;
21147 /*
21148 * VAL TODO: Implement a real "attribute use" component.
21149 */
21150 if (attrUse->refDecl != NULL)
21151 attrDecl = attrUse->refDecl;
21152 else
21153 attrDecl = attrUse;
21154 for (i = 0; i < nbAttrs; i++) {
21155 attr = vctxt->attrInfos[i];
21156 /*
21157 * SPEC (cvc-complex-type) (3)
21158 * Skip meta attributes.
21159 */
21160 if (attr->metaType)
21161 continue;
21162 if (attr->localName[0] != attrDecl->name[0])
21163 continue;
21164 if (!xmlStrEqual(attr->localName, attrDecl->name))
21165 continue;
21166 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21167 continue;
21168 found = 1;
21169 /*
21170 * SPEC (cvc-complex-type)
21171 * (3.1) "If there is among the {attribute uses} an attribute
21172 * use with an {attribute declaration} whose {name} matches
21173 * the attribute information item's [local name] and whose
21174 * {target namespace} is identical to the attribute information
21175 * item's [namespace name] (where an ·absent· {target namespace}
21176 * is taken to be identical to a [namespace name] with no value),
21177 * then the attribute information must be ·valid· with respect
21178 * to that attribute use as per Attribute Locally Valid (Use)
21179 * (§3.5.4). In this case the {attribute declaration} of that
21180 * attribute use is the ·context-determined declaration· for the
21181 * attribute information item with respect to Schema-Validity
21182 * Assessment (Attribute) (§3.2.4) and
21183 * Assessment Outcome (Attribute) (§3.2.5).
21184 */
21185 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21186 attr->use = attrUse;
21187 /*
21188 * Context-determined declaration.
21189 */
21190 attr->decl = attrDecl;
21191 attr->typeDef = attrDecl->subtypes;
21192 break;
21193 }
21194
21195 if (found)
21196 continue;
21197
21198 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21199 /*
21200 * Handle non-existent, required attributes.
21201 *
21202 * SPEC (cvc-complex-type)
21203 * (4) "The {attribute declaration} of each attribute use in
21204 * the {attribute uses} whose {required} is true matches one
21205 * of the attribute information items in the element information
21206 * item's [attributes] as per clause 3.1 above."
21207 */
21208 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21209 if (tmpAttr == NULL) {
21210 VERROR_INT(
21211 "xmlSchemaVAttributesComplex",
21212 "calling xmlSchemaGetFreshAttrInfo()");
21213 return (-1);
21214 }
21215 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21216 tmpAttr->use = attrUse;
21217 tmpAttr->decl = attrDecl;
21218 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21219 ((attrUse->defValue != NULL) ||
21220 (attrDecl->defValue != NULL))) {
21221 /*
21222 * Handle non-existent, optional, default/fixed attributes.
21223 */
21224 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21225 if (tmpAttr == NULL) {
21226 VERROR_INT(
21227 "xmlSchemaVAttributesComplex",
21228 "calling xmlSchemaGetFreshAttrInfo()");
21229 return (-1);
21230 }
21231 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21232 tmpAttr->use = attrUse;
21233 tmpAttr->decl = attrDecl;
21234 tmpAttr->typeDef = attrDecl->subtypes;
21235 tmpAttr->localName = attrDecl->name;
21236 tmpAttr->nsName = attrDecl->targetNamespace;
21237 }
21238 }
21239 if (vctxt->nbAttrInfos == 0)
21240 return (0);
21241 /*
21242 * Validate against the wildcard.
21243 */
21244 if (type->attributeWildcard != NULL) {
21245 /*
21246 * SPEC (cvc-complex-type)
21247 * (3.2.1) "There must be an {attribute wildcard}."
21248 */
21249 for (i = 0; i < nbAttrs; i++) {
21250 attr = vctxt->attrInfos[i];
21251 /*
21252 * SPEC (cvc-complex-type) (3)
21253 * Skip meta attributes.
21254 */
21255 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21256 continue;
21257 /*
21258 * SPEC (cvc-complex-type)
21259 * (3.2.2) "The attribute information item must be ·valid· with
21260 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21261 *
21262 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21263 * "... its [namespace name] must be ·valid· with respect to
21264 * the wildcard constraint, as defined in Wildcard allows
21265 * Namespace Name (§3.10.4)."
21266 */
21267 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21268 attr->nsName)) {
21269 /*
21270 * Handle processContents.
21271 *
21272 * SPEC (cvc-wildcard):
21273 * processContents | context-determined declaration:
21274 * "strict" "mustFind"
21275 * "lax" "none"
21276 * "skip" "skip"
21277 */
21278 if (type->attributeWildcard->processContents ==
21279 XML_SCHEMAS_ANY_SKIP) {
21280 /*
21281 * context-determined declaration = "skip"
21282 *
21283 * SPEC PSVI Assessment Outcome (Attribute)
21284 * [validity] = "notKnown"
21285 * [validation attempted] = "none"
21286 */
21287 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21288 continue;
21289 }
21290 /*
21291 * Find an attribute declaration.
21292 */
21293 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21294 attr->localName, attr->nsName);
21295 if (attr->decl != NULL) {
21296 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21297 /*
21298 * SPEC (cvc-complex-type)
21299 * (5) "Let [Definition:] the wild IDs be the set of
21300 * all attribute information item to which clause 3.2
21301 * applied and whose ·validation· resulted in a
21302 * ·context-determined declaration· of mustFind or no
21303 * ·context-determined declaration· at all, and whose
21304 * [local name] and [namespace name] resolve (as
21305 * defined by QName resolution (Instance) (§3.15.4)) to
21306 * an attribute declaration whose {type definition} is
21307 * or is derived from ID. Then all of the following
21308 * must be true:"
21309 */
21310 attr->typeDef = attr->decl->subtypes;
21311 if (xmlSchemaIsDerivedFromBuiltInType(
21312 attr->typeDef, XML_SCHEMAS_ID)) {
21313 /*
21314 * SPEC (5.1) "There must be no more than one
21315 * item in ·wild IDs·."
21316 */
21317 if (wildIDs != 0) {
21318 /* VAL TODO */
21319 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21320 TODO
21321 continue;
21322 }
21323 wildIDs++;
21324 /*
21325 * SPEC (cvc-complex-type)
21326 * (5.2) "If ·wild IDs· is non-empty, there must not
21327 * be any attribute uses among the {attribute uses}
21328 * whose {attribute declaration}'s {type definition}
21329 * is or is derived from ID."
21330 */
21331 for (attrUseLink = type->attributeUses;
21332 attrUseLink != NULL;
21333 attrUseLink = attrUseLink->next) {
21334 if (xmlSchemaIsDerivedFromBuiltInType(
21335 attrUseLink->attr->subtypes,
21336 XML_SCHEMAS_ID)) {
21337 /* VAL TODO */
21338 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21339 TODO
21340 }
21341 }
21342 }
21343 } else if (type->attributeWildcard->processContents ==
21344 XML_SCHEMAS_ANY_LAX) {
21345 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21346 /*
21347 * SPEC PSVI Assessment Outcome (Attribute)
21348 * [validity] = "notKnown"
21349 * [validation attempted] = "none"
21350 */
21351 } else {
21352 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21353 }
21354 }
21355 }
21356 }
21357
21358
21359 if (vctxt->nbAttrInfos == 0)
21360 return (0);
21361
21362 /*
21363 * Validate values, create default attributes, evaluate IDCs.
21364 */
21365 xpathRes = 0;
21366 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21367 attr = vctxt->attrInfos[i];
21368 /*
21369 * VAL TODO: Note that we won't try to resolve IDCs to
21370 * "lax" and "skip" validated attributes. Check what to
21371 * do in this case.
21372 */
21373 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21374 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21375 continue;
21376 /*
21377 * VAL TODO: What to do if the type definition is missing?
21378 */
21379 if (attr->typeDef == NULL) {
21380 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21381 continue;
21382 }
21383
21384 ACTIVATE_ATTRIBUTE(attr);
21385
21386 if (vctxt->xpathStates != NULL) {
21387 /*
21388 * Evaluate IDCs.
21389 */
21390 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21391 XML_ATTRIBUTE_NODE);
21392 if (xpathRes == -1) {
21393 VERROR_INT("xmlSchemaVAttributesComplex",
21394 "calling xmlSchemaXPathEvaluate()");
21395 goto internal_error;
21396 }
21397 }
21398
21399 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21400 /*
21401 * Default/fixed attributes.
21402 */
21403 if (xpathRes) {
21404 if (attr->use->defValue == NULL) {
21405 attr->value = (xmlChar *) attr->use->defValue;
21406 attr->val = attr->use->defVal;
21407 } else {
21408 attr->value = (xmlChar *) attr->decl->defValue;
21409 attr->val = attr->decl->defVal;
21410 }
21411 /*
21412 * IDCs will consume the precomputed default value,
21413 * so we need to clone it.
21414 */
21415 if (attr->val == NULL) {
21416 VERROR_INT("xmlSchemaVAttributesComplex",
21417 "default/fixed value on an attribute use was "
21418 "not precomputed");
21419 goto internal_error;
21420 }
21421 attr->val = xmlSchemaCopyValue(attr->val);
21422 if (attr->val == NULL) {
21423 VERROR_INT("xmlSchemaVAttributesComplex",
21424 "calling xmlSchemaCopyValue()");
21425 goto internal_error;
21426 }
21427 }
21428 /*
21429 * PSVI: Add the default attribute to the current element.
21430 * VAL TODO: Should we use the *normalized* value? This currently
21431 * uses the *initial* value.
21432 */
21433 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21434 (attr->node != NULL) && (attr->node->doc != NULL)) {
21435 xmlChar *normValue;
21436 const xmlChar *value;
21437
21438 value = attr->value;
21439 /*
21440 * Normalize the value.
21441 */
21442 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21443 attr->value);
21444 if (normValue != NULL)
21445 value = BAD_CAST normValue;
21446
21447 if (attr->nsName == NULL) {
21448 if (xmlNewProp(attr->node->parent,
21449 attr->localName, value) == NULL) {
21450 VERROR_INT("xmlSchemaVAttributesComplex",
21451 "callling xmlNewProp()");
21452 if (normValue != NULL)
21453 xmlFree(normValue);
21454 goto internal_error;
21455 }
21456 } else {
21457 xmlNsPtr ns;
21458
21459 ns = xmlSearchNsByHref(attr->node->doc,
21460 attr->node->parent, attr->nsName);
21461 if (ns == NULL) {
21462 xmlChar prefix[12];
21463 int counter = 0;
21464
21465 /*
21466 * Create a namespace declaration on the validation
21467 * root node if no namespace declaration is in scope.
21468 */
21469 do {
21470 snprintf((char *) prefix, 12, "p%d", counter++);
21471 ns = xmlSearchNs(attr->node->doc,
21472 attr->node->parent, BAD_CAST prefix);
21473 if (counter > 1000) {
21474 VERROR_INT(
21475 "xmlSchemaVAttributesComplex",
21476 "could not compute a ns prefix for a "
21477 "default/fixed attribute");
21478 if (normValue != NULL)
21479 xmlFree(normValue);
21480 goto internal_error;
21481 }
21482 } while (ns != NULL);
21483 ns = xmlNewNs(vctxt->validationRoot,
21484 attr->nsName, BAD_CAST prefix);
21485 }
21486 xmlNewNsProp(attr->node->parent, ns,
21487 attr->localName, value);
21488 }
21489 if (normValue != NULL)
21490 xmlFree(normValue);
21491 }
21492 /*
21493 * Go directly to IDC evaluation.
21494 */
21495 goto eval_idcs;
21496 }
21497 /*
21498 * Validate the value.
21499 */
21500 if (vctxt->value != NULL) {
21501 /*
21502 * Free last computed value; just for safety reasons.
21503 */
21504 xmlSchemaFreeValue(vctxt->value);
21505 vctxt->value = NULL;
21506 }
21507 /*
21508 * Note that the attribute *use* can be unavailable, if
21509 * the attribute was a wild attribute.
21510 */
21511 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21512 ((attr->use != NULL) &&
21513 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21514 fixed = 1;
21515 else
21516 fixed = 0;
21517 /*
21518 * SPEC (cvc-attribute)
21519 * (3) "The item's ·normalized value· must be locally ·valid·
21520 * with respect to that {type definition} as per
21521 * String Valid (§3.14.4)."
21522 *
21523 * VAL TODO: Do we already have the
21524 * "normalized attribute value" here?
21525 */
21526 if (xpathRes || fixed) {
21527 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21528 /*
21529 * Request a computed value.
21530 */
21531 res = xmlSchemaVCheckCVCSimpleType(
21532 (xmlSchemaAbstractCtxtPtr) vctxt,
21533 attr->node, attr->typeDef, attr->value, &(attr->val),
21534 1, 1, 0);
21535 } else {
21536 res = xmlSchemaVCheckCVCSimpleType(
21537 (xmlSchemaAbstractCtxtPtr) vctxt,
21538 attr->node, attr->typeDef, attr->value, NULL,
21539 1, 0, 0);
21540 }
21541
21542 if (res != 0) {
21543 if (res == -1) {
21544 VERROR_INT("xmlSchemaVAttributesComplex",
21545 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21546 goto internal_error;
21547 }
21548 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21549 /*
21550 * SPEC PSVI Assessment Outcome (Attribute)
21551 * [validity] = "invalid"
21552 */
21553 goto eval_idcs;
21554 }
21555
21556 if (fixed) {
21557 int ws;
21558 /*
21559 * SPEC Attribute Locally Valid (Use) (cvc-au)
21560 * "For an attribute information item to be·valid·
21561 * with respect to an attribute use its *normalized*
21562 * value· must match the *canonical* lexical
21563 * representation of the attribute use's {value
21564 * constraint}value, if it is present and fixed."
21565 *
21566 * VAL TODO: The requirement for the *canonical* value
21567 * will be removed in XML Schema 1.1.
21568 */
21569 /*
21570 * SPEC Attribute Locally Valid (cvc-attribute)
21571 * (4) "The item's *actual* value· must match the *value* of
21572 * the {value constraint}, if it is present and fixed."
21573 */
21574 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21575 if (attr->val == NULL) {
21576 /* VAL TODO: A value was not precomputed. */
21577 TODO
21578 goto eval_idcs;
21579 }
21580 if ((attr->use != NULL) &&
21581 (attr->use->defValue != NULL)) {
21582 if (attr->use->defVal == NULL) {
21583 /* VAL TODO: A default value was not precomputed. */
21584 TODO
21585 goto eval_idcs;
21586 }
21587 attr->vcValue = attr->use->defValue;
21588 /*
21589 if (xmlSchemaCompareValuesWhtsp(attr->val,
21590 (xmlSchemaWhitespaceValueType) ws,
21591 attr->use->defVal,
21592 (xmlSchemaWhitespaceValueType) ws) != 0) {
21593 */
21594 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21595 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21596 } else {
21597 if (attrDecl->defVal == NULL) {
21598 /* VAL TODO: A default value was not precomputed. */
21599 TODO
21600 goto eval_idcs;
21601 }
21602 attr->vcValue = attrDecl->defValue;
21603 /*
21604 if (xmlSchemaCompareValuesWhtsp(attr->val,
21605 (xmlSchemaWhitespaceValueType) ws,
21606 attrDecl->defVal,
21607 (xmlSchemaWhitespaceValueType) ws) != 0) {
21608 */
21609 if (! xmlSchemaAreValuesEqual(attr->val, attrDecl->defVal))
21610 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21611 }
21612 /*
21613 * [validity] = "valid"
21614 */
21615 }
21616eval_idcs:
21617 /*
21618 * Evaluate IDCs.
21619 */
21620 if (xpathRes) {
21621 if (xmlSchemaXPathProcessHistory(vctxt,
21622 vctxt->depth +1) == -1) {
21623 VERROR_INT("xmlSchemaVAttributesComplex",
21624 "calling xmlSchemaXPathEvaluate()");
21625 goto internal_error;
21626 }
21627 }
21628 }
21629
21630 /*
21631 * Report errors.
21632 */
21633 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21634 attr = vctxt->attrInfos[i];
21635 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21636 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21637 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21638 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21639 continue;
21640 ACTIVATE_ATTRIBUTE(attr);
21641 switch (attr->state) {
21642 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21643 xmlChar *str = NULL;
21644 ACTIVATE_ELEM;
21645 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21646 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21647 "The attribute '%s' is required but missing",
21648 xmlSchemaFormatQName(&str,
21649 attr->decl->targetNamespace,
21650 attr->decl->name),
21651 NULL);
21652 FREE_AND_NULL(str)
21653 break;
21654 }
21655 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21656 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21657 "The type definition is absent");
21658 break;
21659 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21660 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21661 XML_SCHEMAV_CVC_AU, NULL, NULL,
21662 "The value '%s' does not match the fixed "
21663 "value constraint '%s'",
21664 attr->value, attr->vcValue);
21665 break;
21666 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21667 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21668 "No matching global attribute declaration available, but "
21669 "demanded by the strict wildcard");
21670 break;
21671 case XML_SCHEMAS_ATTR_UNKNOWN:
21672 if (attr->metaType)
21673 break;
21674 /*
21675 * MAYBE VAL TODO: One might report different error messages
21676 * for the following errors.
21677 */
21678 if (type->attributeWildcard == NULL) {
21679 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21680 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21681 } else {
21682 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21683 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21684 }
21685 break;
21686 default:
21687 break;
21688 }
21689 }
21690
21691 ACTIVATE_ELEM;
21692 return (0);
21693internal_error:
21694 ACTIVATE_ELEM;
21695 return (-1);
21696}
21697
21698static int
21699xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21700 int *skip)
21701{
21702 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21703 /*
21704 * The namespace of the element was already identified to be
21705 * matching the wildcard.
21706 */
21707 if ((skip == NULL) || (wild == NULL) ||
21708 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21709 VERROR_INT("xmlSchemaValidateElemWildcard",
21710 "bad arguments");
21711 return (-1);
21712 }
21713 *skip = 0;
21714 if (wild->negNsSet != NULL) {
21715 /*
21716 * URGENT VAL TODO: Fix the content model to reject
21717 * "##other" wildcards.
21718 */
21719 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21720 vctxt->inode->nsName) != 0) {
21721 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21722 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21723 /*
21724 * VAL TODO: Workaround possible *only* if minOccurs and
21725 * maxOccurs are 1.
21726 */
21727 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21728 /* VAL TODO: error code? */
21729 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21730 (xmlSchemaTypePtr) wild,
21731 "This element is not accepted by the wildcard",
21732 0, 0, NULL);
21733 vctxt->skipDepth = vctxt->depth;
21734 if ((pinode->flags &
21735 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21736 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21737 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21738 return (XML_SCHEMAV_ELEMENT_CONTENT);
21739 }
21740 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21741 *skip = 1;
21742 return (0);
21743 }
21744 vctxt->inode->typeDef =
21745 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21746 return (0);
21747 }
21748 }
21749 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21750 /*
21751 * URGENT VAL TODO: Either we need to position the stream to the
21752 * next sibling, or walk the whole subtree.
21753 */
21754 *skip = 1;
21755 return (0);
21756 }
21757 {
21758 xmlSchemaElementPtr decl = NULL;
21759
21760 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21761 vctxt->inode->localName, vctxt->inode->nsName,
21762 NULL);
21763 if (decl != NULL) {
21764 vctxt->inode->decl = decl;
21765 return (0);
21766 }
21767 }
21768 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21769 /* VAL TODO: Change to proper error code. */
21770 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21771 "No matching global element declaration available, but "
21772 "demanded by the strict wildcard");
21773 return (vctxt->err);
21774 }
21775 if (vctxt->nbAttrInfos != 0) {
21776 xmlSchemaAttrInfoPtr iattr;
21777 /*
21778 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21779 * (1.2.1.2.1) - (1.2.1.2.3 )
21780 *
21781 * Use the xsi:type attribute for the type definition.
21782 */
21783 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21784 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21785 if (iattr != NULL) {
21786 if (xmlSchemaProcessXSIType(vctxt, iattr,
21787 &(vctxt->inode->typeDef), NULL) == -1) {
21788 VERROR_INT("xmlSchemaValidateElemWildcard",
21789 "calling xmlSchemaProcessXSIType() to "
21790 "process the attribute 'xsi:nil'");
21791 return (-1);
21792 }
21793 /*
21794 * Don't return an error on purpose.
21795 */
21796 return (0);
21797 }
21798 }
21799 /*
21800 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21801 *
21802 * Fallback to "anyType".
21803 */
21804 vctxt->inode->typeDef =
21805 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21806 return (0);
21807}
21808
21809/*
21810* xmlSchemaCheckCOSValidDefault:
21811*
21812* This will be called if: not nilled, no content and a default/fixed
21813* value is provided.
21814*/
21815
21816static int
21817xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21818 const xmlChar *value,
21819 xmlSchemaValPtr *val)
21820{
21821 int ret = 0;
21822 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21823
21824 /*
21825 * cos-valid-default:
21826 * Schema Component Constraint: Element Default Valid (Immediate)
21827 * For a string to be a valid default with respect to a type
21828 * definition the appropriate case among the following must be true:
21829 */
21830 if IS_COMPLEX_TYPE(inode->typeDef) {
21831 /*
21832 * Complex type.
21833 *
21834 * SPEC (2.1) "its {content type} must be a simple type definition
21835 * or mixed."
21836 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21837 * type}'s particle must be ·emptiable· as defined by
21838 * Particle Emptiable (§3.9.6)."
21839 */
21840 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21841 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21842 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21843 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21844 /* NOTE that this covers (2.2.2) as well. */
21845 VERROR(ret, NULL,
21846 "For a string to be a valid default, the type definition "
21847 "must be a simple type or a complex type with simple content "
21848 "or mixed content and a particle emptiable");
21849 return(ret);
21850 }
21851 }
21852 /*
21853 * 1 If the type definition is a simple type definition, then the string
21854 * must be ·valid· with respect to that definition as defined by String
21855 * Valid (§3.14.4).
21856 *
21857 * AND
21858 *
21859 * 2.2.1 If the {content type} is a simple type definition, then the
21860 * string must be ·valid· with respect to that simple type definition
21861 * as defined by String Valid (§3.14.4).
21862 */
21863 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21864
21865 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21866 NULL, inode->typeDef, value, val, 1, 1, 0);
21867
21868 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21869
21870 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21871 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21872 }
21873 if (ret < 0) {
21874 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21875 "calling xmlSchemaVCheckCVCSimpleType()");
21876 }
21877 return (ret);
21878}
21879
21880static void
21881xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21882 const xmlChar * name ATTRIBUTE_UNUSED,
21883 xmlSchemaElementPtr item,
21884 xmlSchemaNodeInfoPtr inode)
21885{
21886 inode->decl = item;
21887#ifdef DEBUG_CONTENT
21888 {
21889 xmlChar *str = NULL;
21890
21891 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21892 xmlGenericError(xmlGenericErrorContext,
21893 "AUTOMATON callback for '%s' [declaration]\n",
21894 xmlSchemaFormatQName(&str,
21895 inode->localName, inode->nsName));
21896 } else {
21897 xmlGenericError(xmlGenericErrorContext,
21898 "AUTOMATON callback for '%s' [wildcard]\n",
21899 xmlSchemaFormatQName(&str,
21900 inode->localName, inode->nsName));
21901
21902 }
21903 FREE_AND_NULL(str)
21904 }
21905#endif
21906}
21907
21908static int
21909xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
21910{
21911 vctxt->depth++;
21912 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
21913 if (vctxt->inode == NULL) {
21914 VERROR_INT("xmlSchemaValidatorPushElem",
21915 "calling xmlSchemaGetFreshElemInfo()");
21916 return (-1);
21917 }
21918 vctxt->nbAttrInfos = 0;
21919 return (0);
21920}
21921
21922static int
21923xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
21924 xmlSchemaNodeInfoPtr inode,
21925 xmlSchemaTypePtr type,
21926 const xmlChar *value)
21927{
21928 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
21929 return (xmlSchemaVCheckCVCSimpleType(
21930 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21931 type, value, &(inode->val), 1, 1, 0));
21932 else
21933 return (xmlSchemaVCheckCVCSimpleType(
21934 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21935 type, value, NULL, 1, 0, 0));
21936}
21937
21938
21939
21940/*
21941* Process END of element.
21942*/
21943static int
21944xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
21945{
21946 int ret = 0;
21947 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21948
21949 if (vctxt->nbAttrInfos != 0)
21950 xmlSchemaClearAttrInfos(vctxt);
21951 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
21952 /*
21953 * This element was not expected;
21954 * we will not validate child elements of broken parents.
21955 * Skip validation of all content of the parent.
21956 */
21957 vctxt->skipDepth = vctxt->depth -1;
21958 goto end_elem;
21959 }
21960 if ((inode->typeDef == NULL) ||
21961 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
21962 /*
21963 * The type definition might be missing if the element was
21964 * error prone.
21965 */
21966 goto end_elem;
21967 }
21968 /*
21969 * Check the content model.
21970 */
21971 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
21972 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
21973
21974 /*
21975 * Workaround for "anyType".
21976 */
21977 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
21978 goto character_content;
21979
21980 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
21981 xmlChar *values[10];
21982 int terminal, nbval = 10, nbneg;
21983
21984 if (inode->regexCtxt == NULL) {
21985 /*
21986 * Create the regex context.
21987 */
21988 inode->regexCtxt =
21989 xmlRegNewExecCtxt(inode->typeDef->contModel,
21990 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
21991 vctxt);
21992 if (inode->regexCtxt == NULL) {
21993 VERROR_INT("xmlSchemaValidatorPopElem",
21994 "failed to create a regex context");
21995 goto internal_error;
21996 }
21997#ifdef DEBUG_AUTOMATA
21998 xmlGenericError(xmlGenericErrorContext,
21999 "AUTOMATON create on '%s'\n", inode->localName);
22000#endif
22001 }
22002 /*
22003 * Get hold of the still expected content, since a further
22004 * call to xmlRegExecPushString() will loose this information.
22005 */
22006 xmlRegExecNextValues(inode->regexCtxt,
22007 &nbval, &nbneg, &values[0], &terminal);
22008 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22009 if (ret <= 0) {
22010 /*
22011 * Still missing something.
22012 */
22013 ret = 1;
22014 inode->flags |=
22015 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22016 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22017 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22018 "Missing child element(s)",
22019 nbval, nbneg, values);
22020#ifdef DEBUG_AUTOMATA
22021 xmlGenericError(xmlGenericErrorContext,
22022 "AUTOMATON missing ERROR on '%s'\n",
22023 inode->localName);
22024#endif
22025 } else {
22026 /*
22027 * Content model is satisfied.
22028 */
22029 ret = 0;
22030#ifdef DEBUG_AUTOMATA
22031 xmlGenericError(xmlGenericErrorContext,
22032 "AUTOMATON succeeded on '%s'\n",
22033 inode->localName);
22034#endif
22035 }
22036
22037 }
22038 }
22039 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22040 goto end_elem;
22041
22042character_content:
22043
22044 if (vctxt->value != NULL) {
22045 xmlSchemaFreeValue(vctxt->value);
22046 vctxt->value = NULL;
22047 }
22048 /*
22049 * Check character content.
22050 */
22051 if (inode->decl == NULL) {
22052 /*
22053 * Speedup if no declaration exists.
22054 */
22055 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22056 ret = xmlSchemaVCheckINodeDataType(vctxt,
22057 inode, inode->typeDef, inode->value);
22058 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22059 ret = xmlSchemaVCheckINodeDataType(vctxt,
22060 inode, inode->typeDef->contentTypeDef,
22061 inode->value);
22062 }
22063 if (ret < 0) {
22064 VERROR_INT("xmlSchemaValidatorPopElem",
22065 "calling xmlSchemaVCheckCVCSimpleType()");
22066 goto internal_error;
22067 }
22068 goto end_elem;
22069 }
22070 /*
22071 * cvc-elt (3.3.4) : 5
22072 * The appropriate case among the following must be true:
22073 */
22074 /*
22075 * cvc-elt (3.3.4) : 5.1
22076 * If the declaration has a {value constraint},
22077 * the item has neither element nor character [children] and
22078 * clause 3.2 has not applied, then all of the following must be true:
22079 */
22080 if ((inode->decl->value != NULL) &&
22081 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22082 (! INODE_NILLED(inode))) {
22083 /*
22084 * cvc-elt (3.3.4) : 5.1.1
22085 * If the ·actual type definition· is a ·local type definition·
22086 * then the canonical lexical representation of the {value constraint}
22087 * value must be a valid default for the ·actual type definition· as
22088 * defined in Element Default Valid (Immediate) (§3.3.6).
22089 */
22090 /*
22091 * NOTE: 'local' above means types aquired by xsi:type.
22092 * NOTE: Although the *canonical* value is stated, it is not
22093 * relevant if canonical or not. Additionally XML Schema 1.1
22094 * will removed this requirement as well.
22095 */
22096 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22097
22098 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22099 inode->decl->value, &(inode->val));
22100 if (ret != 0) {
22101 if (ret < 0) {
22102 VERROR_INT("xmlSchemaValidatorPopElem",
22103 "calling xmlSchemaCheckCOSValidDefault()");
22104 goto internal_error;
22105 }
22106 goto end_elem;
22107 }
22108 /*
22109 * Stop here, to avoid redundant validation of the value
22110 * (see following).
22111 */
22112 goto default_psvi;
22113 }
22114 /*
22115 * cvc-elt (3.3.4) : 5.1.2
22116 * The element information item with the canonical lexical
22117 * representation of the {value constraint} value used as its
22118 * ·normalized value· must be ·valid· with respect to the
22119 * ·actual type definition· as defined by Element Locally Valid (Type)
22120 * (§3.3.4).
22121 */
22122 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22123 ret = xmlSchemaVCheckINodeDataType(vctxt,
22124 inode, inode->typeDef, inode->decl->value);
22125 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22126 ret = xmlSchemaVCheckINodeDataType(vctxt,
22127 inode, inode->typeDef->contentTypeDef,
22128 inode->decl->value);
22129 }
22130 if (ret != 0) {
22131 if (ret < 0) {
22132 VERROR_INT("xmlSchemaValidatorPopElem",
22133 "calling xmlSchemaVCheckCVCSimpleType()");
22134 goto internal_error;
22135 }
22136 goto end_elem;
22137 }
22138
22139default_psvi:
22140 /*
22141 * PSVI: Create a text node on the instance element.
22142 */
22143 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22144 (inode->node != NULL)) {
22145 xmlNodePtr textChild;
22146 xmlChar *normValue;
22147 /*
22148 * VAL TODO: Normalize the value.
22149 */
22150 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22151 inode->decl->value);
22152 if (normValue != NULL) {
22153 textChild = xmlNewText(BAD_CAST normValue);
22154 xmlFree(normValue);
22155 } else
22156 textChild = xmlNewText(inode->decl->value);
22157 if (textChild == NULL) {
22158 VERROR_INT("xmlSchemaValidatorPopElem",
22159 "calling xmlNewText()");
22160 goto internal_error;
22161 } else
22162 xmlAddChild(inode->node, textChild);
22163 }
22164
22165 } else if (! INODE_NILLED(inode)) {
22166 /*
22167 * 5.2.1 The element information item must be ·valid· with respect
22168 * to the ·actual type definition· as defined by Element Locally
22169 * Valid (Type) (§3.3.4).
22170 */
22171 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22172 /*
22173 * SPEC (cvc-type) (3.1)
22174 * "If the type definition is a simple type definition, ..."
22175 * (3.1.3) "If clause 3.2 of Element Locally Valid
22176 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22177 * must be ·valid· with respect to the type definition as defined
22178 * by String Valid (§3.14.4).
22179 */
22180 ret = xmlSchemaVCheckINodeDataType(vctxt,
22181 inode, inode->typeDef, inode->value);
22182 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22183 /*
22184 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22185 * definition, then the element information item must be
22186 * ·valid· with respect to the type definition as per
22187 * Element Locally Valid (Complex Type) (§3.4.4);"
22188 *
22189 * SPEC (cvc-complex-type) (2.2)
22190 * "If the {content type} is a simple type definition, ...
22191 * the ·normalized value· of the element information item is
22192 * ·valid· with respect to that simple type definition as
22193 * defined by String Valid (§3.14.4)."
22194 */
22195 ret = xmlSchemaVCheckINodeDataType(vctxt,
22196 inode, inode->typeDef->contentTypeDef, inode->value);
22197 }
22198 if (ret != 0) {
22199 if (ret < 0) {
22200 VERROR_INT("xmlSchemaValidatorPopElem",
22201 "calling xmlSchemaVCheckCVCSimpleType()");
22202 goto internal_error;
22203 }
22204 goto end_elem;
22205 }
22206 /*
22207 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22208 * not applied, all of the following must be true:
22209 */
22210 if ((inode->decl->value != NULL) &&
22211 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22212
22213 /*
22214 * TODO: We will need a computed value, when comparison is
22215 * done on computed values.
22216 */
22217 /*
22218 * 5.2.2.1 The element information item must have no element
22219 * information item [children].
22220 */
22221 if (inode->flags &
22222 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22223 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22224 VERROR(ret, NULL,
22225 "The content must not containt element nodes since "
22226 "there is a fixed value constraint");
22227 goto end_elem;
22228 } else {
22229 /*
22230 * 5.2.2.2 The appropriate case among the following must
22231 * be true:
22232 */
22233 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22234 /*
22235 * 5.2.2.2.1 If the {content type} of the ·actual type
22236 * definition· is mixed, then the *initial value* of the
22237 * item must match the canonical lexical representation
22238 * of the {value constraint} value.
22239 *
22240 * ... the *initial value* of an element information
22241 * item is the string composed of, in order, the
22242 * [character code] of each character information item in
22243 * the [children] of that element information item.
22244 */
22245 if (! xmlStrEqual(inode->value, inode->decl->value)){
22246 /*
22247 * VAL TODO: Report invalid & expected values as well.
22248 * VAL TODO: Implement the canonical stuff.
22249 */
22250 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22251 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22252 ret, NULL, NULL,
22253 "The initial value '%s' does not match the fixed "
22254 "value constraint '%s'",
22255 inode->value, inode->decl->value);
22256 goto end_elem;
22257 }
22258 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22259 /*
22260 * 5.2.2.2.2 If the {content type} of the ·actual type
22261 * definition· is a simple type definition, then the
22262 * *actual value* of the item must match the canonical
22263 * lexical representation of the {value constraint} value.
22264 */
22265 /*
22266 * VAL TODO: *actual value* is the normalized value, impl.
22267 * this.
22268 * VAL TODO: Report invalid & expected values as well.
22269 * VAL TODO: Implement a comparison with the computed values.
22270 */
22271 if (! xmlStrEqual(inode->value,
22272 inode->decl->value)) {
22273 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22274 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22275 ret, NULL, NULL,
22276 "The actual value '%s' does not match the fixed "
22277 "value constraint '%s'",
22278 inode->value,
22279 inode->decl->value);
22280 goto end_elem;
22281 }
22282 }
22283 }
22284 }
22285 }
22286
22287end_elem:
22288 if (vctxt->depth < 0) {
22289 /* TODO: raise error? */
22290 return (0);
22291 }
22292 if (vctxt->depth == vctxt->skipDepth)
22293 vctxt->skipDepth = -1;
22294 /*
22295 * Evaluate the history of XPath state objects.
22296 */
22297 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22298 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022299 /*
22300 * TODO: 6 The element information item must be ·valid· with respect to each of
22301 * the {identity-constraint definitions} as per Identity-constraint
22302 * Satisfied (§3.11.4).
22303 */
22304 /*
22305 * Validate IDC keyrefs.
22306 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022307 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22308 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022309 /*
22310 * Merge/free the IDC table.
22311 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022312 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022313#ifdef DEBUG_IDC
22314 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022315 inode->nsName,
22316 inode->localName,
22317 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022318#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022319 if (vctxt->depth > 0) {
22320 /*
22321 * Merge the IDC node table with the table of the parent node.
22322 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022323 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22324 goto internal_error;
22325 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022326 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022327 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022328 * Clear the current ielem.
22329 * VAL TODO: Don't free the PSVI IDC tables if they are
22330 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022331 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022332 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022333 /*
22334 * Skip further processing if we are on the validation root.
22335 */
22336 if (vctxt->depth == 0) {
22337 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022338 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022339 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022340 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022341 /*
22342 * Reset the bubbleDepth if needed.
22343 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022344 if (vctxt->aidcs != NULL) {
22345 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22346 do {
22347 if (aidc->bubbleDepth == vctxt->depth) {
22348 /*
22349 * A bubbleDepth of a key/unique IDC matches the current
22350 * depth, this means that we are leaving the scope of the
22351 * top-most keyref IDC.
22352 */
22353 aidc->bubbleDepth = -1;
22354 }
22355 aidc = aidc->next;
22356 } while (aidc != NULL);
22357 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022358 vctxt->depth--;
22359 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022360 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022361 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022362 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22363 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022364 return (ret);
22365
22366internal_error:
22367 vctxt->err = -1;
22368 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022369}
22370
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022371/*
22372* 3.4.4 Complex Type Definition Validation Rules
22373* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22374*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022375static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022376xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022377{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022378 xmlSchemaNodeInfoPtr pielem;
22379 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022380 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022381
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022382 if (vctxt->depth <= 0) {
22383 VERROR_INT("xmlSchemaValidateChildElem",
22384 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022385 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022386 }
22387 pielem = vctxt->elemInfos[vctxt->depth -1];
22388 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22389 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022390 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022391 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022392 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022393 if (INODE_NILLED(pielem)) {
22394 /*
22395 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22396 */
22397 ACTIVATE_PARENT_ELEM;
22398 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22399 VERROR(ret, NULL,
22400 "Neither character nor element content is allowed, "
22401 "because the element was 'nilled'");
22402 ACTIVATE_ELEM;
22403 goto unexpected_elem;
22404 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022405
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022406 ptype = pielem->typeDef;
22407
22408 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22409 /*
22410 * Workaround for "anyType": we have currently no content model
22411 * assigned for "anyType", so handle it explicitely.
22412 * "anyType" has an unbounded, lax "any" wildcard.
22413 */
22414 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22415 vctxt->inode->localName,
22416 vctxt->inode->nsName);
22417
22418 if (vctxt->inode->decl == NULL) {
22419 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022420 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022421 * Process "xsi:type".
22422 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022424 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22425 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22426 if (iattr != NULL) {
22427 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22428 &(vctxt->inode->typeDef), NULL);
22429 if (ret != 0) {
22430 if (ret == -1) {
22431 VERROR_INT("xmlSchemaValidateChildElem",
22432 "calling xmlSchemaProcessXSIType() to "
22433 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022434 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022435 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022436 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022437 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022438 } else {
22439 /*
22440 * Fallback to "anyType".
22441 *
22442 * SPEC (cvc-assess-elt)
22443 * "If the item cannot be ·strictly assessed·, [...]
22444 * an element information item's schema validity may be laxly
22445 * assessed if its ·context-determined declaration· is not
22446 * skip by ·validating· with respect to the ·ur-type
22447 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22448 */
22449 vctxt->inode->typeDef =
22450 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022451 }
22452 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022453 return (0);
22454 }
22455
22456 switch (ptype->contentType) {
22457 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022458 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022459 * SPEC (2.1) "If the {content type} is empty, then the
22460 * element information item has no character or element
22461 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022462 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022463 ACTIVATE_PARENT_ELEM
22464 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22465 VERROR(ret, NULL,
22466 "Element content is not allowed, "
22467 "because the content type is empty");
22468 ACTIVATE_ELEM
22469 goto unexpected_elem;
22470 break;
22471
22472 case XML_SCHEMA_CONTENT_MIXED:
22473 case XML_SCHEMA_CONTENT_ELEMENTS: {
22474 xmlRegExecCtxtPtr regexCtxt;
22475 xmlChar *values[10];
22476 int terminal, nbval = 10, nbneg;
22477
22478 /* VAL TODO: Optimized "anyType" validation.*/
22479
22480 if (ptype->contModel == NULL) {
22481 VERROR_INT("xmlSchemaValidateChildElem",
22482 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022483 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022485 /*
22486 * Safety belf for evaluation if the cont. model was already
22487 * examined to be invalid.
22488 */
22489 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22490 VERROR_INT("xmlSchemaValidateChildElem",
22491 "validating elem, but elem content is already invalid");
22492 return (-1);
22493 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022494
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022495 regexCtxt = pielem->regexCtxt;
22496 if (regexCtxt == NULL) {
22497 /*
22498 * Create the regex context.
22499 */
22500 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22501 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22502 vctxt);
22503 if (regexCtxt == NULL) {
22504 VERROR_INT("xmlSchemaValidateChildElem",
22505 "failed to create a regex context");
22506 return (-1);
22507 }
22508 pielem->regexCtxt = regexCtxt;
22509#ifdef DEBUG_AUTOMATA
22510 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22511 pielem->localName);
22512#endif
22513 }
22514
22515 /*
22516 * SPEC (2.4) "If the {content type} is element-only or mixed,
22517 * then the sequence of the element information item's
22518 * element information item [children], if any, taken in
22519 * order, is ·valid· with respect to the {content type}'s
22520 * particle, as defined in Element Sequence Locally Valid
22521 * (Particle) (§3.9.4)."
22522 */
22523 ret = xmlRegExecPushString2(regexCtxt,
22524 vctxt->inode->localName,
22525 vctxt->inode->nsName,
22526 vctxt->inode);
22527#ifdef DEBUG_AUTOMATA
22528 if (ret < 0)
22529 xmlGenericError(xmlGenericErrorContext,
22530 "AUTOMATON push ERROR for '%s' on '%s'\n",
22531 vctxt->inode->localName, pielem->localName);
22532 else
22533 xmlGenericError(xmlGenericErrorContext,
22534 "AUTOMATON push OK for '%s' on '%s'\n",
22535 vctxt->inode->localName, pielem->localName);
22536#endif
22537 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22538 VERROR_INT("xmlSchemaValidateChildElem",
22539 "calling xmlRegExecPushString2()");
22540 return (-1);
22541 }
22542 if (ret < 0) {
22543 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22544 &values[0], &terminal);
22545 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22546 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22547 "This element is not expected",
22548 nbval, nbneg, values);
22549 ret = vctxt->err;
22550 goto unexpected_elem;
22551 } else
22552 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022553 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022554 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022555 case XML_SCHEMA_CONTENT_SIMPLE:
22556 case XML_SCHEMA_CONTENT_BASIC:
22557 ACTIVATE_PARENT_ELEM
22558 if (IS_COMPLEX_TYPE(ptype)) {
22559 /*
22560 * SPEC (cvc-complex-type) (2.2)
22561 * "If the {content type} is a simple type definition, then
22562 * the element information item has no element information
22563 * item [children], ..."
22564 */
22565 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22566 VERROR(ret, NULL, "Element content is not allowed, "
22567 "because the content type is a simple type definition");
22568 } else {
22569 /*
22570 * SPEC (cvc-type) (3.1.2) "The element information item must
22571 * have no element information item [children]."
22572 */
22573 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22574 VERROR(ret, NULL, "Element content is not allowed, "
22575 "because the type definition is simple");
22576 }
22577 ACTIVATE_ELEM
22578 ret = vctxt->err;
22579 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022580 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022581
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022582 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022583 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022584 }
22585 return (ret);
22586unexpected_elem:
22587 /*
22588 * Pop this element and set the skipDepth to skip
22589 * all further content of the parent element.
22590 */
22591 vctxt->skipDepth = vctxt->depth;
22592 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22593 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22594 return (ret);
22595}
22596
22597#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22598#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22599#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22600
22601static int
22602xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22603 int nodeType, const xmlChar *value, int len,
22604 int mode, int *consumed)
22605{
22606 /*
22607 * Unfortunately we have to duplicate the text sometimes.
22608 * OPTIMIZE: Maybe we could skip it, if:
22609 * 1. content type is simple
22610 * 2. whitespace is "collapse"
22611 * 3. it consists of whitespace only
22612 *
22613 * Process character content.
22614 */
22615 if (consumed != NULL)
22616 *consumed = 0;
22617 if (INODE_NILLED(vctxt->inode)) {
22618 /*
22619 * SPEC cvc-elt (3.3.4 - 3.2.1)
22620 * "The element information item must have no character or
22621 * element information item [children]."
22622 */
22623 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22624 "Neither character nor element content is allowed "
22625 "because the element is 'nilled'");
22626 return (vctxt->err);
22627 }
22628 /*
22629 * SPEC (2.1) "If the {content type} is empty, then the
22630 * element information item has no character or element
22631 * information item [children]."
22632 */
22633 if (vctxt->inode->typeDef->contentType ==
22634 XML_SCHEMA_CONTENT_EMPTY) {
22635 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22636 "Character content is not allowed, "
22637 "because the content type is empty");
22638 return (vctxt->err);
22639 }
22640
22641 if (vctxt->inode->typeDef->contentType ==
22642 XML_SCHEMA_CONTENT_ELEMENTS) {
22643 if ((nodeType != XML_TEXT_NODE) ||
22644 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22645 /*
22646 * SPEC cvc-complex-type (2.3)
22647 * "If the {content type} is element-only, then the
22648 * element information item has no character information
22649 * item [children] other than those whose [character
22650 * code] is defined as a white space in [XML 1.0 (Second
22651 * Edition)]."
22652 */
22653 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22654 "Character content other than whitespace is not allowed "
22655 "because the content type is 'element-only'");
22656 return (vctxt->err);
22657 }
22658 return (0);
22659 }
22660
22661 if ((value == NULL) || (value[0] == 0))
22662 return (0);
22663 /*
22664 * Save the value.
22665 * NOTE that even if the content type is *mixed*, we need the
22666 * *initial value* for default/fixed value constraints.
22667 */
22668 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22669 ((vctxt->inode->decl == NULL) ||
22670 (vctxt->inode->decl->value == NULL)))
22671 return (0);
22672
22673 if (vctxt->inode->value == NULL) {
22674 /*
22675 * Set the value.
22676 */
22677 switch (mode) {
22678 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22679 /*
22680 * When working on a tree.
22681 */
22682 vctxt->inode->value = value;
22683 break;
22684 case XML_SCHEMA_PUSH_TEXT_CREATED:
22685 /*
22686 * When working with the reader.
22687 * The value will be freed by the element info.
22688 */
22689 vctxt->inode->value = value;
22690 if (consumed != NULL)
22691 *consumed = 1;
22692 vctxt->inode->flags |=
22693 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22694 break;
22695 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22696 /*
22697 * When working with SAX.
22698 * The value will be freed by the element info.
22699 */
22700 if (len != -1)
22701 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22702 else
22703 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22704 vctxt->inode->flags |=
22705 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22706 break;
22707 default:
22708 break;
22709 }
22710 } else {
22711 /*
22712 * Concat the value.
22713 */
22714 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
22715 vctxt->inode->value =
22716 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, -1);
22717 } else {
22718 vctxt->inode->value =
22719 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, -1);
22720 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22721 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022723
22724 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022725}
22726
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022727static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022728xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022729{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022730 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022731
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022732 if ((vctxt->skipDepth != -1) &&
22733 (vctxt->depth >= vctxt->skipDepth)) {
22734 VERROR_INT("xmlSchemaValidateElem",
22735 "in skip-state");
22736 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022737 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022738 if (vctxt->xsiAssemble) {
22739 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22740 goto internal_error;
22741 }
22742 if (vctxt->depth > 0) {
22743 /*
22744 * Validate this element against the content model
22745 * of the parent.
22746 */
22747 ret = xmlSchemaValidateChildElem(vctxt);
22748 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022749 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022750 VERROR_INT("xmlSchemaValidateElem",
22751 "calling xmlSchemaStreamValidateChildElement()");
22752 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022753 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022754 goto exit;
22755 }
22756 if (vctxt->depth == vctxt->skipDepth)
22757 goto exit;
22758 if ((vctxt->inode->decl == NULL) &&
22759 (vctxt->inode->typeDef == NULL)) {
22760 VERROR_INT("xmlSchemaValidateElem",
22761 "the child element was valid but neither the "
22762 "declaration nor the type was set");
22763 goto internal_error;
22764 }
22765 } else {
22766 /*
22767 * Get the declaration of the validation root.
22768 */
22769 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22770 vctxt->inode->localName,
22771 vctxt->inode->nsName);
22772 if (vctxt->inode->decl == NULL) {
22773 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
22774 "No matching global declaration available "
22775 "for the validation root");
22776 ret = vctxt->err;
22777 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022778 }
22779 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022780
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022781 if (vctxt->inode->decl == NULL)
22782 goto type_validation;
22783
22784 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22785 int skip;
22786 /*
22787 * Wildcards.
22788 */
22789 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22790 if (ret != 0) {
22791 if (ret < 0) {
22792 VERROR_INT("xmlSchemaValidateElem",
22793 "calling xmlSchemaValidateElemWildcard()");
22794 goto internal_error;
22795 }
22796 goto exit;
22797 }
22798 if (skip) {
22799 vctxt->skipDepth = vctxt->depth;
22800 goto exit;
22801 }
22802 /*
22803 * The declaration might be set by the wildcard validation,
22804 * when the processContents is "lax" or "strict".
22805 */
22806 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22807 /*
22808 * Clear the "decl" field to not confuse further processing.
22809 */
22810 vctxt->inode->decl = NULL;
22811 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022812 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022813 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022814 /*
22815 * Validate against the declaration.
22816 */
22817 ret = xmlSchemaValidateElemDecl(vctxt);
22818 if (ret != 0) {
22819 if (ret < 0) {
22820 VERROR_INT("xmlSchemaValidateElem",
22821 "calling xmlSchemaValidateElemDecl()");
22822 goto internal_error;
22823 }
22824 goto exit;
22825 }
22826type_validation:
22827
22828 if (vctxt->inode->typeDef == NULL) {
22829 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22830 ret = XML_SCHEMAV_CVC_TYPE_1;
22831 VERROR(ret, NULL,
22832 "The type definition is absent");
22833 goto exit;
22834 }
22835 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22836 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22837 ret = XML_SCHEMAV_CVC_TYPE_2;
22838 VERROR(ret, NULL,
22839 "The type definition is abstract");
22840 goto exit;
22841 }
22842 /*
22843 * Evaluate IDCs. Do it here, since new matchers are registered
22844 * during validation against the declaration. This must be done
22845 * _before_ attribute validation.
22846 */
22847 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22848 if (ret == -1) {
22849 VERROR_INT("xmlSchemaValidateElem",
22850 "calling xmlSchemaXPathEvaluate()");
22851 goto internal_error;
22852 }
22853 /*
22854 * Validate attributes.
22855 */
22856 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22857 if ((vctxt->nbAttrInfos != 0) ||
22858 (vctxt->inode->typeDef->attributeUses != NULL)) {
22859
22860 ret = xmlSchemaVAttributesComplex(vctxt);
22861 }
22862 } else if (vctxt->nbAttrInfos != 0) {
22863
22864 ret = xmlSchemaVAttributesSimple(vctxt);
22865 }
22866 /*
22867 * Clear registered attributes.
22868 */
22869 if (vctxt->nbAttrInfos != 0)
22870 xmlSchemaClearAttrInfos(vctxt);
22871 if (ret == -1) {
22872 VERROR_INT("xmlSchemaValidateElem",
22873 "calling attributes validation");
22874 goto internal_error;
22875 }
22876 /*
22877 * Don't return an error if attributes are invalid on purpose.
22878 */
22879 ret = 0;
22880
22881exit:
22882 if (ret != 0)
22883 vctxt->skipDepth = vctxt->depth;
22884 return (ret);
22885internal_error:
22886 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022887}
22888
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022889#ifdef XML_SCHEMA_READER_ENABLED
22890static int
22891xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022892{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022893 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22894 int depth, nodeType, ret = 0, consumed;
22895 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022896
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022897 vctxt->depth = -1;
22898 ret = xmlTextReaderRead(vctxt->reader);
22899 /*
22900 * Move to the document element.
22901 */
22902 while (ret == 1) {
22903 nodeType = xmlTextReaderNodeType(vctxt->reader);
22904 if (nodeType == XML_ELEMENT_NODE)
22905 goto root_found;
22906 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022907 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022908 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022909
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022910root_found:
22911
22912 do {
22913 depth = xmlTextReaderDepth(vctxt->reader);
22914 nodeType = xmlTextReaderNodeType(vctxt->reader);
22915
22916 if (nodeType == XML_ELEMENT_NODE) {
22917
22918 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
22919 VERROR_INT("xmlSchemaVReaderWalk",
22920 "calling xmlSchemaValidatorPushElem()");
22921 goto internal_error;
22922 }
22923 ielem = vctxt->inode;
22924 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
22925 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
22926 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
22927 /*
22928 * Is the element empty?
22929 */
22930 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
22931 if (ret == -1) {
22932 VERROR_INT("xmlSchemaVReaderWalk",
22933 "calling xmlTextReaderIsEmptyElement()");
22934 goto internal_error;
22935 }
22936 if (ret) {
22937 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
22938 }
22939 /*
22940 * Register attributes.
22941 */
22942 vctxt->nbAttrInfos = 0;
22943 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
22944 if (ret == -1) {
22945 VERROR_INT("xmlSchemaVReaderWalk",
22946 "calling xmlTextReaderMoveToFirstAttribute()");
22947 goto internal_error;
22948 }
22949 if (ret == 1) {
22950 do {
22951 /*
22952 * VAL TODO: How do we know that the reader works on a
22953 * node tree, to be able to pass a node here?
22954 */
22955 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
22956 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
22957 xmlTextReaderNamespaceUri(vctxt->reader), 1,
22958 xmlTextReaderValue(vctxt->reader), 1) == -1) {
22959
22960 VERROR_INT("xmlSchemaVReaderWalk",
22961 "calling xmlSchemaValidatorPushAttribute()");
22962 goto internal_error;
22963 }
22964 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
22965 if (ret == -1) {
22966 VERROR_INT("xmlSchemaVReaderWalk",
22967 "calling xmlTextReaderMoveToFirstAttribute()");
22968 goto internal_error;
22969 }
22970 } while (ret == 1);
22971 /*
22972 * Back to element position.
22973 */
22974 ret = xmlTextReaderMoveToElement(vctxt->reader);
22975 if (ret == -1) {
22976 VERROR_INT("xmlSchemaVReaderWalk",
22977 "calling xmlTextReaderMoveToElement()");
22978 goto internal_error;
22979 }
22980 }
22981 /*
22982 * Validate the element.
22983 */
22984 ret= xmlSchemaValidateElem(vctxt);
22985 if (ret != 0) {
22986 if (ret == -1) {
22987 VERROR_INT("xmlSchemaVReaderWalk",
22988 "calling xmlSchemaValidateElem()");
22989 goto internal_error;
22990 }
22991 goto exit;
22992 }
22993 if (vctxt->depth == vctxt->skipDepth) {
22994 int curDepth;
22995 /*
22996 * Skip all content.
22997 */
22998 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
22999 ret = xmlTextReaderRead(vctxt->reader);
23000 curDepth = xmlTextReaderDepth(vctxt->reader);
23001 while ((ret == 1) && (curDepth != depth)) {
23002 ret = xmlTextReaderRead(vctxt->reader);
23003 curDepth = xmlTextReaderDepth(vctxt->reader);
23004 }
23005 if (ret < 0) {
23006 /*
23007 * VAL TODO: A reader error occured; what to do here?
23008 */
23009 ret = 1;
23010 goto exit;
23011 }
23012 }
23013 goto leave_elem;
23014 }
23015 /*
23016 * READER VAL TODO: Is an END_ELEM really never called
23017 * if the elem is empty?
23018 */
23019 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23020 goto leave_elem;
23021 } else if (nodeType == END_ELEM) {
23022 /*
23023 * Process END of element.
23024 */
23025leave_elem:
23026 ret = xmlSchemaValidatorPopElem(vctxt);
23027 if (ret != 0) {
23028 if (ret < 0) {
23029 VERROR_INT("xmlSchemaVReaderWalk",
23030 "calling xmlSchemaValidatorPopElem()");
23031 goto internal_error;
23032 }
23033 goto exit;
23034 }
23035 if (vctxt->depth >= 0)
23036 ielem = vctxt->inode;
23037 else
23038 ielem = NULL;
23039 } else if ((nodeType == XML_TEXT_NODE) ||
23040 (nodeType == XML_CDATA_SECTION_NODE) ||
23041 (nodeType == WHTSP) ||
23042 (nodeType == SIGN_WHTSP)) {
23043 /*
23044 * Process character content.
23045 */
23046 xmlChar *value;
23047
23048 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23049 nodeType = XML_TEXT_NODE;
23050
23051 value = xmlTextReaderValue(vctxt->reader);
23052 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23053 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23054 if (! consumed)
23055 xmlFree(value);
23056 if (ret == -1) {
23057 VERROR_INT("xmlSchemaVReaderWalk",
23058 "calling xmlSchemaVPushText()");
23059 goto internal_error;
23060 }
23061 } else if ((nodeType == XML_ENTITY_NODE) ||
23062 (nodeType == XML_ENTITY_REF_NODE)) {
23063 /*
23064 * VAL TODO: What to do with entities?
23065 */
23066 TODO
23067 }
23068 /*
23069 * Read next node.
23070 */
23071 ret = xmlTextReaderRead(vctxt->reader);
23072 } while (ret == 1);
23073
23074exit:
23075 return (ret);
23076internal_error:
23077 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023078}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023079#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023080
23081/************************************************************************
23082 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023083 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023084 * *
23085 ************************************************************************/
23086
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023087#ifdef XML_SCHEMA_SAX_ENABLED
23088/*
23089* Process text content.
23090*/
23091static void
23092xmlSchemaSAXHandleText(void *ctx,
23093 const xmlChar * ch,
23094 int len)
23095{
23096 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23097
23098 if (vctxt->depth < 0)
23099 return;
23100 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23101 return;
23102 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23103 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23104 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23105 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23106 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23107 "calling xmlSchemaVPushText()");
23108 vctxt->err = -1;
23109 xmlStopParser(vctxt->parserCtxt);
23110 }
23111}
23112
23113/*
23114* Process CDATA content.
23115*/
23116static void
23117xmlSchemaSAXHandleCDataSection(void *ctx,
23118 const xmlChar * ch,
23119 int len)
23120{
23121 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23122
23123 if (vctxt->depth < 0)
23124 return;
23125 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23126 return;
23127 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23128 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23129 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23130 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23131 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23132 "calling xmlSchemaVPushText()");
23133 vctxt->err = -1;
23134 xmlStopParser(vctxt->parserCtxt);
23135 }
23136}
23137
23138static void
23139xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23140 const xmlChar * name ATTRIBUTE_UNUSED)
23141{
23142 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23143
23144 if (vctxt->depth < 0)
23145 return;
23146 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23147 return;
23148 /* SAX VAL TODO: What to do here? */
23149 TODO
23150}
23151
23152static void
23153xmlSchemaSAXHandleStartElementNs(void *ctx,
23154 const xmlChar * localname,
23155 const xmlChar * prefix ATTRIBUTE_UNUSED,
23156 const xmlChar * URI,
23157 int nb_namespaces,
23158 const xmlChar ** namespaces,
23159 int nb_attributes,
23160 int nb_defaulted ATTRIBUTE_UNUSED,
23161 const xmlChar ** attributes)
23162{
23163 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23164 int ret;
23165 xmlSchemaNodeInfoPtr ielem;
23166 int i, j;
23167
23168 /*
23169 * SAX VAL TODO: What to do with nb_defaulted?
23170 */
23171 /*
23172 * Skip elements if inside a "skip" wildcard.
23173 */
23174 if ((vctxt->skipDepth != -1) && (vctxt->depth > vctxt->skipDepth))
23175 return;
23176 /*
23177 * Push the element.
23178 */
23179 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23180 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23181 "calling xmlSchemaValidatorPushElem()");
23182 goto internal_error;
23183 }
23184 ielem = vctxt->inode;
23185 ielem->localName = localname;
23186 ielem->nsName = URI;
23187 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23188 /*
23189 * Register namespaces on the elem info.
23190 */
23191 if (nb_namespaces != 0) {
23192 /*
23193 * Although the parser builds its own namespace list,
23194 * we have no access to it, so we'll use an own one.
23195 */
23196 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23197 /*
23198 * Store prefix and namespace name.
23199 */
23200 if (ielem->nsBindings == NULL) {
23201 ielem->nsBindings =
23202 (const xmlChar **) xmlMalloc(10 *
23203 sizeof(const xmlChar *));
23204 if (ielem->nsBindings == NULL) {
23205 xmlSchemaVErrMemory(vctxt,
23206 "allocating namespace bindings for SAX validation",
23207 NULL);
23208 goto internal_error;
23209 }
23210 ielem->nbNsBindings = 0;
23211 ielem->sizeNsBindings = 5;
23212 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23213 ielem->sizeNsBindings *= 2;
23214 ielem->nsBindings =
23215 (const xmlChar **) xmlRealloc(
23216 (void *) ielem->nsBindings,
23217 ielem->nbNsBindings * 2 * sizeof(const xmlChar *));
23218 if (ielem->nsBindings == NULL) {
23219 xmlSchemaVErrMemory(vctxt,
23220 "re-allocating namespace bindings for SAX validation",
23221 NULL);
23222 goto internal_error;
23223 }
23224 }
23225
23226 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23227 if (namespaces[j+1][0] == 0) {
23228 /*
23229 * Handle xmlns="".
23230 */
23231 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23232 } else
23233 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23234 namespaces[j+1];
23235 ielem->nbNsBindings++;
23236 }
23237 }
23238 /*
23239 * Register attributes.
23240 * SAX VAL TODO: We are not adding namespace declaration
23241 * attributes yet.
23242 */
23243 if (nb_attributes != 0) {
23244 xmlChar *value;
23245
23246 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23247 /*
23248 * Duplicate the value.
23249 */
23250 value = xmlStrndup(attributes[j+3],
23251 attributes[j+4] - attributes[j+3]);
23252 ret = xmlSchemaValidatorPushAttribute(vctxt,
23253 NULL, attributes[j], attributes[j+2], 0,
23254 value, 1);
23255 if (ret == -1) {
23256 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23257 "calling xmlSchemaValidatorPushAttribute()");
23258 goto internal_error;
23259 }
23260 }
23261 }
23262 /*
23263 * Validate the element.
23264 */
23265 ret = xmlSchemaValidateElem(vctxt);
23266 if (ret != 0) {
23267 if (ret == -1) {
23268 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23269 "calling xmlSchemaValidateElem()");
23270 goto internal_error;
23271 }
23272 goto exit;
23273 }
23274
23275exit:
23276 return;
23277internal_error:
23278 vctxt->err = -1;
23279 xmlStopParser(vctxt->parserCtxt);
23280 return;
23281}
23282
23283static void
23284xmlSchemaSAXHandleEndElementNs(void *ctx,
23285 const xmlChar * localname ATTRIBUTE_UNUSED,
23286 const xmlChar * prefix ATTRIBUTE_UNUSED,
23287 const xmlChar * URI ATTRIBUTE_UNUSED)
23288{
23289 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23290 int res;
23291
23292 /*
23293 * Skip elements if inside a "skip" wildcard.
23294 */
23295 if (vctxt->skipDepth != -1) {
23296 if (vctxt->depth > vctxt->skipDepth) {
23297 vctxt->depth--;
23298 return;
23299 } else
23300 vctxt->skipDepth = -1;
23301 }
23302 /*
23303 * SAX VAL TODO: Just a temporary check.
23304 */
23305 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23306 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23307 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23308 "elem pop mismatch");
23309 }
23310 res = xmlSchemaValidatorPopElem(vctxt);
23311 if (res != 0) {
23312 if (res < 0) {
23313 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23314 "calling xmlSchemaValidatorPopElem()");
23315 goto internal_error;
23316 }
23317 goto exit;
23318 }
23319exit:
23320 return;
23321internal_error:
23322 vctxt->err = -1;
23323 xmlStopParser(vctxt->parserCtxt);
23324 return;
23325}
23326#endif
23327
Daniel Veillard4255d502002-04-16 15:50:10 +000023328/************************************************************************
23329 * *
23330 * Validation interfaces *
23331 * *
23332 ************************************************************************/
23333
23334/**
23335 * xmlSchemaNewValidCtxt:
23336 * @schema: a precompiled XML Schemas
23337 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023338 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023339 *
23340 * Returns the validation context or NULL in case of error
23341 */
23342xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023343xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23344{
Daniel Veillard4255d502002-04-16 15:50:10 +000023345 xmlSchemaValidCtxtPtr ret;
23346
23347 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23348 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023349 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023350 return (NULL);
23351 }
23352 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023353 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23354 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023355 return (ret);
23356}
23357
23358/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023359 * xmlSchemaClearValidCtxt:
23360 * @ctxt: the schema validation context
23361 *
23362 * Free the resources associated to the schema validation context;
23363 * leaves some fields alive intended for reuse of the context.
23364 */
23365static void
23366xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23367{
23368 if (vctxt == NULL)
23369 return;
23370
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023371 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023372 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023373 vctxt->doc = NULL;
23374 vctxt->reader = NULL;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023375 if (vctxt->value != NULL) {
23376 xmlSchemaFreeValue(vctxt->value);
23377 vctxt->value = NULL;
23378 }
23379 /*
23380 * Augmented IDC information.
23381 */
23382 if (vctxt->aidcs != NULL) {
23383 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23384 do {
23385 next = cur->next;
23386 xmlFree(cur);
23387 cur = next;
23388 } while (cur != NULL);
23389 vctxt->aidcs = NULL;
23390 }
23391 if (vctxt->idcNodes != NULL) {
23392 int i;
23393 xmlSchemaPSVIIDCNodePtr item;
23394
23395 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023396 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023397 xmlFree(item->keys);
23398 xmlFree(item);
23399 }
23400 xmlFree(vctxt->idcNodes);
23401 vctxt->idcNodes = NULL;
23402 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023403 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023404 * Note that we won't delete the XPath state pool here.
23405 */
23406 if (vctxt->xpathStates != NULL) {
23407 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23408 vctxt->xpathStates = NULL;
23409 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023410 /*
23411 * Attribute info.
23412 */
23413 if (vctxt->nbAttrInfos != 0) {
23414 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023415 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023416 /*
23417 * Element info.
23418 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023419 if (vctxt->elemInfos != NULL) {
23420 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023421 xmlSchemaNodeInfoPtr ei;
23422
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023423 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023424 ei = vctxt->elemInfos[i];
23425 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023426 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023427 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023428 }
23429 }
23430}
23431
23432/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023433 * xmlSchemaFreeValidCtxt:
23434 * @ctxt: the schema validation context
23435 *
23436 * Free the resources associated to the schema validation context
23437 */
23438void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023439xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23440{
Daniel Veillard4255d502002-04-16 15:50:10 +000023441 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023442 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023443 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023444 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023445 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023446 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023447 if (ctxt->idcNodes != NULL) {
23448 int i;
23449 xmlSchemaPSVIIDCNodePtr item;
23450
23451 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023452 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023453 xmlFree(item->keys);
23454 xmlFree(item);
23455 }
23456 xmlFree(ctxt->idcNodes);
23457 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023458 if (ctxt->idcKeys != NULL) {
23459 int i;
23460 for (i = 0; i < ctxt->nbIdcKeys; i++)
23461 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23462 xmlFree(ctxt->idcKeys);
23463 }
23464
23465 if (ctxt->xpathStates != NULL)
23466 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23467 if (ctxt->xpathStatePool != NULL)
23468 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23469
23470 /*
23471 * Augmented IDC information.
23472 */
23473 if (ctxt->aidcs != NULL) {
23474 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23475 do {
23476 next = cur->next;
23477 xmlFree(cur);
23478 cur = next;
23479 } while (cur != NULL);
23480 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023481 if (ctxt->attrInfos != NULL) {
23482 int i;
23483 xmlSchemaAttrInfoPtr attr;
23484
23485 /* Just a paranoid call to the cleanup. */
23486 if (ctxt->nbAttrInfos != 0)
23487 xmlSchemaClearAttrInfos(ctxt);
23488 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23489 attr = ctxt->attrInfos[i];
23490 xmlFree(attr);
23491 }
23492 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023493 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023494 if (ctxt->elemInfos != NULL) {
23495 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023496 xmlSchemaNodeInfoPtr ei;
23497
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023498 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023499 ei = ctxt->elemInfos[i];
23500 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023501 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023502 xmlSchemaClearElemInfo(ei);
23503 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023504 }
23505 xmlFree(ctxt->elemInfos);
23506 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023507 if (ctxt->dict != NULL)
23508 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023509 xmlFree(ctxt);
23510}
23511
23512/**
23513 * xmlSchemaSetValidErrors:
23514 * @ctxt: a schema validation context
23515 * @err: the error function
23516 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023517 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023518 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023519 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023520 */
23521void
23522xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023523 xmlSchemaValidityErrorFunc err,
23524 xmlSchemaValidityWarningFunc warn, void *ctx)
23525{
Daniel Veillard4255d502002-04-16 15:50:10 +000023526 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023527 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023528 ctxt->error = err;
23529 ctxt->warning = warn;
23530 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023531 if (ctxt->pctxt != NULL)
23532 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023533}
23534
23535/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023536 * xmlSchemaGetValidErrors:
23537 * @ctxt: a XML-Schema validation context
23538 * @err: the error function result
23539 * @warn: the warning function result
23540 * @ctx: the functions context result
23541 *
23542 * Get the error and warning callback informations
23543 *
23544 * Returns -1 in case of error and 0 otherwise
23545 */
23546int
23547xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23548 xmlSchemaValidityErrorFunc * err,
23549 xmlSchemaValidityWarningFunc * warn, void **ctx)
23550{
23551 if (ctxt == NULL)
23552 return (-1);
23553 if (err != NULL)
23554 *err = ctxt->error;
23555 if (warn != NULL)
23556 *warn = ctxt->warning;
23557 if (ctx != NULL)
23558 *ctx = ctxt->userData;
23559 return (0);
23560}
23561
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023562
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023563/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023564 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023565 * @ctxt: a schema validation context
23566 * @options: a combination of xmlSchemaValidOption
23567 *
23568 * Sets the options to be used during the validation.
23569 *
23570 * Returns 0 in case of success, -1 in case of an
23571 * API error.
23572 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023573int
23574xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23575 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023576
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023577{
23578 int i;
23579
23580 if (ctxt == NULL)
23581 return (-1);
23582 /*
23583 * WARNING: Change the start value if adding to the
23584 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023585 * TODO: Is there an other, more easy to maintain,
23586 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023587 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023588 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023589 if (options & 1<<i)
23590 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023591 }
23592 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023593 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023594}
23595
23596/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023597 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023598 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023599 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023600 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023601 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023602 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023603 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023604int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023605xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023606
23607{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023608 if (ctxt == NULL)
23609 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023610 else
23611 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023612}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023613
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023614static int
23615xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23616{
23617 xmlAttrPtr attr;
23618 int ret = 0;
23619 xmlSchemaNodeInfoPtr ielem = NULL;
23620 xmlNodePtr node, valRoot;
23621 const xmlChar *nsName;
23622
23623 /* DOC VAL TODO: Move this to the start function. */
23624 valRoot = xmlDocGetRootElement(vctxt->doc);
23625 if (valRoot == NULL) {
23626 /* VAL TODO: Error code? */
23627 VERROR(1, NULL, "The document has no document element");
23628 return (1);
23629 }
23630 vctxt->depth = -1;
23631 vctxt->validationRoot = valRoot;
23632 node = valRoot;
23633 while (node != NULL) {
23634 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23635 goto next_sibling;
23636 if (node->type == XML_ELEMENT_NODE) {
23637
23638 /*
23639 * Init the node-info.
23640 */
23641 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23642 goto internal_error;
23643 ielem = vctxt->inode;
23644 ielem->node = node;
23645 ielem->localName = node->name;
23646 if (node->ns != NULL)
23647 ielem->nsName = node->ns->href;
23648 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23649 /*
23650 * Register attributes.
23651 * DOC VAL TODO: We do not register namespace declaration
23652 * attributes yet.
23653 */
23654 vctxt->nbAttrInfos = 0;
23655 if (node->properties != NULL) {
23656 attr = node->properties;
23657 do {
23658 if (attr->ns != NULL)
23659 nsName = attr->ns->href;
23660 else
23661 nsName = NULL;
23662 ret = xmlSchemaValidatorPushAttribute(vctxt,
23663 (xmlNodePtr) attr,
23664 attr->name, nsName, 0,
23665 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23666 if (ret == -1) {
23667 VERROR_INT("xmlSchemaDocWalk",
23668 "calling xmlSchemaValidatorPushAttribute()");
23669 goto internal_error;
23670 }
23671 attr = attr->next;
23672 } while (attr);
23673 }
23674 /*
23675 * Validate the element.
23676 */
23677 ret = xmlSchemaValidateElem(vctxt);
23678 if (ret != 0) {
23679 if (ret == -1) {
23680 VERROR_INT("xmlSchemaDocWalk",
23681 "calling xmlSchemaValidateElem()");
23682 goto internal_error;
23683 }
23684 /*
23685 * Don't stop validation; just skip the content
23686 * of this element.
23687 */
23688 goto leave_node;
23689 }
23690 if ((vctxt->skipDepth != -1) &&
23691 (vctxt->depth >= vctxt->skipDepth))
23692 goto leave_node;
23693 } else if ((node->type == XML_TEXT_NODE) ||
23694 (node->type == XML_CDATA_SECTION_NODE)) {
23695 /*
23696 * Process character content.
23697 */
23698 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23699 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23700 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23701 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23702 if (ret < 0) {
23703 VERROR_INT("xmlSchemaVDocWalk",
23704 "calling xmlSchemaVPushText()");
23705 goto internal_error;
23706 }
23707 /*
23708 * DOC VAL TODO: Should we skip further validation of the
23709 * element content here?
23710 */
23711 } else if ((node->type == XML_ENTITY_NODE) ||
23712 (node->type == XML_ENTITY_REF_NODE)) {
23713 /*
23714 * DOC VAL TODO: What to do with entities?
23715 */
23716 TODO
23717 } else {
23718 goto leave_node;
23719 /*
23720 * DOC VAL TODO: XInclude nodes, etc.
23721 */
23722 }
23723 /*
23724 * Walk the doc.
23725 */
23726 if (node->children != NULL) {
23727 node = node->children;
23728 continue;
23729 }
23730leave_node:
23731 if (node->type == XML_ELEMENT_NODE) {
23732 /*
23733 * Leaving the scope of an element.
23734 */
23735 if (node != vctxt->inode->node) {
23736 VERROR_INT("xmlSchemaVDocWalk",
23737 "element position mismatch");
23738 goto internal_error;
23739 }
23740 ret = xmlSchemaValidatorPopElem(vctxt);
23741 if (ret != 0) {
23742 if (ret < 0) {
23743 VERROR_INT("xmlSchemaVDocWalk",
23744 "calling xmlSchemaValidatorPopElem()");
23745 goto internal_error;
23746 }
23747 }
23748 if (node == valRoot)
23749 goto exit;
23750 }
23751next_sibling:
23752 if (node->next != NULL)
23753 node = node->next;
23754 else {
23755 node = node->parent;
23756 goto leave_node;
23757 }
23758 }
23759
23760exit:
23761 return (ret);
23762internal_error:
23763 return (-1);
23764}
23765
23766static int
23767xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23768{
23769 int ret = 0;
23770
23771 /*
23772 * Some initialization.
23773 */
23774 vctxt->err = 0;
23775 vctxt->nberrors = 0;
23776 vctxt->depth = -1;
23777 vctxt->skipDepth = -1;
23778 /*
23779 * Create a schema + parser if necessary.
23780 */
23781 if (vctxt->schema == NULL) {
23782
23783 if ((vctxt->pctxt == NULL) &&
23784 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23785 return (-1);
23786
23787 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23788 if (vctxt->schema == NULL) {
23789 VERROR_INT("xmlSchemaVStartValidation",
23790 "creating a schema");
23791 return (-1);
23792 }
23793 vctxt->xsiAssemble = 1;
23794 } else
23795 vctxt->xsiAssemble = 0;
23796 /*
23797 * Augment the IDC definitions.
23798 */
23799 if (vctxt->schema->idcDef != NULL) {
23800 xmlHashScan(vctxt->schema->idcDef,
23801 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23802 }
23803 if (vctxt->doc != NULL) {
23804 /*
23805 * Tree validation.
23806 */
23807 ret = xmlSchemaVDocWalk(vctxt);
23808 } else if (vctxt->reader != NULL) {
23809 /*
23810 * XML Reader validation.
23811 */
23812#ifdef XML_SCHEMA_READER_ENABLED
23813 ret = xmlSchemaVReaderWalk(vctxt);
23814#endif
23815 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23816 /*
23817 * SAX validation.
23818 */
23819 /* ret = xmlSAXUserParseFile(ctxt->sax, ctxt, uri); */
23820 ret = xmlParseDocument(vctxt->parserCtxt);
23821 } else {
23822 VERROR_INT("xmlSchemaVStartValidation",
23823 "no instance to validate");
23824 ret = -1;
23825 }
23826
23827 if (vctxt->xsiAssemble) {
23828 if (vctxt->schema != NULL) {
23829 xmlSchemaFree(vctxt->schema);
23830 vctxt->schema = NULL;
23831 }
23832 }
23833 xmlSchemaClearValidCtxt(vctxt);
23834 if (ret == 0)
23835 ret = vctxt->err;
23836 return (ret);
23837}
23838
23839/**
23840 * xmlSchemaValidateOneElement:
23841 * @ctxt: a schema validation context
23842 * @elem: an element node
23843 *
23844 * Validate a branch of a tree, starting with the given @elem.
23845 *
23846 * Returns 0 if the element and its subtree is valid, a positive error
23847 * code number otherwise and -1 in case of an internal or API error.
23848 */
23849int
23850xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23851{
23852 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
23853 return (-1);
23854
23855 if (ctxt->schema == NULL)
23856 return (-1);
23857
23858 ctxt->doc = elem->doc;
23859 ctxt->node = elem;
23860 ctxt->validationRoot = elem;
23861 return(xmlSchemaVStart(ctxt));
23862}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023863
Daniel Veillard259f0df2004-08-18 09:13:18 +000023864/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023865 * xmlSchemaValidateDoc:
23866 * @ctxt: a schema validation context
23867 * @doc: a parsed document tree
23868 *
23869 * Validate a document tree in memory.
23870 *
23871 * Returns 0 if the document is schemas valid, a positive error code
23872 * number otherwise and -1 in case of internal or API error.
23873 */
23874int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023875xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23876{
Daniel Veillard4255d502002-04-16 15:50:10 +000023877 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023878 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023879
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023880 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023881 ctxt->node = xmlDocGetRootElement(doc);
23882 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023883 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023884 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23885 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023886 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023887 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023888 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023889 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023890 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023891}
23892
23893/**
23894 * xmlSchemaValidateStream:
23895 * @ctxt: a schema validation context
23896 * @input: the input to use for reading the data
23897 * @enc: an optional encoding information
23898 * @sax: a SAX handler for the resulting events
23899 * @user_data: the context to provide to the SAX handler.
23900 *
23901 * Validate a document tree in memory.
23902 *
23903 * Returns 0 if the document is schemas valid, a positive error code
23904 * number otherwise and -1 in case of internal or API error.
23905 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023906int
Daniel Veillard4255d502002-04-16 15:50:10 +000023907xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023908 xmlParserInputBufferPtr input, xmlCharEncoding enc,
23909 xmlSAXHandlerPtr sax, void *user_data)
23910{
Daniel Veillard4255d502002-04-16 15:50:10 +000023911 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023912 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023913 ctxt->input = input;
23914 ctxt->enc = enc;
23915 ctxt->sax = sax;
23916 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023917 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023918}
23919
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023920#if 0
23921/**
23922 * xmlSchemaValidateFile:
23923 * @ctxt: a schema validation context
23924 * @uri: the URI of the instance
23925 *
23926 * Returns 0 if the document is valid, a positive error code
23927 * number otherwise and -1 in case of an internal or API error.
23928 */
23929int
23930xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
23931 const char * filename)
23932{
23933 int ret;
23934
23935 if ((ctxt == NULL) || (filename == NULL))
23936 return (-1);
23937
23938 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
23939 if (ctxt->sax == NULL) {
23940 xmlSchemaVErrMemory(ctxt,
23941 "creating SAX handler", NULL);
23942 return (-1);
23943 }
23944 memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
23945 ctxt->parserCtxt = xmlCreateFileParserCtxt(filename);
23946 if (ctxt->parserCtxt == NULL) {
23947 xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt,
23948 "xmlSchemaValidateFile", "creating a parser context");
23949 xmlFree(ctxt->sax);
23950 return (-1);
23951 }
23952#ifdef LIBXML_SAX1_ENABLED
23953 if (ctxt->parserCtxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
23954#endif /* LIBXML_SAX1_ENABLED */
23955 xmlFree(ctxt->parserCtxt->sax);
23956 /*
23957 * Init the SAX handler.
23958 */
23959 ctxt->sax->startElementNs = xmlSchemaSAXHandleStartElementNs;
23960 ctxt->sax->endElementNs = xmlSchemaSAXHandleEndElementNs;
23961 /*
23962 * Note that we use the same text-function for both, to prevent
23963 * the parser from testing for ignorable whitespace.
23964 */
23965 ctxt->sax->ignorableWhitespace = xmlSchemaSAXHandleText;
23966 ctxt->sax->characters = xmlSchemaSAXHandleText;
23967 ctxt->sax->cdataBlock = xmlSchemaSAXHandleCDataSection;
23968 ctxt->sax->reference = xmlSchemaSAXHandleReference;
23969 ctxt->sax->initialized = XML_SAX2_MAGIC;
23970 /*
23971 * Init the parser context.
23972 */
23973 ctxt->parserCtxt->sax = ctxt->sax;
23974 ctxt->parserCtxt->sax2 = 1;
23975 ctxt->parserCtxt->userData = ctxt;
23976 /* VAL TODO: Set error handlers. */
23977
23978 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
23979 ret = xmlSchemaVStart(ctxt, filename);
23980
23981 /*
23982 * URGENT VAL TODO: What to do with well-formedness errors?
23983 */
23984 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
23985 ret = ctxt->parserCtxt->errNo;
23986 if (ret == 0)
23987 /* URGENT VAL TODO: Error code? */
23988 ret = 1;
23989 xmlSchemaErr((xmlSchemaAbstractCtxtPtr) ctxt, ret, NULL,
23990 "The instance document '%s' is not well-formed",
23991 filename, NULL);
23992 }
23993 ctxt->parserCtxt->sax = NULL;
23994 xmlFreeParserCtxt(ctxt->parserCtxt);
23995 xmlFree(ctxt->sax);
23996 ctxt->sax = NULL;
23997
23998 return (ret);
23999}
24000#endif
24001
24002#ifdef XML_SCHEMA_READER_ENABLED
24003int
24004xmlSchemaValidateReader(xmlSchemaValidCtxtPtr ctxt,
24005 xmlTextReaderPtr reader)
24006{
24007 if ((ctxt == NULL) || (reader == NULL))
24008 return (-1);
24009 ctxt->reader = reader;
24010 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24011 return(xmlSchemaVStart(ctxt, NULL));
24012}
24013#endif /* XML_SCHEMA_READER_ENABLED */
24014
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024015#define bottom_xmlschemas
24016#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024017#endif /* LIBXML_SCHEMAS_ENABLED */