blob: 8263b5a5dc4b9ddf00dd6055257a8761a53b1b97 [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#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000799 case XML_SCHEMA_TYPE_IDC_UNIQUE:
800 return(BAD_CAST "IDC (unique)");
801 case XML_SCHEMA_TYPE_IDC_KEY:
802 return(BAD_CAST "IDC (key)");
803 case XML_SCHEMA_TYPE_IDC_KEYREF:
804 return(BAD_CAST "IDC (keyref)");
805 case XML_SCHEMA_EXTRA_QNAMEREF:
806 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000807 default:
808 return(BAD_CAST "Not a schema component");
809 }
810}
811
812/**
813 * xmlSchemaGetComponentNode:
814 * @item: a schema component
815 *
816 * Returns node associated with the schema component.
817 * NOTE that such a node need not be available; plus, a component's
818 * node need not to reflect the component directly, since there is no
819 * one-to-one relationship between the XML Schema representation and
820 * the component representation.
821 */
822static xmlNodePtr
823xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
824{
825 switch (item->type) {
826 case XML_SCHEMA_TYPE_ELEMENT:
827 return (((xmlSchemaElementPtr) item)->node);
828 case XML_SCHEMA_TYPE_ATTRIBUTE:
829 return (((xmlSchemaAttributePtr) item)->node);
830 case XML_SCHEMA_TYPE_COMPLEX:
831 case XML_SCHEMA_TYPE_SIMPLE:
832 return (((xmlSchemaTypePtr) item)->node);
833 case XML_SCHEMA_TYPE_ANY:
834 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
835 return (((xmlSchemaWildcardPtr) item)->node);
836 case XML_SCHEMA_TYPE_PARTICLE:
837 return (((xmlSchemaParticlePtr) item)->node);
838 case XML_SCHEMA_TYPE_SEQUENCE:
839 case XML_SCHEMA_TYPE_CHOICE:
840 case XML_SCHEMA_TYPE_ALL:
841 return (((xmlSchemaModelGroupPtr) item)->node);
842 case XML_SCHEMA_TYPE_GROUP:
843 return (((xmlSchemaModelGroupDefPtr) item)->node);
844 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
845 return (((xmlSchemaAttributeGroupPtr) item)->node);
846 case XML_SCHEMA_TYPE_IDC_UNIQUE:
847 case XML_SCHEMA_TYPE_IDC_KEY:
848 case XML_SCHEMA_TYPE_IDC_KEYREF:
849 return (((xmlSchemaIDCPtr) item)->node);
850 default:
851 return (NULL);
852 }
853}
854
855#if 0
856/**
857 * xmlSchemaGetNextComponent:
858 * @item: a schema component
859 *
860 * Returns the next sibling of the schema component.
861 */
862static xmlSchemaBasicItemPtr
863xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
864{
865 switch (item->type) {
866 case XML_SCHEMA_TYPE_ELEMENT:
867 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
868 case XML_SCHEMA_TYPE_ATTRIBUTE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
870 case XML_SCHEMA_TYPE_COMPLEX:
871 case XML_SCHEMA_TYPE_SIMPLE:
872 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
873 case XML_SCHEMA_TYPE_ANY:
874 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
875 return (NULL);
876 case XML_SCHEMA_TYPE_PARTICLE:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
878 case XML_SCHEMA_TYPE_SEQUENCE:
879 case XML_SCHEMA_TYPE_CHOICE:
880 case XML_SCHEMA_TYPE_ALL:
881 return (NULL);
882 case XML_SCHEMA_TYPE_GROUP:
883 return (NULL);
884 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
885 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
886 case XML_SCHEMA_TYPE_IDC_UNIQUE:
887 case XML_SCHEMA_TYPE_IDC_KEY:
888 case XML_SCHEMA_TYPE_IDC_KEYREF:
889 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
890 default:
891 return (NULL);
892 }
893}
894#endif
895
896/**
897 * xmlSchemaGetAttrName:
898 * @attr: the attribute declaration/use
899 *
900 * Returns the name of the attribute; if the attribute
901 * is a reference, the name of the referenced global type will be returned.
902 */
903static const xmlChar *
904xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
905{
906 if (attr->ref != NULL)
907 return(attr->ref);
908 else
909 return(attr->name);
910}
911
912/**
913 * xmlSchemaGetAttrTargetNsURI:
914 * @type: the type (element or attribute)
915 *
916 * Returns the target namespace URI of the type; if the type is a reference,
917 * the target namespace of the referenced type will be returned.
918 */
919static const xmlChar *
920xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
921{
922 if (attr->ref != NULL)
923 return (attr->refNs);
924 else
925 return(attr->targetNamespace);
926}
927
928/**
929 * xmlSchemaFormatQName:
930 * @buf: the string buffer
931 * @namespaceName: the namespace name
932 * @localName: the local name
933 *
934 * Returns the given QName in the format "{namespaceName}localName" or
935 * just "localName" if @namespaceName is NULL.
936 *
937 * Returns the localName if @namespaceName is NULL, a formatted
938 * string otherwise.
939 */
940static const xmlChar*
941xmlSchemaFormatQName(xmlChar **buf,
942 const xmlChar *namespaceName,
943 const xmlChar *localName)
944{
945 FREE_AND_NULL(*buf)
946 if (namespaceName == NULL)
947 return(localName);
948
949 *buf = xmlStrdup(BAD_CAST "{");
950 *buf = xmlStrcat(*buf, namespaceName);
951 *buf = xmlStrcat(*buf, BAD_CAST "}");
952 *buf = xmlStrcat(*buf, localName);
953
954 return ((const xmlChar *) *buf);
955}
956
957static const xmlChar*
958xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
959{
960 if (ns != NULL)
961 return (xmlSchemaFormatQName(buf, ns->href, localName));
962 else
963 return (xmlSchemaFormatQName(buf, NULL, localName));
964}
965
966static const xmlChar *
967xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
968{
969 switch (item->type) {
970 case XML_SCHEMA_TYPE_ELEMENT:
971 return (((xmlSchemaElementPtr) item)->name);
972 case XML_SCHEMA_TYPE_ATTRIBUTE:
973 return (((xmlSchemaAttributePtr) item)->name);
974 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
975 return (((xmlSchemaAttributeGroupPtr) item)->name);
976 case XML_SCHEMA_TYPE_BASIC:
977 case XML_SCHEMA_TYPE_SIMPLE:
978 case XML_SCHEMA_TYPE_COMPLEX:
979 return (((xmlSchemaTypePtr) item)->name);
980 case XML_SCHEMA_TYPE_GROUP:
981 return (((xmlSchemaModelGroupDefPtr) item)->name);
982 case XML_SCHEMA_TYPE_IDC_KEY:
983 case XML_SCHEMA_TYPE_IDC_UNIQUE:
984 case XML_SCHEMA_TYPE_IDC_KEYREF:
985 return (((xmlSchemaIDCPtr) item)->name);
986 default:
987 /*
988 * Other components cannot have names.
989 */
990 break;
991 }
992 return (NULL);
993}
994
995static const xmlChar *
996xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
997{
998 switch (item->type) {
999 case XML_SCHEMA_TYPE_ELEMENT:
1000 return (((xmlSchemaElementPtr) item)->targetNamespace);
1001 case XML_SCHEMA_TYPE_ATTRIBUTE:
1002 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1003 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1004 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1005 case XML_SCHEMA_TYPE_BASIC:
1006 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1007 case XML_SCHEMA_TYPE_SIMPLE:
1008 case XML_SCHEMA_TYPE_COMPLEX:
1009 return (((xmlSchemaTypePtr) item)->targetNamespace);
1010 case XML_SCHEMA_TYPE_GROUP:
1011 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1012 case XML_SCHEMA_TYPE_IDC_KEY:
1013 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1014 case XML_SCHEMA_TYPE_IDC_KEYREF:
1015 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1016 default:
1017 /*
1018 * Other components cannot have names.
1019 */
1020 break;
1021 }
1022 return (NULL);
1023}
1024
1025static const xmlChar*
1026xmlSchemaGetComponentQName(xmlChar **buf,
1027 void *item)
1028{
1029 return (xmlSchemaFormatQName(buf,
1030 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1031 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1032}
1033
1034/**
1035 * xmlSchemaWildcardPCToString:
1036 * @pc: the type of processContents
1037 *
1038 * Returns a string representation of the type of
1039 * processContents.
1040 */
1041static const xmlChar *
1042xmlSchemaWildcardPCToString(int pc)
1043{
1044 switch (pc) {
1045 case XML_SCHEMAS_ANY_SKIP:
1046 return (BAD_CAST "skip");
1047 case XML_SCHEMAS_ANY_LAX:
1048 return (BAD_CAST "lax");
1049 case XML_SCHEMAS_ANY_STRICT:
1050 return (BAD_CAST "strict");
1051 default:
1052 return (BAD_CAST "invalid process contents");
1053 }
1054}
1055
1056/**
1057 * xmlSchemaGetCanonValueWhtspExt:
1058 * @val: the precomputed value
1059 * @retValue: the returned value
1060 * @ws: the whitespace type of the value
1061 *
1062 * Get a the cononical representation of the value.
1063 * The caller has to free the returned retValue.
1064 *
1065 * Returns 0 if the value could be built and -1 in case of
1066 * API errors or if the value type is not supported yet.
1067 */
1068static int
1069xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1070 xmlSchemaWhitespaceValueType ws,
1071 xmlChar **retValue)
1072{
1073 int list;
1074 xmlSchemaValType valType;
1075 const xmlChar *value, *value2 = NULL;
1076
1077
1078 if ((retValue == NULL) || (val == NULL))
1079 return (-1);
1080 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1081 *retValue = NULL;
1082 do {
1083 value = NULL;
1084 valType = xmlSchemaGetValType(val);
1085 switch (valType) {
1086 case XML_SCHEMAS_STRING:
1087 case XML_SCHEMAS_NORMSTRING:
1088 case XML_SCHEMAS_ANYSIMPLETYPE:
1089 value = xmlSchemaValueGetAsString(val);
1090 if (value != NULL) {
1091 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1092 value2 = xmlSchemaCollapseString(value);
1093 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1094 value2 = xmlSchemaWhiteSpaceReplace(value);
1095 if (value2 != NULL)
1096 value = value2;
1097 }
1098 break;
1099 default:
1100 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1101 if (value2 != NULL)
1102 xmlFree((xmlChar *) value2);
1103 goto internal_error;
1104 }
1105 value = value2;
1106 }
1107 if (*retValue == NULL)
1108 if (value == NULL) {
1109 if (! list)
1110 *retValue = xmlStrdup(BAD_CAST "");
1111 } else
1112 *retValue = xmlStrdup(value);
1113 else if (value != NULL) {
1114 /* List. */
1115 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1116 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1117 }
1118 FREE_AND_NULL(value2)
1119 val = xmlSchemaValueGetNext(val);
1120 } while (val != NULL);
1121
1122 return (0);
1123internal_error:
1124 if (*retValue != NULL)
1125 xmlFree((xmlChar *) (*retValue));
1126 if (value2 != NULL)
1127 xmlFree((xmlChar *) value2);
1128 return (-1);
1129}
1130
1131/**
1132 * xmlSchemaFormatItemForReport:
1133 * @buf: the string buffer
1134 * @itemDes: the designation of the item
1135 * @itemName: the name of the item
1136 * @item: the item as an object
1137 * @itemNode: the node of the item
1138 * @local: the local name
1139 * @parsing: if the function is used during the parse
1140 *
1141 * Returns a representation of the given item used
1142 * for error reports.
1143 *
1144 * The following order is used to build the resulting
1145 * designation if the arguments are not NULL:
1146 * 1a. If itemDes not NULL -> itemDes
1147 * 1b. If (itemDes not NULL) and (itemName not NULL)
1148 * -> itemDes + itemName
1149 * 2. If the preceding was NULL and (item not NULL) -> item
1150 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1151 *
1152 * If the itemNode is an attribute node, the name of the attribute
1153 * will be appended to the result.
1154 *
1155 * Returns the formatted string and sets @buf to the resulting value.
1156 */
1157static xmlChar*
1158xmlSchemaFormatItemForReport(xmlChar **buf,
1159 const xmlChar *itemDes,
1160 xmlSchemaTypePtr item,
1161 xmlNodePtr itemNode)
1162{
1163 xmlChar *str = NULL;
1164 int named = 1;
1165
1166 if (*buf != NULL) {
1167 xmlFree(*buf);
1168 *buf = NULL;
1169 }
1170
1171 if (itemDes != NULL) {
1172 *buf = xmlStrdup(itemDes);
1173 } else if (item != NULL) {
1174 switch (item->type) {
1175 case XML_SCHEMA_TYPE_BASIC:
1176 if (VARIETY_ATOMIC(item))
1177 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1178 else if (VARIETY_LIST(item))
1179 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1180 else if (VARIETY_UNION(item))
1181 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1182 else
1183 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1184 *buf = xmlStrcat(*buf, item->name);
1185 *buf = xmlStrcat(*buf, BAD_CAST "'");
1186 break;
1187 case XML_SCHEMA_TYPE_SIMPLE:
1188 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1189 *buf = xmlStrdup(BAD_CAST"");
1190 } else {
1191 *buf = xmlStrdup(BAD_CAST "local ");
1192 }
1193 if (VARIETY_ATOMIC(item))
1194 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1195 else if (VARIETY_LIST(item))
1196 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1197 else if (VARIETY_UNION(item))
1198 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1199 else
1200 *buf = xmlStrcat(*buf, BAD_CAST "simple 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_COMPLEX:
1208 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1209 *buf = xmlStrdup(BAD_CAST "");
1210 else
1211 *buf = xmlStrdup(BAD_CAST "local ");
1212 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1213 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1214 *buf = xmlStrcat(*buf, BAD_CAST " '");
1215 *buf = xmlStrcat(*buf, item->name);
1216 *buf = xmlStrcat(*buf, BAD_CAST "'");
1217 }
1218 break;
1219 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1220 xmlSchemaAttributePtr attr;
1221
1222 attr = (xmlSchemaAttributePtr) item;
1223 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1224 (attr->ref == NULL)) {
1225 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1226 *buf = xmlStrcat(*buf, BAD_CAST " '");
1227 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1228 attr->targetNamespace, attr->name));
1229 FREE_AND_NULL(str)
1230 *buf = xmlStrcat(*buf, BAD_CAST "'");
1231 } else {
1232 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1233 *buf = xmlStrcat(*buf, BAD_CAST " '");
1234 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1235 attr->refNs, attr->ref));
1236 FREE_AND_NULL(str)
1237 *buf = xmlStrcat(*buf, BAD_CAST "'");
1238 }
1239 }
1240 break;
1241 case XML_SCHEMA_TYPE_ELEMENT: {
1242 xmlSchemaElementPtr elem;
1243
1244 elem = (xmlSchemaElementPtr) item;
1245 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1246 (elem->ref == NULL)) {
1247 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1248 *buf = xmlStrcat(*buf, BAD_CAST " '");
1249 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1250 elem->targetNamespace, elem->name));
1251 *buf = xmlStrcat(*buf, BAD_CAST "'");
1252 }
1253 }
1254 break;
1255 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1256 case XML_SCHEMA_TYPE_IDC_KEY:
1257 case XML_SCHEMA_TYPE_IDC_KEYREF:
1258 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1259 *buf = xmlStrdup(BAD_CAST "unique '");
1260 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1261 *buf = xmlStrdup(BAD_CAST "key '");
1262 else
1263 *buf = xmlStrdup(BAD_CAST "keyRef '");
1264 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1265 *buf = xmlStrcat(*buf, BAD_CAST "'");
1266 break;
1267 case XML_SCHEMA_TYPE_ANY:
1268 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1269 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1270 ((xmlSchemaWildcardPtr) item)->processContents));
1271 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1272 break;
1273 case XML_SCHEMA_FACET_MININCLUSIVE:
1274 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1275 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1276 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1277 case XML_SCHEMA_FACET_TOTALDIGITS:
1278 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1279 case XML_SCHEMA_FACET_PATTERN:
1280 case XML_SCHEMA_FACET_ENUMERATION:
1281 case XML_SCHEMA_FACET_WHITESPACE:
1282 case XML_SCHEMA_FACET_LENGTH:
1283 case XML_SCHEMA_FACET_MAXLENGTH:
1284 case XML_SCHEMA_FACET_MINLENGTH:
1285 *buf = xmlStrdup(BAD_CAST "facet '");
1286 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1287 *buf = xmlStrcat(*buf, BAD_CAST "'");
1288 break;
1289 case XML_SCHEMA_TYPE_NOTATION:
1290 *buf = xmlStrdup(BAD_CAST "notation");
1291 break;
1292 case XML_SCHEMA_TYPE_GROUP: {
1293 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1294 *buf = xmlStrcat(*buf, BAD_CAST " '");
1295 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1296 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1297 ((xmlSchemaModelGroupDefPtr) item)->name));
1298 *buf = xmlStrcat(*buf, BAD_CAST "'");
1299 FREE_AND_NULL(str)
1300 }
1301 break;
1302 case XML_SCHEMA_TYPE_SEQUENCE:
1303 case XML_SCHEMA_TYPE_CHOICE:
1304 case XML_SCHEMA_TYPE_ALL:
1305 case XML_SCHEMA_TYPE_PARTICLE:
1306 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1307 break;
1308 default:
1309 named = 0;
1310 }
1311 } else
1312 named = 0;
1313
1314 if ((named == 0) && (itemNode != NULL)) {
1315 xmlNodePtr elem;
1316
1317 if (itemNode->type == XML_ATTRIBUTE_NODE)
1318 elem = itemNode->parent;
1319 else
1320 elem = itemNode;
1321 *buf = xmlStrdup(BAD_CAST "Element '");
1322 if (elem->ns != NULL) {
1323 *buf = xmlStrcat(*buf,
1324 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1325 FREE_AND_NULL(str)
1326 } else
1327 *buf = xmlStrcat(*buf, elem->name);
1328 *buf = xmlStrcat(*buf, BAD_CAST "'");
1329
1330 }
1331 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1332 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1333 if (itemNode->ns != NULL) {
1334 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1335 itemNode->ns->href, itemNode->name));
1336 FREE_AND_NULL(str)
1337 } else
1338 *buf = xmlStrcat(*buf, itemNode->name);
1339 *buf = xmlStrcat(*buf, BAD_CAST "'");
1340 }
1341 FREE_AND_NULL(str)
1342
1343 return (*buf);
1344}
1345
1346/**
1347 * xmlSchemaFormatFacetEnumSet:
1348 * @buf: the string buffer
1349 * @type: the type holding the enumeration facets
1350 *
1351 * Builds a string consisting of all enumeration elements.
1352 *
1353 * Returns a string of all enumeration elements.
1354 */
1355static const xmlChar *
1356xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1357 xmlChar **buf, xmlSchemaTypePtr type)
1358{
1359 xmlSchemaFacetPtr facet;
1360 xmlSchemaWhitespaceValueType ws;
1361 xmlChar *value = NULL;
1362 int res;
1363
1364 if (*buf != NULL)
1365 xmlFree(*buf);
1366 *buf = NULL;
1367
1368 do {
1369 /*
1370 * Use the whitespace type of the base type.
1371 */
1372 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1373 for (facet = type->facets; facet != NULL; facet = facet->next) {
1374 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1375 continue;
1376 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1377 ws, &value);
1378 if (res == -1) {
1379 xmlSchemaInternalErr(actxt,
1380 "xmlSchemaFormatFacetEnumSet",
1381 "compute the canonical lexical representation");
1382 if (*buf != NULL)
1383 xmlFree(*buf);
1384 *buf = NULL;
1385 return (NULL);
1386 }
1387 if (*buf == NULL)
1388 *buf = xmlStrdup(BAD_CAST "'");
1389 else
1390 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1391 *buf = xmlStrcat(*buf, BAD_CAST value);
1392 *buf = xmlStrcat(*buf, BAD_CAST "'");
1393 if (value != NULL) {
1394 xmlFree((xmlChar *)value);
1395 value = NULL;
1396 }
1397 }
1398 type = type->baseType;
1399 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1400
1401 return ((const xmlChar *) *buf);
1402}
1403
1404/************************************************************************
1405 * *
1406 * Error functions *
1407 * *
1408 ************************************************************************/
1409
1410#if 0
1411static void
1412xmlSchemaErrMemory(const char *msg)
1413{
1414 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1415 msg);
1416}
1417#endif
1418
1419/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001420 * xmlSchemaPErrMemory:
1421 * @node: a context node
1422 * @extra: extra informations
1423 *
1424 * Handle an out of memory condition
1425 */
1426static void
1427xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1428 const char *extra, xmlNodePtr node)
1429{
1430 if (ctxt != NULL)
1431 ctxt->nberrors++;
1432 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1433 extra);
1434}
1435
1436/**
1437 * xmlSchemaPErr:
1438 * @ctxt: the parsing context
1439 * @node: the context node
1440 * @error: the error code
1441 * @msg: the error message
1442 * @str1: extra data
1443 * @str2: extra data
1444 *
1445 * Handle a parser error
1446 */
1447static void
1448xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1449 const char *msg, const xmlChar * str1, const xmlChar * str2)
1450{
1451 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001452 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001453 void *data = NULL;
1454
1455 if (ctxt != NULL) {
1456 ctxt->nberrors++;
1457 channel = ctxt->error;
1458 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001459 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001460 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001461 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001462 error, XML_ERR_ERROR, NULL, 0,
1463 (const char *) str1, (const char *) str2, NULL, 0, 0,
1464 msg, str1, str2);
1465}
1466
1467/**
1468 * xmlSchemaPErr2:
1469 * @ctxt: the parsing context
1470 * @node: the context node
1471 * @node: the current child
1472 * @error: the error code
1473 * @msg: the error message
1474 * @str1: extra data
1475 * @str2: extra data
1476 *
1477 * Handle a parser error
1478 */
1479static void
1480xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1481 xmlNodePtr child, int error,
1482 const char *msg, const xmlChar * str1, const xmlChar * str2)
1483{
1484 if (child != NULL)
1485 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1486 else
1487 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1488}
1489
Daniel Veillard01fa6152004-06-29 17:04:39 +00001490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001491/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001492 * xmlSchemaPErrExt:
1493 * @ctxt: the parsing context
1494 * @node: the context node
1495 * @error: the error code
1496 * @strData1: extra data
1497 * @strData2: extra data
1498 * @strData3: extra data
1499 * @msg: the message
1500 * @str1: extra parameter for the message display
1501 * @str2: extra parameter for the message display
1502 * @str3: extra parameter for the message display
1503 * @str4: extra parameter for the message display
1504 * @str5: extra parameter for the message display
1505 *
1506 * Handle a parser error
1507 */
1508static void
1509xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1510 const xmlChar * strData1, const xmlChar * strData2,
1511 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1512 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1513 const xmlChar * str5)
1514{
1515
1516 xmlGenericErrorFunc channel = NULL;
1517 xmlStructuredErrorFunc schannel = NULL;
1518 void *data = NULL;
1519
1520 if (ctxt != NULL) {
1521 ctxt->nberrors++;
1522 channel = ctxt->error;
1523 data = ctxt->userData;
1524 schannel = ctxt->serror;
1525 }
1526 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1527 error, XML_ERR_ERROR, NULL, 0,
1528 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001529 (const char *) strData3, 0, 0, msg, str1, str2,
1530 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001531}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001532
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001533/************************************************************************
1534 * *
1535 * Allround error functions *
1536 * *
1537 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001538
1539/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001540 * xmlSchemaVTypeErrMemory:
1541 * @node: a context node
1542 * @extra: extra informations
1543 *
1544 * Handle an out of memory condition
1545 */
1546static void
1547xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1548 const char *extra, xmlNodePtr node)
1549{
1550 if (ctxt != NULL) {
1551 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001552 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001553 }
1554 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1555 extra);
1556}
1557
1558/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001559 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001560 * @ctxt: the validation context
1561 * @node: the context node
1562 * @error: the error code
1563 * @msg: the error message
1564 * @str1: extra data
1565 * @str2: extra data
1566 * @str3: extra data
1567 *
1568 * Handle a validation error
1569 */
1570static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1572 int error, xmlNodePtr node, const char *msg,
1573 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001574{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001575 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576 xmlGenericErrorFunc channel = NULL;
1577 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 if (ctxt != NULL) {
1580 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1581 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001582 int line = 0;
1583 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584
1585 vctxt->nberrors++;
1586 vctxt->err = error;
1587 channel = vctxt->error;
1588 schannel = vctxt->serror;
1589 data = vctxt->userData;
1590 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001591 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001592 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 }
1594 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1595 (vctxt->parserCtxt->input != NULL)) {
1596 file = vctxt->parserCtxt->input->filename;
1597 line = vctxt->parserCtxt->input->line;
1598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 __xmlRaiseError(schannel, channel, data, ctxt,
1600 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001601 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001602 (const char *) str1, (const char *) str2,
1603 (const char *) str3, 0, 0, msg, str1, str2, str3);
1604
1605 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1606 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1607
1608 pctxt->nberrors++;
1609 pctxt->err = error;
1610 channel = pctxt->error;
1611 schannel = pctxt->serror;
1612 data = pctxt->userData;
1613 __xmlRaiseError(schannel, channel, data, ctxt,
1614 node, XML_FROM_SCHEMASP,
1615 error, XML_ERR_ERROR, NULL, 0,
1616 (const char *) str1, (const char *) str2,
1617 (const char *) str3, 0, 0, msg, str1, str2, str3);
1618 } else {
1619 TODO
1620 }
1621 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static void
1625xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1626 int error, xmlNodePtr node, const char *msg,
1627 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001628{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001629 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001630}
1631
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001632static xmlChar *
1633xmlSchemaFormatNodeForError(xmlChar ** msg,
1634 xmlSchemaAbstractCtxtPtr actxt,
1635 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001636{
1637 xmlChar *str = NULL;
1638
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001639 if (node != NULL) {
1640 /*
1641 * Work on tree nodes.
1642 */
1643 if (node->type == XML_ATTRIBUTE_NODE) {
1644 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001645
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001646 *msg = xmlStrdup(BAD_CAST "Element '");
1647 if (elem->ns != NULL)
1648 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1649 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1652 NULL, elem->name));
1653 FREE_AND_NULL(str);
1654 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1655 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1656 } else {
1657 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001658 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001659 if (node->ns != NULL)
1660 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1661 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001662 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001663 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1664 NULL, node->name));
1665 FREE_AND_NULL(str);
1666 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1667 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1668 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1669 /*
1670 * Work on node infos.
1671 */
1672 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1673 xmlSchemaNodeInfoPtr ielem =
1674 vctxt->elemInfos[vctxt->depth];
1675
1676 *msg = xmlStrdup(BAD_CAST "Element '");
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 ielem->nsName, ielem->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1681 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1682 } else {
1683 *msg = xmlStrdup(BAD_CAST "Element '");
1684 }
1685 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1686 vctxt->inode->nsName, vctxt->inode->localName));
1687 FREE_AND_NULL(str);
1688 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1689 } else {
1690 TODO
1691 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001692 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001693 /*
1694 * VAL TODO: The output of the given schema component is currently
1695 * disabled.
1696 */
1697#if 0
1698 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1699 *msg = xmlStrcat(*msg, BAD_CAST " [");
1700 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1701 NULL, type, NULL, 0));
1702 FREE_AND_NULL(str)
1703 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001704 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001705#endif
1706 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001707}
1708
Daniel Veillardc0826a72004-08-10 14:17:33 +00001709static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001710xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001711 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001712 const char *message,
1713 const xmlChar *str1,
1714 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001715{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001716 xmlChar *msg = NULL;
1717
1718 msg = xmlStrdup(BAD_CAST "Internal error: ");
1719 msg = xmlStrcat(msg, BAD_CAST funcName);
1720 msg = xmlStrcat(msg, BAD_CAST ", ");
1721 msg = xmlStrcat(msg, BAD_CAST message);
1722 msg = xmlStrcat(msg, BAD_CAST ".\n");
1723
1724 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1725 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001726 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001727
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001728 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001729 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001730 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001731
1732 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001733}
1734
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001735static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001736xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1737 const char *funcName,
1738 const char *message)
1739{
1740 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
1741}
1742
1743static void
1744xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
1745 const char *funcName,
1746 const char *message,
1747 const xmlChar *str1,
1748 const xmlChar *str2)
1749{
1750 xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message,
1751 str1, str2);
1752}
1753
1754static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001755xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1756 xmlParserErrors error,
1757 xmlNodePtr node,
1758 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1759 const char *message,
1760 const xmlChar *str1,
1761 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001762{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001763 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 xmlSchemaFormatNodeForError(&msg, actxt, node);
1766 msg = xmlStrcat(msg, (const xmlChar *) message);
1767 msg = xmlStrcat(msg, BAD_CAST ".\n");
1768 xmlSchemaErr(actxt, error, node,
1769 (const char *) msg, str1, str2);
1770 FREE_AND_NULL(msg)
1771}
1772
1773static int
1774xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1775 xmlNodePtr node)
1776{
1777 if (node != NULL)
1778 return (node->type);
1779 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1780 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1781 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1782 return (-1);
1783}
1784
1785static int
1786xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1787{
1788 switch (item->type) {
1789 case XML_SCHEMA_TYPE_COMPLEX:
1790 case XML_SCHEMA_TYPE_SIMPLE:
1791 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1792 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001793 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001794 case XML_SCHEMA_TYPE_GROUP:
1795 return (1);
1796 case XML_SCHEMA_TYPE_ELEMENT:
1797 if ( ((xmlSchemaElementPtr) item)->flags &
1798 XML_SCHEMAS_ELEM_GLOBAL)
1799 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001800 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001801 case XML_SCHEMA_TYPE_ATTRIBUTE:
1802 if ( ((xmlSchemaAttributePtr) item)->flags &
1803 XML_SCHEMAS_ATTR_GLOBAL)
1804 return(1);
1805 break;
1806 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001807 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001808 return(1);
1809 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001810 return (0);
1811}
1812
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001813static void
1814xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1815 xmlParserErrors error,
1816 xmlNodePtr node,
1817 const xmlChar *value,
1818 xmlSchemaTypePtr type,
1819 int displayValue)
1820{
1821 xmlChar *msg = NULL;
1822
1823 xmlSchemaFormatNodeForError(&msg, actxt, node);
1824
1825 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1826 XML_ATTRIBUTE_NODE))
1827 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1828 else
1829 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1830 "value of ");
1831
1832 if (! xmlSchemaIsGlobalItem(type))
1833 msg = xmlStrcat(msg, BAD_CAST "the local ");
1834 else
1835 msg = xmlStrcat(msg, BAD_CAST "the ");
1836
1837 if (VARIETY_ATOMIC(type))
1838 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1839 else if (VARIETY_LIST(type))
1840 msg = xmlStrcat(msg, BAD_CAST "list type");
1841 else if (VARIETY_UNION(type))
1842 msg = xmlStrcat(msg, BAD_CAST "union type");
1843
1844 if (xmlSchemaIsGlobalItem(type)) {
1845 xmlChar *str = NULL;
1846 msg = xmlStrcat(msg, BAD_CAST " '");
1847 if (type->builtInType != 0) {
1848 msg = xmlStrcat(msg, BAD_CAST "xs:");
1849 msg = xmlStrcat(msg, type->name);
1850 } else
1851 msg = xmlStrcat(msg,
1852 xmlSchemaFormatQName(&str,
1853 type->targetNamespace, type->name));
1854 msg = xmlStrcat(msg, BAD_CAST "'");
1855 FREE_AND_NULL(str);
1856 }
1857 msg = xmlStrcat(msg, BAD_CAST ".\n");
1858 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1859 XML_ATTRIBUTE_NODE))
1860 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1861 else
1862 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1863 FREE_AND_NULL(msg)
1864}
1865
Daniel Veillardc0826a72004-08-10 14:17:33 +00001866static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001867xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1868 xmlSchemaNodeInfoPtr ni,
1869 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001870{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001871 if (node != NULL) {
1872 if (node->ns != NULL)
1873 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1874 else
1875 return (xmlSchemaFormatQName(str, NULL, node->name));
1876 } else if (ni != NULL)
1877 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1878 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001879}
1880
Daniel Veillardc0826a72004-08-10 14:17:33 +00001881static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001882xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1883 xmlParserErrors error,
1884 xmlSchemaAttrInfoPtr ni,
1885 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001886{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001887 xmlChar *msg = NULL, *str = NULL;
1888
1889 xmlSchemaFormatNodeForError(&msg, actxt, node);
1890 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1891 xmlSchemaErr(actxt, error, node, (const char *) msg,
1892 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1893 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001894 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001895 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001896}
1897
Daniel Veillardc0826a72004-08-10 14:17:33 +00001898static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001899xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1900 xmlParserErrors error,
1901 xmlNodePtr node,
1902 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001903 const char *message,
1904 int nbval,
1905 int nbneg,
1906 xmlChar **values)
1907{
1908 xmlChar *str = NULL, *msg = NULL;
1909 xmlChar *localName, *nsName;
1910 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00001911 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001912
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001913 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001915 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001916 /*
1917 * Note that is does not make sense to report that we have a
1918 * wildcard here, since the wildcard might be unfolded into
1919 * multiple transitions.
1920 */
1921 if (nbval + nbneg > 0) {
1922 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001923 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001924 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001925 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001926 nsName = NULL;
1927
1928 for (i = 0; i < nbval + nbneg; i++) {
1929 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00001930 if (cur == NULL)
1931 continue;
1932 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
1933 (cur[3] == ' ')) {
1934 is_not = 1;
1935 cur += 4;
1936 str = xmlStrcat(str, BAD_CAST "not ");
1937 } else {
1938 is_not = 0;
1939 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001940 /*
1941 * Get the local name.
1942 */
1943 localName = NULL;
1944
1945 end = cur;
1946 if (*end == '*') {
1947 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001948 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001949 } else {
1950 while ((*end != 0) && (*end != '|'))
1951 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001952 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001953 }
1954 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001955 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001956 /*
1957 * Skip "*|*" if they come with negated expressions, since
1958 * they represent the same negated wildcard.
1959 */
1960 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1961 /*
1962 * Get the namespace name.
1963 */
1964 cur = end;
1965 if (*end == '*') {
1966 nsName = xmlStrdup(BAD_CAST "{*}");
1967 } else {
1968 while (*end != 0)
1969 end++;
1970
1971 if (i >= nbval)
1972 nsName = xmlStrdup(BAD_CAST "{##other:");
1973 else
1974 nsName = xmlStrdup(BAD_CAST "{");
1975
1976 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1977 nsName = xmlStrcat(nsName, BAD_CAST "}");
1978 }
1979 str = xmlStrcat(str, BAD_CAST nsName);
1980 FREE_AND_NULL(nsName)
1981 } else {
1982 FREE_AND_NULL(localName);
1983 continue;
1984 }
1985 }
1986 str = xmlStrcat(str, BAD_CAST localName);
1987 FREE_AND_NULL(localName);
1988
1989 if (i < nbval + nbneg -1)
1990 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001991 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001992 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001993 msg = xmlStrcat(msg, BAD_CAST str);
1994 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001995 } else
1996 msg = xmlStrcat(msg, BAD_CAST "\n");
1997 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001998 xmlFree(msg);
1999}
2000
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002001static void
2002xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2003 xmlParserErrors error,
2004 xmlNodePtr node,
2005 const xmlChar *value,
2006 unsigned long length,
2007 xmlSchemaTypePtr type,
2008 xmlSchemaFacetPtr facet,
2009 const char *message,
2010 const xmlChar *str1,
2011 const xmlChar *str2)
2012{
2013 xmlChar *str = NULL, *msg = NULL;
2014 xmlSchemaTypeType facetType;
2015 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2016
2017 xmlSchemaFormatNodeForError(&msg, actxt, node);
2018 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2019 facetType = XML_SCHEMA_FACET_ENUMERATION;
2020 /*
2021 * If enumerations are validated, one must not expect the
2022 * facet to be given.
2023 */
2024 } else
2025 facetType = facet->type;
2026 msg = xmlStrcat(msg, BAD_CAST "[");
2027 msg = xmlStrcat(msg, BAD_CAST "facet '");
2028 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2029 msg = xmlStrcat(msg, BAD_CAST "'] ");
2030 if (message == NULL) {
2031 /*
2032 * Use a default message.
2033 */
2034 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2035 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2036 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2037
2038 char len[25], actLen[25];
2039
2040 /* FIXME, TODO: What is the max expected string length of the
2041 * this value?
2042 */
2043 if (nodeType == XML_ATTRIBUTE_NODE)
2044 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2045 else
2046 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2047
2048 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2049 snprintf(actLen, 24, "%lu", length);
2050
2051 if (facetType == XML_SCHEMA_FACET_LENGTH)
2052 msg = xmlStrcat(msg,
2053 BAD_CAST "this differs from the allowed length of '%s'.\n");
2054 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2055 msg = xmlStrcat(msg,
2056 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2057 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2058 msg = xmlStrcat(msg,
2059 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2060
2061 if (nodeType == XML_ATTRIBUTE_NODE)
2062 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2063 value, (const xmlChar *) actLen, (const xmlChar *) len);
2064 else
2065 xmlSchemaErr(actxt, error, node, (const char *) msg,
2066 (const xmlChar *) actLen, (const xmlChar *) len);
2067
2068 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2069 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2070 "of the set {%s}.\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2072 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2073 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2074 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2075 "by the pattern '%s'.\n");
2076 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2077 facet->value);
2078 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2079 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2080 "minimum value allowed ('%s').\n");
2081 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2082 facet->value);
2083 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2084 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2085 "maximum value allowed ('%s').\n");
2086 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2087 facet->value);
2088 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2089 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2090 "'%s'.\n");
2091 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2092 facet->value);
2093 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2094 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2095 "'%s'.\n");
2096 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2097 facet->value);
2098 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2099 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2100 "digits than are allowed ('%s').\n");
2101 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2102 facet->value);
2103 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2104 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2105 "digits than are allowed ('%s').\n");
2106 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2107 facet->value);
2108 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2109 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2110 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2111 } else {
2112 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2113 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2114 }
2115 } else {
2116 msg = xmlStrcat(msg, (const xmlChar *) message);
2117 msg = xmlStrcat(msg, BAD_CAST ".\n");
2118 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2119 }
2120 FREE_AND_NULL(str)
2121 xmlFree(msg);
2122}
2123
2124#define VERROR(err, type, msg) \
2125 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2126
2127#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2128
2129#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2130
2131#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2132
2133
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002134/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002135 * xmlSchemaPMissingAttrErr:
2136 * @ctxt: the schema validation context
2137 * @ownerDes: the designation of the owner
2138 * @ownerName: the name of the owner
2139 * @ownerItem: the owner as a schema object
2140 * @ownerElem: the owner as an element node
2141 * @node: the parent element node of the missing attribute node
2142 * @type: the corresponding type of the attribute node
2143 *
2144 * Reports an illegal attribute.
2145 */
2146static void
2147xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002148 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002149 xmlSchemaTypePtr ownerItem,
2150 xmlNodePtr ownerElem,
2151 const char *name,
2152 const char *message)
2153{
2154 xmlChar *des = NULL;
2155
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002156 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2157
Daniel Veillardc0826a72004-08-10 14:17:33 +00002158 if (message != NULL)
2159 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002160 else
2161 xmlSchemaPErr(ctxt, ownerElem, error,
2162 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002163 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002164 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165}
2166
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002167
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168/**
2169 * xmlSchemaPResCompAttrErr:
2170 * @ctxt: the schema validation context
2171 * @error: the error code
2172 * @ownerDes: the designation of the owner
2173 * @ownerItem: the owner as a schema object
2174 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002175 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002176 * @refName: the referenced local name
2177 * @refURI: the referenced namespace URI
2178 * @message: optional message
2179 *
2180 * Used to report QName attribute values that failed to resolve
2181 * to schema components.
2182 */
2183static void
2184xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002185 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002186 xmlSchemaTypePtr ownerItem,
2187 xmlNodePtr ownerElem,
2188 const char *name,
2189 const xmlChar *refName,
2190 const xmlChar *refURI,
2191 xmlSchemaTypeType refType,
2192 const char *refTypeStr)
2193{
2194 xmlChar *des = NULL, *strA = NULL;
2195
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002196 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2199 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002200 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002201 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2202 "%s.\n", BAD_CAST des, BAD_CAST name,
2203 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002204 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002205 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002206 FREE_AND_NULL(strA)
2207}
2208
William M. Brack2f2a6632004-08-20 23:09:47 +00002209/**
2210 * xmlSchemaPCustomAttrErr:
2211 * @ctxt: the schema parser context
2212 * @error: the error code
2213 * @ownerDes: the designation of the owner
2214 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002215 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002216 *
2217 * Reports an illegal attribute during the parse.
2218 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002219static void
2220xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002221 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002222 xmlChar **ownerDes,
2223 xmlSchemaTypePtr ownerItem,
2224 xmlAttrPtr attr,
2225 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226{
2227 xmlChar *des = NULL;
2228
2229 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002230 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002231 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 } else
2235 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002236 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002237 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002238 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2239 if (ownerDes == NULL)
2240 FREE_AND_NULL(des);
2241}
2242
2243/**
2244 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002245 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002246 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002247 * @ownerDes: the designation of the attribute's owner
2248 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002251 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252 */
2253static void
2254xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002255 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002256 xmlChar **ownerDes,
2257 xmlSchemaTypePtr ownerItem,
2258 xmlAttrPtr attr)
2259{
2260 xmlChar *des = NULL, *strA = NULL;
2261
2262 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002263 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002264 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002265 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002266 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002267 } else
2268 des = *ownerDes;
2269 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2270 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2271 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002272 if (ownerDes == NULL)
2273 FREE_AND_NULL(des);
2274 FREE_AND_NULL(strA);
2275}
2276
William M. Brack2f2a6632004-08-20 23:09:47 +00002277/**
2278 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002279 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002280 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002281 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002282 * @itemElem: the node of the schema item
2283 *
2284 * Creates a designation for an item.
2285 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002286static void
2287xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002288 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002289 xmlSchemaTypePtr item,
2290 xmlNodePtr itemElem)
2291{
2292 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002293 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002294 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002297 } else
2298 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002299}
2300
William M. Brack2f2a6632004-08-20 23:09:47 +00002301/**
2302 * xmlSchemaPCustomErr:
2303 * @ctxt: the schema parser context
2304 * @error: the error code
2305 * @itemDes: the designation of the schema item
2306 * @item: the schema item
2307 * @itemElem: the node of the schema item
2308 * @message: the error message
2309 * @str1: an optional param for the error message
2310 * @str2: an optional param for the error message
2311 * @str3: an optional param for the error message
2312 *
2313 * Reports an error during parsing.
2314 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002315static void
2316xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002317 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002318 xmlChar **itemDes,
2319 xmlSchemaTypePtr item,
2320 xmlNodePtr itemElem,
2321 const char *message,
2322 const xmlChar *str1,
2323 const xmlChar *str2,
2324 const xmlChar *str3)
2325{
2326 xmlChar *des = NULL, *msg = NULL;
2327
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002328 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002329 msg = xmlStrdup(BAD_CAST "%s: ");
2330 msg = xmlStrcat(msg, (const xmlChar *) message);
2331 msg = xmlStrcat(msg, BAD_CAST ".\n");
2332 if ((itemElem == NULL) && (item != NULL))
2333 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002334 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002335 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2336 if (itemDes == NULL)
2337 FREE_AND_NULL(des);
2338 FREE_AND_NULL(msg);
2339}
2340
William M. Brack2f2a6632004-08-20 23:09:47 +00002341/**
2342 * xmlSchemaPCustomErr:
2343 * @ctxt: the schema parser context
2344 * @error: the error code
2345 * @itemDes: the designation of the schema item
2346 * @item: the schema item
2347 * @itemElem: the node of the schema item
2348 * @message: the error message
2349 * @str1: the optional param for the error message
2350 *
2351 * Reports an error during parsing.
2352 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002353static void
2354xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002355 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002356 xmlChar **itemDes,
2357 xmlSchemaTypePtr item,
2358 xmlNodePtr itemElem,
2359 const char *message,
2360 const xmlChar *str1)
2361{
2362 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2363 str1, NULL, NULL);
2364}
2365
William M. Brack2f2a6632004-08-20 23:09:47 +00002366/**
2367 * xmlSchemaPAttrUseErr:
2368 * @ctxt: the schema parser context
2369 * @error: the error code
2370 * @itemDes: the designation of the schema type
2371 * @item: the schema type
2372 * @itemElem: the node of the schema type
2373 * @attr: the invalid schema attribute
2374 * @message: the error message
2375 * @str1: the optional param for the error message
2376 *
2377 * Reports an attribute use error during parsing.
2378 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002379static void
2380xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002381 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002382 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002383 const xmlSchemaAttributePtr attr,
2384 const char *message,
2385 const xmlChar *str1)
2386{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002387 xmlChar *str = NULL, *msg = NULL;
2388 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2389 msg = xmlStrcat(msg, BAD_CAST ", ");
2390 msg = xmlStrcat(msg,
2391 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2392 (xmlSchemaTypePtr) attr, NULL));
2393 FREE_AND_NULL(str);
2394 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002395 msg = xmlStrcat(msg, (const xmlChar *) message);
2396 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002397 xmlSchemaPErr(ctxt, attr->node, error,
2398 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002399 xmlFree(msg);
2400}
2401
William M. Brack2f2a6632004-08-20 23:09:47 +00002402/**
2403 * xmlSchemaPIllegalFacetAtomicErr:
2404 * @ctxt: the schema parser context
2405 * @error: the error code
2406 * @itemDes: the designation of the type
2407 * @item: the schema type
2408 * @baseItem: the base type of type
2409 * @facet: the illegal facet
2410 *
2411 * Reports an illegal facet for atomic simple types.
2412 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002413static void
2414xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002415 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002416 xmlChar **itemDes,
2417 xmlSchemaTypePtr item,
2418 xmlSchemaTypePtr baseItem,
2419 xmlSchemaFacetPtr facet)
2420{
2421 xmlChar *des = NULL, *strT = NULL;
2422
2423 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2424 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2425 "%s: The facet '%s' is not allowed on types derived from the "
2426 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002427 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002428 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002429 NULL, NULL);
2430 if (itemDes == NULL)
2431 FREE_AND_NULL(des);
2432 FREE_AND_NULL(strT);
2433}
2434
William M. Brack2f2a6632004-08-20 23:09:47 +00002435/**
2436 * xmlSchemaPIllegalFacetListUnionErr:
2437 * @ctxt: the schema parser context
2438 * @error: the error code
2439 * @itemDes: the designation of the schema item involved
2440 * @item: the schema item involved
2441 * @facet: the illegal facet
2442 *
2443 * Reports an illegal facet for <list> and <union>.
2444 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002445static void
2446xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002447 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002448 xmlChar **itemDes,
2449 xmlSchemaTypePtr item,
2450 xmlSchemaFacetPtr facet)
2451{
2452 xmlChar *des = NULL, *strT = NULL;
2453
2454 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002455 xmlSchemaPErr(ctxt, item->node, error,
2456 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002457 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002458 if (itemDes == NULL)
2459 FREE_AND_NULL(des);
2460 FREE_AND_NULL(strT);
2461}
2462
2463/**
2464 * xmlSchemaPMutualExclAttrErr:
2465 * @ctxt: the schema validation context
2466 * @error: the error code
2467 * @elemDes: the designation of the parent element node
2468 * @attr: the bad attribute node
2469 * @type: the corresponding type of the attribute node
2470 *
2471 * Reports an illegal attribute.
2472 */
2473static void
2474xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2475 xmlParserErrors error,
2476 xmlChar **ownerDes,
2477 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 const char *name1,
2480 const char *name2)
2481{
2482 xmlChar *des = NULL;
2483
2484 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002485 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002486 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002487 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002488 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002489 } else
2490 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002491 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002492 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002493 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2494 if (ownerDes == NULL)
2495 FREE_AND_NULL(des)
2496}
2497
2498/**
2499 * xmlSchemaPSimpleTypeErr:
2500 * @ctxt: the schema validation context
2501 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002502 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002503 * @ownerDes: the designation of the owner
2504 * @ownerItem: the schema object if existent
2505 * @node: the validated node
2506 * @value: the validated value
2507 *
2508 * Reports a simple type validation error.
2509 * TODO: Should this report the value of an element as well?
2510 */
2511static void
2512xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2513 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002515 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002516 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002517 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002518 const xmlChar *value,
2519 const char *message,
2520 const xmlChar *str1,
2521 const xmlChar *str2)
2522{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002523 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002525 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002526 if (message == NULL) {
2527 /*
2528 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002529 */
2530 if (type != NULL) {
2531 if (node->type == XML_ATTRIBUTE_NODE)
2532 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2533 else
2534 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2535 "valid value of ");
2536 if (! xmlSchemaIsGlobalItem(type))
2537 msg = xmlStrcat(msg, BAD_CAST "the local ");
2538 else
2539 msg = xmlStrcat(msg, BAD_CAST "the ");
2540
2541 if (VARIETY_ATOMIC(type))
2542 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2543 else if (VARIETY_LIST(type))
2544 msg = xmlStrcat(msg, BAD_CAST "list type");
2545 else if (VARIETY_UNION(type))
2546 msg = xmlStrcat(msg, BAD_CAST "union type");
2547
2548 if (xmlSchemaIsGlobalItem(type)) {
2549 xmlChar *str = NULL;
2550 msg = xmlStrcat(msg, BAD_CAST " '");
2551 if (type->builtInType != 0) {
2552 msg = xmlStrcat(msg, BAD_CAST "xs:");
2553 msg = xmlStrcat(msg, type->name);
2554 } else
2555 msg = xmlStrcat(msg,
2556 xmlSchemaFormatQName(&str,
2557 type->targetNamespace, type->name));
2558 msg = xmlStrcat(msg, BAD_CAST "'.");
2559 FREE_AND_NULL(str);
2560 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002561 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002562 if (node->type == XML_ATTRIBUTE_NODE)
2563 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2564 else
2565 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2566 "valid.");
2567 }
2568 if (expected) {
2569 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2570 msg = xmlStrcat(msg, BAD_CAST expected);
2571 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2572 } else
2573 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2576 else
2577 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2578 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002579 msg = xmlStrcat(msg, BAD_CAST message);
2580 msg = xmlStrcat(msg, BAD_CAST "\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002582 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002583 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002584 /* Cleanup. */
2585 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002586}
2587
William M. Brack2f2a6632004-08-20 23:09:47 +00002588/**
2589 * xmlSchemaPContentErr:
2590 * @ctxt: the schema parser context
2591 * @error: the error code
2592 * @onwerDes: the designation of the holder of the content
2593 * @ownerItem: the owner item of the holder of the content
2594 * @ownerElem: the node of the holder of the content
2595 * @child: the invalid child node
2596 * @message: the optional error message
2597 * @content: the optional string describing the correct content
2598 *
2599 * Reports an error concerning the content of a schema element.
2600 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002601static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002602xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002603 xmlParserErrors error,
2604 xmlChar **ownerDes,
2605 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002606 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002607 xmlNodePtr child,
2608 const char *message,
2609 const char *content)
2610{
2611 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002612
Daniel Veillardc0826a72004-08-10 14:17:33 +00002613 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002614 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002615 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002616 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002617 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002618 } else
2619 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002620 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002621 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2622 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002623 BAD_CAST des, BAD_CAST message);
2624 else {
2625 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002626 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2627 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002628 BAD_CAST des, BAD_CAST content);
2629 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002630 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2631 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002632 BAD_CAST des, NULL);
2633 }
2634 }
2635 if (ownerDes == NULL)
2636 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002637}
2638
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002639/************************************************************************
2640 * *
2641 * Streamable error functions *
2642 * *
2643 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002644
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002645
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002646
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002648/************************************************************************
2649 * *
2650 * Validation helper functions *
2651 * *
2652 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002653
Daniel Veillardc0826a72004-08-10 14:17:33 +00002654
Daniel Veillard4255d502002-04-16 15:50:10 +00002655/************************************************************************
2656 * *
2657 * Allocation functions *
2658 * *
2659 ************************************************************************/
2660
2661/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002662 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002663 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002664 *
2665 * Allocate a new Schema structure.
2666 *
2667 * Returns the newly allocated structure or NULL in case or error
2668 */
2669static xmlSchemaPtr
2670xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2671{
2672 xmlSchemaPtr ret;
2673
2674 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2675 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002676 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002677 return (NULL);
2678 }
2679 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002680 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002681 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002682
2683 return (ret);
2684}
2685
2686/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002687 * xmlSchemaNewSchema:
2688 * @ctxt: a schema validation context
2689 *
2690 * Allocate a new Schema structure.
2691 *
2692 * Returns the newly allocated structure or NULL in case or error
2693 */
2694static xmlSchemaAssemblePtr
2695xmlSchemaNewAssemble(void)
2696{
2697 xmlSchemaAssemblePtr ret;
2698
2699 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2700 if (ret == NULL) {
2701 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2702 return (NULL);
2703 }
2704 memset(ret, 0, sizeof(xmlSchemaAssemble));
2705 ret->items = NULL;
2706 return (ret);
2707}
2708
2709/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002710 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002711 *
2712 * Allocate a new Facet structure.
2713 *
2714 * Returns the newly allocated structure or NULL in case or error
2715 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002716xmlSchemaFacetPtr
2717xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002718{
2719 xmlSchemaFacetPtr ret;
2720
2721 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2722 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002723 return (NULL);
2724 }
2725 memset(ret, 0, sizeof(xmlSchemaFacet));
2726
2727 return (ret);
2728}
2729
2730/**
2731 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002732 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002733 * @node: a node
2734 *
2735 * Allocate a new annotation structure.
2736 *
2737 * Returns the newly allocated structure or NULL in case or error
2738 */
2739static xmlSchemaAnnotPtr
2740xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2741{
2742 xmlSchemaAnnotPtr ret;
2743
2744 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2745 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002746 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002747 return (NULL);
2748 }
2749 memset(ret, 0, sizeof(xmlSchemaAnnot));
2750 ret->content = node;
2751 return (ret);
2752}
2753
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002754static xmlSchemaItemListPtr
2755xmlSchemaNewItemList(void)
2756{
2757 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002758
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002759 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2760 if (ret == NULL) {
2761 xmlSchemaPErrMemory(NULL,
2762 "allocating an item list structure", NULL);
2763 return (NULL);
2764 }
2765 memset(ret, 0, sizeof(xmlSchemaItemList));
2766 return (ret);
2767}
2768
2769/**
2770 * xmlSchemaAddElementSubstitutionMember:
2771 * @pctxt: a schema parser context
2772 * @head: the head of the substitution group
2773 * @member: the new member of the substitution group
2774 *
2775 * Allocate a new annotation structure.
2776 *
2777 * Returns the newly allocated structure or NULL in case or error
2778 */
2779static int
2780xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2781 xmlSchemaElementPtr head,
2782 xmlSchemaElementPtr member)
2783{
2784 xmlSchemaSubstGroupPtr substGroup;
2785
2786 if (pctxt == NULL)
2787 return (-1);
2788
2789 if (pctxt->substGroups == NULL) {
2790 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2791 if (pctxt->substGroups == NULL)
2792 return (-1);
2793 }
2794 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2795 head->targetNamespace);
2796 if (substGroup == NULL) {
2797 int res;
2798
2799 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2800 if (substGroup == NULL) {
2801 xmlSchemaPErrMemory(NULL,
2802 "xmlSchemaAddElementSubstitution, allocating a substitution "
2803 "group container",
2804 NULL);
2805 return (-1);
2806 }
2807 substGroup->members = xmlSchemaNewItemList();
2808 if (substGroup->members == NULL) {
2809 xmlFree(substGroup);
2810 return (-1);
2811 }
2812 substGroup->head = head;
2813
2814 res = xmlHashAddEntry2(pctxt->substGroups,
2815 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002816 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002817 xmlFree(substGroup->members);
2818 xmlFree(substGroup);
2819 xmlSchemaPErr(pctxt, member->node,
2820 XML_SCHEMAP_INTERNAL,
2821 "Internal error: xmlSchemaAddElementSubstitution, "
2822 "failed to add a new substitution group container for "
2823 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002824 return (-1);
2825 }
2826 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002827 if (substGroup->members->items == NULL) {
2828 substGroup->members->items = (void **) xmlMalloc(
2829 5 * sizeof(xmlSchemaElementPtr));
2830 if (substGroup->members->items == NULL) {
2831 xmlSchemaPErrMemory(NULL,
2832 "allocating list of substitution group members", NULL);
2833 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002834 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002835 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002837 substGroup->members->nbItems) {
2838 substGroup->members->sizeItems *= 2;
2839 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002840 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002841 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2842 if (substGroup->members->items == NULL) {
2843 xmlSchemaPErrMemory(NULL,
2844 "re-allocating list of substitution group members", NULL);
2845 substGroup->members->sizeItems = 0;
2846 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002847 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002848 }
2849 ((xmlSchemaElementPtr *) substGroup->members->items)
2850 [substGroup->members->nbItems++] = (void *) member;
2851 return (0);
2852}
2853
2854/**
2855 * xmlSchemaGetElementSubstitutionGroup:
2856 * @pctxt: a schema parser context
2857 * @head: the head of the substitution group
2858 * @member: the new member of the substitution group
2859 *
2860 * Allocate a new annotation structure.
2861 *
2862 * Returns the newly allocated structure or NULL in case or error
2863 */
2864static xmlSchemaSubstGroupPtr
2865xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2866 xmlSchemaElementPtr head)
2867{
2868 if (pctxt == NULL)
2869 return (NULL);
2870
2871 if (pctxt->substGroups == NULL)
2872 return (NULL);
2873
2874 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2875 head->name, head->targetNamespace));
2876}
2877
2878/**
2879 * xmlSchemaFreeItemList:
2880 * @annot: a schema type structure
2881 *
2882 * Deallocate a annotation structure
2883 */
2884static void
2885xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2886{
2887 if (list == NULL)
2888 return;
2889 if (list->items != NULL)
2890 xmlFree(list->items);
2891 xmlFree(list);
2892}
2893
Daniel Veillard4255d502002-04-16 15:50:10 +00002894/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002895 * xmlSchemaFreeAnnot:
2896 * @annot: a schema type structure
2897 *
2898 * Deallocate a annotation structure
2899 */
2900static void
2901xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2902{
2903 if (annot == NULL)
2904 return;
2905 xmlFree(annot);
2906}
2907
2908/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002909 * xmlSchemaFreeImport:
2910 * @import: a schema import structure
2911 *
2912 * Deallocate an import structure
2913 */
2914static void
2915xmlSchemaFreeImport(xmlSchemaImportPtr import)
2916{
2917 if (import == NULL)
2918 return;
2919
2920 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002921 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002922 xmlFree(import);
2923}
2924
2925/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002926 * xmlSchemaFreeInclude:
2927 * @include: a schema include structure
2928 *
2929 * Deallocate an include structure
2930 */
2931static void
2932xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2933{
2934 if (include == NULL)
2935 return;
2936
2937 xmlFreeDoc(include->doc);
2938 xmlFree(include);
2939}
2940
2941/**
2942 * xmlSchemaFreeIncludeList:
2943 * @includes: a schema include list
2944 *
2945 * Deallocate an include structure
2946 */
2947static void
2948xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2949{
2950 xmlSchemaIncludePtr next;
2951
2952 while (includes != NULL) {
2953 next = includes->next;
2954 xmlSchemaFreeInclude(includes);
2955 includes = next;
2956 }
2957}
2958
2959/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002960 * xmlSchemaFreeNotation:
2961 * @schema: a schema notation structure
2962 *
2963 * Deallocate a Schema Notation structure.
2964 */
2965static void
2966xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2967{
2968 if (nota == NULL)
2969 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002970 xmlFree(nota);
2971}
2972
2973/**
2974 * xmlSchemaFreeAttribute:
2975 * @schema: a schema attribute structure
2976 *
2977 * Deallocate a Schema Attribute structure.
2978 */
2979static void
2980xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2981{
2982 if (attr == NULL)
2983 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002984 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002985 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002986 if (attr->defVal != NULL)
2987 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002988 xmlFree(attr);
2989}
2990
2991/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002992 * xmlSchemaFreeWildcardNsSet:
2993 * set: a schema wildcard namespace
2994 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002995 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002996 */
2997static void
2998xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2999{
3000 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003001
Daniel Veillard3646d642004-06-02 19:19:14 +00003002 while (set != NULL) {
3003 next = set->next;
3004 xmlFree(set);
3005 set = next;
3006 }
3007}
3008
3009/**
3010 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003011 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003012 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003013 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003014 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003015void
Daniel Veillard3646d642004-06-02 19:19:14 +00003016xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3017{
3018 if (wildcard == NULL)
3019 return;
3020 if (wildcard->annot != NULL)
3021 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003022 if (wildcard->nsSet != NULL)
3023 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3024 if (wildcard->negNsSet != NULL)
3025 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003026 xmlFree(wildcard);
3027}
3028
3029/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003030 * xmlSchemaFreeAttributeGroup:
3031 * @schema: a schema attribute group structure
3032 *
3033 * Deallocate a Schema Attribute Group structure.
3034 */
3035static void
3036xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3037{
3038 if (attr == NULL)
3039 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003040 if (attr->annot != NULL)
3041 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 xmlFree(attr);
3043}
3044
3045/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003046 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003047 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003048 *
3049 * Deallocate a list of schema attribute uses.
3050 */
3051static void
3052xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3053{
3054 xmlSchemaAttributeLinkPtr next;
3055
3056 while (attrUse != NULL) {
3057 next = attrUse->next;
3058 xmlFree(attrUse);
3059 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003060 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003061}
3062
3063/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003064 * xmlSchemaFreeQNameRef:
3065 * @item: a QName reference structure
3066 *
3067 * Deallocatea a QName reference structure.
3068 */
3069static void
3070xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3071{
3072 xmlFree(item);
3073}
3074
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003075/**
3076 * xmlSchemaFreeQNameRef:
3077 * @item: a QName reference structure
3078 *
3079 * Deallocatea a QName reference structure.
3080 */
3081static void
3082xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3083{
3084 if (item == NULL)
3085 return;
3086 if (item->members != NULL)
3087 xmlSchemaFreeItemList(item->members);
3088 xmlFree(item);
3089}
3090
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003091static int
3092xmlSchemaAddVolatile(xmlSchemaPtr schema,
3093 xmlSchemaBasicItemPtr item)
3094{
3095 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003096
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003097 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003098 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003099 if (schema->volatiles == NULL) {
3100 xmlSchemaPErrMemory(NULL,
3101 "allocating list of volatiles", NULL);
3102 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003103 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003104 }
3105 list = (xmlSchemaItemListPtr) schema->volatiles;
3106 if (list->items == NULL) {
3107 list->items = (void **) xmlMalloc(
3108 20 * sizeof(xmlSchemaBasicItemPtr));
3109 if (list->items == NULL) {
3110 xmlSchemaPErrMemory(NULL,
3111 "allocating new volatile item buffer", NULL);
3112 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003113 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003114 list->sizeItems = 20;
3115 } else if (list->sizeItems <= list->nbItems) {
3116 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003117 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003118 list->sizeItems * sizeof(xmlSchemaTypePtr));
3119 if (list->items == NULL) {
3120 xmlSchemaPErrMemory(NULL,
3121 "growing volatile item buffer", NULL);
3122 list->sizeItems = 0;
3123 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003124 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003125 }
3126 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3127 return (0);
3128}
3129
3130/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003131 * xmlSchemaFreeTypeLinkList:
3132 * @alink: a type link
3133 *
3134 * Deallocate a list of types.
3135 */
3136static void
3137xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3138{
3139 xmlSchemaTypeLinkPtr next;
3140
3141 while (link != NULL) {
3142 next = link->next;
3143 xmlFree(link);
3144 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003145 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003146}
3147
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003148static void
3149xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3150{
3151 xmlSchemaIDCStateObjPtr next;
3152 while (sto != NULL) {
3153 next = sto->next;
3154 if (sto->history != NULL)
3155 xmlFree(sto->history);
3156 if (sto->xpathCtxt != NULL)
3157 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3158 xmlFree(sto);
3159 sto = next;
3160 }
3161}
3162
3163/**
3164 * xmlSchemaFreeIDC:
3165 * @idc: a identity-constraint definition
3166 *
3167 * Deallocates an identity-constraint definition.
3168 */
3169static void
3170xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3171{
3172 xmlSchemaIDCSelectPtr cur, prev;
3173
3174 if (idcDef == NULL)
3175 return;
3176 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003177 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003178 /* Selector */
3179 if (idcDef->selector != NULL) {
3180 if (idcDef->selector->xpathComp != NULL)
3181 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3182 xmlFree(idcDef->selector);
3183 }
3184 /* Fields */
3185 if (idcDef->fields != NULL) {
3186 cur = idcDef->fields;
3187 do {
3188 prev = cur;
3189 cur = cur->next;
3190 if (prev->xpathComp != NULL)
3191 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003192 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003193 } while (cur != NULL);
3194 }
3195 xmlFree(idcDef);
3196}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003197
Daniel Veillard01fa6152004-06-29 17:04:39 +00003198/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 * xmlSchemaFreeElement:
3200 * @schema: a schema element structure
3201 *
3202 * Deallocate a Schema Element structure.
3203 */
3204static void
3205xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3206{
3207 if (elem == NULL)
3208 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003209 if (elem->annot != NULL)
3210 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003213 if (elem->defVal != NULL)
3214 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003215 xmlFree(elem);
3216}
3217
3218/**
3219 * xmlSchemaFreeFacet:
3220 * @facet: a schema facet structure
3221 *
3222 * Deallocate a Schema Facet structure.
3223 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003224void
Daniel Veillard4255d502002-04-16 15:50:10 +00003225xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3226{
3227 if (facet == NULL)
3228 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003229 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003230 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003231 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003232 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003233 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003234 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003235 xmlFree(facet);
3236}
3237
3238/**
3239 * xmlSchemaFreeType:
3240 * @type: a schema type structure
3241 *
3242 * Deallocate a Schema Type structure.
3243 */
3244void
3245xmlSchemaFreeType(xmlSchemaTypePtr type)
3246{
3247 if (type == NULL)
3248 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003249 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003250 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003251 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003252 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003253
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003254 facet = type->facets;
3255 while (facet != NULL) {
3256 next = facet->next;
3257 xmlSchemaFreeFacet(facet);
3258 facet = next;
3259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003261 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3262 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003263 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003264 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003265 if (type->memberTypes != NULL)
3266 xmlSchemaFreeTypeLinkList(type->memberTypes);
3267 if (type->facetSet != NULL) {
3268 xmlSchemaFacetLinkPtr next, link;
3269
3270 link = type->facetSet;
3271 do {
3272 next = link->next;
3273 xmlFree(link);
3274 link = next;
3275 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003276 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003277 if (type->contModel != NULL)
3278 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003279 xmlFree(type);
3280}
3281
3282/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003283 * xmlSchemaFreeModelGroupDef:
3284 * @item: a schema model group definition
3285 *
3286 * Deallocates a schema model group definition.
3287 */
3288static void
3289xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3290{
3291 if (item->annot != NULL)
3292 xmlSchemaFreeAnnot(item->annot);
3293 xmlFree(item);
3294}
3295
3296/**
3297 * xmlSchemaFreeModelGroup:
3298 * @item: a schema model group
3299 *
3300 * Deallocates a schema model group structure.
3301 */
3302static void
3303xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3304{
3305 if (item->annot != NULL)
3306 xmlSchemaFreeAnnot(item->annot);
3307 xmlFree(item);
3308}
3309
3310/**
3311 * xmlSchemaFreeParticle:
3312 * @type: a schema type structure
3313 *
3314 * Deallocate a Schema Type structure.
3315 */
3316static void
3317xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3318{
3319 if (item->annot != NULL)
3320 xmlSchemaFreeAnnot(item->annot);
3321 xmlFree(item);
3322}
3323
3324/**
3325 * xmlSchemaFreeMiscComponents:
3326 * @item: a schema component
3327 *
3328 * Deallocates misc. schema component structures.
3329 */
3330static void
3331xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3332{
3333 if (item == NULL)
3334 return;
3335 switch (item->type) {
3336 case XML_SCHEMA_TYPE_PARTICLE:
3337 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3338 return;
3339 case XML_SCHEMA_TYPE_SEQUENCE:
3340 case XML_SCHEMA_TYPE_CHOICE:
3341 case XML_SCHEMA_TYPE_ALL:
3342 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3343 return;
3344 case XML_SCHEMA_TYPE_ANY:
3345 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3346 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3347 break;
3348 default:
3349 /* TODO: This should never be hit. */
3350 TODO
3351 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003352 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003353}
3354
3355static void
3356xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3357{
3358 if (schema->volatiles == NULL)
3359 return;
3360 {
3361 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3362 xmlSchemaTreeItemPtr item;
3363 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003364
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003365 for (i = 0; i < list->nbItems; i++) {
3366 if (list->items[i] != NULL) {
3367 item = (xmlSchemaTreeItemPtr) list->items[i];
3368 switch (item->type) {
3369 case XML_SCHEMA_EXTRA_QNAMEREF:
3370 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3371 break;
3372 default:
3373 xmlSchemaFreeMiscComponents(item);
3374 }
3375 }
3376 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003377 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003378 }
3379}
3380/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003381 * xmlSchemaFreeTypeList:
3382 * @type: a schema type structure
3383 *
3384 * Deallocate a Schema Type structure.
3385 */
3386static void
3387xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3388{
3389 xmlSchemaTypePtr next;
3390
3391 while (type != NULL) {
3392 next = type->redef;
3393 xmlSchemaFreeType(type);
3394 type = next;
3395 }
3396}
3397
3398/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 * xmlSchemaFree:
3400 * @schema: a schema structure
3401 *
3402 * Deallocate a Schema structure.
3403 */
3404void
3405xmlSchemaFree(xmlSchemaPtr schema)
3406{
3407 if (schema == NULL)
3408 return;
3409
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003410 if (schema->volatiles != NULL)
3411 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003412 if (schema->notaDecl != NULL)
3413 xmlHashFree(schema->notaDecl,
3414 (xmlHashDeallocator) xmlSchemaFreeNotation);
3415 if (schema->attrDecl != NULL)
3416 xmlHashFree(schema->attrDecl,
3417 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3418 if (schema->attrgrpDecl != NULL)
3419 xmlHashFree(schema->attrgrpDecl,
3420 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3421 if (schema->elemDecl != NULL)
3422 xmlHashFree(schema->elemDecl,
3423 (xmlHashDeallocator) xmlSchemaFreeElement);
3424 if (schema->typeDecl != NULL)
3425 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003426 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003427 if (schema->groupDecl != NULL)
3428 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003429 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003430 if (schema->idcDef != NULL)
3431 xmlHashFree(schema->idcDef,
3432 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003433 if (schema->schemasImports != NULL)
3434 xmlHashFree(schema->schemasImports,
3435 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003436 if (schema->includes != NULL) {
3437 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3438 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003439 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003440 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003441 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003442 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003443 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003444 xmlFree(schema);
3445}
3446
3447/************************************************************************
3448 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003449 * Debug functions *
3450 * *
3451 ************************************************************************/
3452
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003453#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003454
Daniel Veillard4255d502002-04-16 15:50:10 +00003455/**
3456 * xmlSchemaElementDump:
3457 * @elem: an element
3458 * @output: the file output
3459 *
3460 * Dump the element
3461 */
3462static void
3463xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003464 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003465 const xmlChar * namespace ATTRIBUTE_UNUSED,
3466 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003467{
3468 if (elem == NULL)
3469 return;
3470
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003471 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3472 fprintf(output, "Particle: %s", name);
3473 fprintf(output, ", term element: %s", elem->ref);
3474 if (elem->refNs != NULL)
3475 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003476 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003477 fprintf(output, "Element");
3478 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3479 fprintf(output, " (global)");
3480 fprintf(output, ": %s ", elem->name);
3481 if (namespace != NULL)
3482 fprintf(output, "ns %s", namespace);
3483 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003484 fprintf(output, "\n");
3485 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003486 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003487 if (elem->maxOccurs >= UNBOUNDED)
3488 fprintf(output, "max: unbounded\n");
3489 else if (elem->maxOccurs != 1)
3490 fprintf(output, "max: %d\n", elem->maxOccurs);
3491 else
3492 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003493 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003494 /*
3495 * Misc other properties.
3496 */
3497 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3498 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3499 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3500 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3501 (elem->id != NULL)) {
3502 fprintf(output, " props: ");
3503 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3504 fprintf(output, "[fixed] ");
3505 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3506 fprintf(output, "[default] ");
3507 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3508 fprintf(output, "[abstract] ");
3509 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3510 fprintf(output, "[nillable] ");
3511 if (elem->id != NULL)
3512 fprintf(output, "[id: '%s'] ", elem->id);
3513 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003514 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003515 /*
3516 * Default/fixed value.
3517 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003518 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003519 fprintf(output, " value: '%s'\n", elem->value);
3520 /*
3521 * Type.
3522 */
3523 if (elem->namedType != NULL) {
3524 fprintf(output, " type: %s ", elem->namedType);
3525 if (elem->namedTypeNs != NULL)
3526 fprintf(output, "ns %s\n", elem->namedTypeNs);
3527 else
3528 fprintf(output, "\n");
3529 }
3530 /*
3531 * Substitution group.
3532 */
3533 if (elem->substGroup != NULL) {
3534 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3535 if (elem->substGroupNs != NULL)
3536 fprintf(output, "ns %s\n", elem->substGroupNs);
3537 else
3538 fprintf(output, "\n");
3539 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003540}
3541
3542/**
3543 * xmlSchemaAnnotDump:
3544 * @output: the file output
3545 * @annot: a annotation
3546 *
3547 * Dump the annotation
3548 */
3549static void
3550xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3551{
3552 xmlChar *content;
3553
3554 if (annot == NULL)
3555 return;
3556
3557 content = xmlNodeGetContent(annot->content);
3558 if (content != NULL) {
3559 fprintf(output, " Annot: %s\n", content);
3560 xmlFree(content);
3561 } else
3562 fprintf(output, " Annot: empty\n");
3563}
3564
3565/**
3566 * xmlSchemaTypeDump:
3567 * @output: the file output
3568 * @type: a type structure
3569 *
3570 * Dump a SchemaType structure
3571 */
3572static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003573xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3574{
3575 xmlChar *str = NULL;
3576 xmlSchemaTreeItemPtr term;
3577 char shift[100];
3578 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003579
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003580 if (particle == NULL)
3581 return;
3582 for (i = 0;((i < depth) && (i < 25));i++)
3583 shift[2 * i] = shift[2 * i + 1] = ' ';
3584 shift[2 * i] = shift[2 * i + 1] = 0;
3585 fprintf(output, shift);
3586 if (particle->children == NULL) {
3587 fprintf(output, "MISSING particle term\n");
3588 return;
3589 }
3590 term = particle->children;
3591 switch (term->type) {
3592 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003593 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003594 ((xmlSchemaElementPtr)term)->targetNamespace,
3595 ((xmlSchemaElementPtr)term)->name));
3596 break;
3597 case XML_SCHEMA_TYPE_SEQUENCE:
3598 fprintf(output, "SEQUENCE");
3599 break;
3600 case XML_SCHEMA_TYPE_CHOICE:
3601 fprintf(output, "CHOICE");
3602 break;
3603 case XML_SCHEMA_TYPE_ALL:
3604 fprintf(output, "ALL");
3605 break;
3606 case XML_SCHEMA_TYPE_ANY:
3607 fprintf(output, "ANY");
3608 break;
3609 default:
3610 fprintf(output, "UNKNOWN\n");
3611 return;
3612 }
3613 if (particle->minOccurs != 1)
3614 fprintf(output, " min: %d", particle->minOccurs);
3615 if (particle->maxOccurs >= UNBOUNDED)
3616 fprintf(output, " max: unbounded");
3617 else if (particle->maxOccurs != 1)
3618 fprintf(output, " max: %d", particle->maxOccurs);
3619 fprintf(output, "\n");
3620 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3621 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3622 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3623 (term->children != NULL)) {
3624 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3625 output, depth +1);
3626 }
3627 if (particle->next != NULL)
3628 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3629 output, depth);
3630}
3631/**
3632 * xmlSchemaTypeDump:
3633 * @output: the file output
3634 * @type: a type structure
3635 *
3636 * Dump a SchemaType structure
3637 */
3638static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003639xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3640{
3641 if (type == NULL) {
3642 fprintf(output, "Type: NULL\n");
3643 return;
3644 }
3645 fprintf(output, "Type: ");
3646 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003647 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "no name ");
3650 if (type->targetNamespace != NULL)
3651 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003652 switch (type->type) {
3653 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003654 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003655 break;
3656 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003657 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003658 break;
3659 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003660 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 break;
3662 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003663 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 break;
3665 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003666 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 break;
3668 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003669 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 break;
3671 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003672 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 break;
3674 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003675 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 break;
3677 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003678 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 break;
3680 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003681 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003682 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003683 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003684 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003686 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003687 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 break;
3689 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003690 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003691 break;
3692 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003693 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003694 break;
3695 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003696 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003697 break;
3698 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003699 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003700 break;
3701 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003702 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003703 break;
3704 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003705 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003706 break;
3707 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003708 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 }
3711 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003712 if (type->base != NULL) {
3713 fprintf(output, " base type: %s", type->base);
3714 if (type->baseNs != NULL)
3715 fprintf(output, " ns %s\n", type->baseNs);
3716 else
3717 fprintf(output, "\n");
3718 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 if (type->annot != NULL)
3720 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003721#ifdef DUMP_CONTENT_MODEL
3722 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3723 (type->subtypes != NULL)) {
3724 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3725 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003727#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003728}
3729
3730/**
3731 * xmlSchemaDump:
3732 * @output: the file output
3733 * @schema: a schema structure
3734 *
3735 * Dump a Schema structure.
3736 */
3737void
3738xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3739{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003740 if (output == NULL)
3741 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003742 if (schema == NULL) {
3743 fprintf(output, "Schemas: NULL\n");
3744 return;
3745 }
3746 fprintf(output, "Schemas: ");
3747 if (schema->name != NULL)
3748 fprintf(output, "%s, ", schema->name);
3749 else
3750 fprintf(output, "no name, ");
3751 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003752 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003753 else
3754 fprintf(output, "no target namespace");
3755 fprintf(output, "\n");
3756 if (schema->annot != NULL)
3757 xmlSchemaAnnotDump(output, schema->annot);
3758
3759 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3760 output);
3761 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003762 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003763}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003764
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003765#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003766/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003767 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003768 * @vctxt: the WXS validation context
3769 *
3770 * Displays the current IDC table for debug purposes.
3771 */
3772static void
3773xmlSchemaDebugDumpIDCTable(FILE * output,
3774 const xmlChar *namespaceName,
3775 const xmlChar *localName,
3776 xmlSchemaPSVIIDCBindingPtr bind)
3777{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003778 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003779 xmlSchemaPSVIIDCNodePtr tab;
3780 xmlSchemaPSVIIDCKeyPtr key;
3781 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003782
3783 fprintf(output, "IDC: TABLES on %s\n",
3784 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003785 FREE_AND_NULL(str)
3786
3787 if (bind == NULL)
3788 return;
3789 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003790 fprintf(output, "IDC: BINDING %s\n",
3791 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003792 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003794 for (i = 0; i < bind->nbNodes; i++) {
3795 tab = bind->nodeTable[i];
3796 fprintf(output, " ( ");
3797 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003798 key = tab->keys[j];
3799 if ((key != NULL) && (key->val != NULL)) {
3800 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003801 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003802 fprintf(output, "\"%s\" ", value);
3803 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003804 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003805 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003806 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003807 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003808 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003809 else
3810 fprintf(output, "(key missing), ");
3811 }
3812 fprintf(output, ")\n");
3813 }
3814 bind = bind->next;
3815 } while (bind != NULL);
3816}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003817#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003818#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003819
3820/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003821 * *
3822 * Utilities *
3823 * *
3824 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003825
Daniel Veillardc0826a72004-08-10 14:17:33 +00003826/**
3827 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003828 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003829 * @name: the name of the attribute
3830 *
3831 * Seeks an attribute with a name of @name in
3832 * no namespace.
3833 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003834 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003835 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003836static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003837xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003838{
3839 xmlAttrPtr prop;
3840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003841 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003842 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003843 prop = node->properties;
3844 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003845 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003846 return(prop);
3847 prop = prop->next;
3848 }
3849 return (NULL);
3850}
3851
3852/**
3853 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003854 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003855 * @uri: the uri
3856 * @name: the name of the attribute
3857 *
3858 * Seeks an attribute with a local name of @name and
3859 * a namespace URI of @uri.
3860 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003861 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003862 */
3863static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003864xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003865{
3866 xmlAttrPtr prop;
3867
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003868 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003869 return(NULL);
3870 prop = node->properties;
3871 while (prop != NULL) {
3872 if ((prop->ns != NULL) &&
3873 xmlStrEqual(prop->name, BAD_CAST name) &&
3874 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003875 return(prop);
3876 prop = prop->next;
3877 }
3878 return (NULL);
3879}
3880
3881static const xmlChar *
3882xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3883{
3884 xmlChar *val;
3885 const xmlChar *ret;
3886
3887 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003888 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003889 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003890 ret = xmlDictLookup(ctxt->dict, val, -1);
3891 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003892 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003893}
3894
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003895/**
3896 * xmlSchemaGetProp:
3897 * @ctxt: the parser context
3898 * @node: the node
3899 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003900 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003901 * Read a attribute value and internalize the string
3902 *
3903 * Returns the string or NULL if not present.
3904 */
3905static const xmlChar *
3906xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3907 const char *name)
3908{
3909 xmlChar *val;
3910 const xmlChar *ret;
3911
3912 val = xmlGetProp(node, BAD_CAST name);
3913 if (val == NULL)
3914 return(NULL);
3915 ret = xmlDictLookup(ctxt->dict, val, -1);
3916 xmlFree(val);
3917 return(ret);
3918}
3919
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003920/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003921 * *
3922 * Parsing functions *
3923 * *
3924 ************************************************************************/
3925
3926/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003927 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003928 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003929 * @name: the element name
3930 * @ns: the element namespace
3931 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003932 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003934 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003935 */
3936static xmlSchemaElementPtr
3937xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003938 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003939{
3940 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003941
3942 if ((name == NULL) || (schema == NULL))
3943 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003944
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003945 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003946 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003947 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003949 } else
3950 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003951 /*
3952 * This one was removed, since top level element declarations have
3953 * the target namespace specified in targetNamespace of the <schema>
3954 * information element, even if elementFormDefault is "unqualified".
3955 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003956
William M. Bracke7091952004-05-11 15:09:58 +00003957 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003958 if (xmlStrEqual(namespace, schema->targetNamespace))
3959 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3960 else
3961 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003962 if ((ret != NULL) &&
3963 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003964 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003965 }
William M. Bracke7091952004-05-11 15:09:58 +00003966 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003967
William M. Brack2f2a6632004-08-20 23:09:47 +00003968 /*
3969 * Removed since imported components will be hold by the main schema only.
3970 *
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 Veillardbe9c6322003-11-22 20:37:51 +00003974 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003975 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003976 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003977 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3978 return (ret);
3979 } else
3980 ret = NULL;
3981 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003982 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003983#ifdef DEBUG
3984 if (ret == NULL) {
3985 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003986 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003987 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003988 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003989 namespace);
3990 }
3991#endif
3992 return (ret);
3993}
3994
3995/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003996 * xmlSchemaGetType:
3997 * @schema: the schemas context
3998 * @name: the type name
3999 * @ns: the type namespace
4000 *
4001 * Lookup a type in the schemas or the predefined types
4002 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004003 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004004 */
4005static xmlSchemaTypePtr
4006xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004007 const xmlChar * namespace)
4008{
Daniel Veillard4255d502002-04-16 15:50:10 +00004009 xmlSchemaTypePtr ret;
4010
4011 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004012 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004013 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004014 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004015 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004016 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004017 }
4018 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00004019 if (ret != NULL)
4020 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004021 /*
4022 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004023 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004024 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004025 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004026 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004027 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004028 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004029 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4031 return (ret);
4032 } else
4033 ret = NULL;
4034 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004035 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004036#ifdef DEBUG
4037 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004038 if (namespace == NULL)
4039 fprintf(stderr, "Unable to lookup type %s", name);
4040 else
4041 fprintf(stderr, "Unable to lookup type %s:%s", name,
4042 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004043 }
4044#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004045 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004046}
4047
Daniel Veillard3646d642004-06-02 19:19:14 +00004048/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004049 * xmlSchemaGetAttributeDecl:
4050 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004051 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004052 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004053 *
4054 * Lookup a an attribute in the schema or imported schemas
4055 *
4056 * Returns the attribute declaration or NULL if not found.
4057 */
4058static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004059xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004060 const xmlChar * namespace)
4061{
4062 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004063
4064 if ((name == NULL) || (schema == NULL))
4065 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004066
4067
Daniel Veillard3646d642004-06-02 19:19:14 +00004068 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4069 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004070 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004071 else
4072 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004073 /*
4074 * Removed, since imported components will be hold by the main schema only.
4075 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004076 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004077 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004078 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004079 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004080 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4083 return (ret);
4084 } else
4085 ret = NULL;
4086 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004087 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004088#ifdef DEBUG
4089 if (ret == NULL) {
4090 if (namespace == NULL)
4091 fprintf(stderr, "Unable to lookup attribute %s", name);
4092 else
4093 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4094 namespace);
4095 }
4096#endif
4097 return (ret);
4098}
4099
4100/**
4101 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004102 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004103 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004104 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004105 *
4106 * Lookup a an attribute group in the schema or imported schemas
4107 *
4108 * Returns the attribute group definition or NULL if not found.
4109 */
4110static xmlSchemaAttributeGroupPtr
4111xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4112 const xmlChar * namespace)
4113{
4114 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004115
4116 if ((name == NULL) || (schema == NULL))
4117 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004118
4119
Daniel Veillard3646d642004-06-02 19:19:14 +00004120 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4121 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004122 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004123 else
4124 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004125 /*
4126 * Removed since imported components will be hold by the main schema only.
4127 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004128 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004129 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004131 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004132 if (import != NULL) {
4133 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4134 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4135 return (ret);
4136 else
4137 ret = NULL;
4138 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004139 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004140#ifdef DEBUG
4141 if (ret == NULL) {
4142 if (namespace == NULL)
4143 fprintf(stderr, "Unable to lookup attribute group %s", name);
4144 else
4145 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4146 namespace);
4147 }
4148#endif
4149 return (ret);
4150}
4151
4152/**
4153 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004154 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004155 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004156 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004157 *
4158 * Lookup a group in the schema or imported schemas
4159 *
4160 * Returns the group definition or NULL if not found.
4161 */
4162static xmlSchemaTypePtr
4163xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4164 const xmlChar * namespace)
4165{
4166 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004167
4168 if ((name == NULL) || (schema == NULL))
4169 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004170
Daniel Veillard3646d642004-06-02 19:19:14 +00004171 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004172 /*
4173 * Removed since imported components will be hold by the main schema only.
4174 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004175 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004176 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004177 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004178 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004179 if (import != NULL) {
4180 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4181 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4182 return (ret);
4183 else
4184 ret = NULL;
4185 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004186 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004187#ifdef DEBUG
4188 if (ret == NULL) {
4189 if (namespace == NULL)
4190 fprintf(stderr, "Unable to lookup group %s", name);
4191 else
4192 fprintf(stderr, "Unable to lookup group %s:%s", name,
4193 namespace);
4194 }
4195#endif
4196 return (ret);
4197}
4198
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004199/**
4200 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004201 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004202 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004203 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004204 *
4205 * Lookup a group in the schema or imported schemas
4206 *
4207 * Returns the group definition or NULL if not found.
4208 */
4209static xmlSchemaTreeItemPtr
4210xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4211 xmlSchemaTypeType itemType,
4212 const xmlChar *name,
4213 const xmlChar *targetNs)
4214{
4215 switch (itemType) {
4216 case XML_SCHEMA_TYPE_GROUP:
4217 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4218 name, targetNs));
4219 case XML_SCHEMA_TYPE_ELEMENT:
4220 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4221 name, targetNs));
4222 default:
4223 return (NULL);
4224 }
4225}
4226
Daniel Veillard4255d502002-04-16 15:50:10 +00004227/************************************************************************
4228 * *
4229 * Parsing functions *
4230 * *
4231 ************************************************************************/
4232
4233#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004234 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004235
4236/**
4237 * xmlSchemaIsBlank:
4238 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004239 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004240 *
4241 * Check if a string is ignorable
4242 *
4243 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4244 */
4245static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004246xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247{
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004249 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004250 if (len < 0) {
4251 while (*str != 0) {
4252 if (!(IS_BLANK_CH(*str)))
4253 return (0);
4254 str++;
4255 }
4256 } else while ((*str != 0) && (len != 0)) {
4257 if (!(IS_BLANK_CH(*str)))
4258 return (0);
4259 str++;
4260 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004261 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004262
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004263 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004264}
4265
4266/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004267 * xmlSchemaAddAssembledItem:
4268 * @ctxt: a schema parser context
4269 * @schema: the schema being built
4270 * @item: the item
4271 *
4272 * Add a item to the schema's list of current items.
4273 * This is used if the schema was already constructed and
4274 * new schemata need to be added to it.
4275 * *WARNING* this interface is highly subject to change.
4276 *
4277 * Returns 0 if suceeds and -1 if an internal error occurs.
4278 */
4279static int
4280xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4281 xmlSchemaTypePtr item)
4282{
4283 static int growSize = 100;
4284 xmlSchemaAssemblePtr ass;
4285
4286 ass = ctxt->assemble;
4287 if (ass->sizeItems < 0) {
4288 /* If disabled. */
4289 return (0);
4290 }
4291 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004292 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004293 if (ass->items == NULL) {
4294 xmlSchemaPErrMemory(ctxt,
4295 "allocating new item buffer", NULL);
4296 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004297 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004298 ass->sizeItems = growSize;
4299 } else if (ass->sizeItems <= ass->nbItems) {
4300 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004301 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004302 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4303 if (ass->items == NULL) {
4304 xmlSchemaPErrMemory(ctxt,
4305 "growing item buffer", NULL);
4306 ass->sizeItems = 0;
4307 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004308 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004309 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004310 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004311 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4312 return (0);
4313}
4314
4315/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004316 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004317 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 * @schema: the schema being built
4319 * @name: the item name
4320 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004321 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004322 * *WARNING* this interface is highly subject to change
4323 *
4324 * Returns the new struture or NULL in case of error
4325 */
4326static xmlSchemaNotationPtr
4327xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004328 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004329{
4330 xmlSchemaNotationPtr ret = NULL;
4331 int val;
4332
4333 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4334 return (NULL);
4335
4336 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004337 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 if (schema->notaDecl == NULL)
4339 return (NULL);
4340
4341 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4342 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004343 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 return (NULL);
4345 }
4346 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004347 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4349 ret);
4350 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004351 /*
4352 * TODO: This should never happen, since a unique name will be computed.
4353 * If it fails, then an other internal error must have occured.
4354 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004355 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4356 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004357 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004358 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 xmlFree(ret);
4360 return (NULL);
4361 }
4362 return (ret);
4363}
4364
4365
4366/**
4367 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004368 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 * @schema: the schema being built
4370 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004371 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 *
4373 * Add an XML schema Attrribute declaration
4374 * *WARNING* this interface is highly subject to change
4375 *
4376 * Returns the new struture or NULL in case of error
4377 */
4378static xmlSchemaAttributePtr
4379xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004380 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004381 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004382{
4383 xmlSchemaAttributePtr ret = NULL;
4384 int val;
4385
4386 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4387 return (NULL);
4388
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004389#ifdef DEBUG
4390 fprintf(stderr, "Adding attribute %s\n", name);
4391 if (namespace != NULL)
4392 fprintf(stderr, " target namespace %s\n", namespace);
4393#endif
4394
Daniel Veillard4255d502002-04-16 15:50:10 +00004395 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004396 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 if (schema->attrDecl == NULL)
4398 return (NULL);
4399
4400 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4401 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 return (NULL);
4404 }
4405 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004406 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004407 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004409 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004411 if (topLevel) {
4412 xmlSchemaPCustomErr(ctxt,
4413 XML_SCHEMAP_REDEFINED_ATTR,
4414 NULL, NULL, node,
4415 "A global attribute declaration with the name '%s' does "
4416 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004417 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004418 return (NULL);
4419 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004420 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004421 /*
4422 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4423 * in the scenario:
4424 * 1. multiple top-level complex types have different target
4425 * namespaces but have the SAME NAME; this can happen if
4426 * schemata are imported
4427 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004428 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004429 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004430 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004431 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004432 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004433 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004434
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004435 if (val != 0) {
4436 xmlSchemaPCustomErr(ctxt,
4437 XML_SCHEMAP_INTERNAL,
4438 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004439 "Internal error: xmlSchemaAddAttribute, "
4440 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004441 "could not be added to the hash.", name);
4442 xmlFree(ret);
4443 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004444 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004445 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004447 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004448 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 return (ret);
4450}
4451
4452/**
4453 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004454 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004455 * @schema: the schema being built
4456 * @name: the item name
4457 *
4458 * Add an XML schema Attrribute Group declaration
4459 *
4460 * Returns the new struture or NULL in case of error
4461 */
4462static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004463xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004464 xmlSchemaPtr schema, const xmlChar * name,
4465 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004466{
4467 xmlSchemaAttributeGroupPtr ret = NULL;
4468 int val;
4469
4470 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4471 return (NULL);
4472
4473 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004474 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004475 if (schema->attrgrpDecl == NULL)
4476 return (NULL);
4477
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004478 ret =
4479 (xmlSchemaAttributeGroupPtr)
4480 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004482 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004483 return (NULL);
4484 }
4485 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004486 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004487 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004488 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004489 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004490 xmlSchemaPCustomErr(ctxt,
4491 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4492 NULL, NULL, node,
4493 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004494 xmlFree(ret);
4495 return (NULL);
4496 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004497 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004498 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004499 return (ret);
4500}
4501
4502/**
4503 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004504 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 * @schema: the schema being built
4506 * @name: the type name
4507 * @namespace: the type namespace
4508 *
4509 * Add an XML schema Element declaration
4510 * *WARNING* this interface is highly subject to change
4511 *
4512 * Returns the new struture or NULL in case of error
4513 */
4514static xmlSchemaElementPtr
4515xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004516 const xmlChar * name, const xmlChar * namespace,
4517 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004518{
4519 xmlSchemaElementPtr ret = NULL;
4520 int val;
4521
4522 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4523 return (NULL);
4524
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004525#ifdef DEBUG
4526 fprintf(stderr, "Adding element %s\n", name);
4527 if (namespace != NULL)
4528 fprintf(stderr, " target namespace %s\n", namespace);
4529#endif
4530
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004532 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 if (schema->elemDecl == NULL)
4534 return (NULL);
4535
4536 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4537 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004538 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 return (NULL);
4540 }
4541 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004544 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004546 if (topLevel) {
4547 xmlSchemaPCustomErr(ctxt,
4548 XML_SCHEMAP_REDEFINED_ELEMENT,
4549 NULL, NULL, node,
4550 "A global element declaration with the name '%s' does "
4551 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004552 xmlFree(ret);
4553 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004554 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004555 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004556
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004557 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004558 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004559 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004560 if (val != 0) {
4561 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004562 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004563 NULL, NULL, node,
4564 "Internal error: xmlSchemaAddElement, "
4565 "a dublicate element declaration with the name '%s' "
4566 "could not be added to the hash.", name);
4567 xmlFree(ret);
4568 return (NULL);
4569 }
4570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004571
Daniel Veillard4255d502002-04-16 15:50:10 +00004572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004573 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004574 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004575 return (ret);
4576}
4577
4578/**
4579 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004580 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004581 * @schema: the schema being built
4582 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004583 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004584 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004585 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004586 * *WARNING* this interface is highly subject to change
4587 *
4588 * Returns the new struture or NULL in case of error
4589 */
4590static xmlSchemaTypePtr
4591xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004592 const xmlChar * name, const xmlChar * namespace,
4593 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004594{
4595 xmlSchemaTypePtr ret = NULL;
4596 int val;
4597
4598 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4599 return (NULL);
4600
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004601#ifdef DEBUG
4602 fprintf(stderr, "Adding type %s\n", name);
4603 if (namespace != NULL)
4604 fprintf(stderr, " target namespace %s\n", namespace);
4605#endif
4606
Daniel Veillard4255d502002-04-16 15:50:10 +00004607 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004608 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004609 if (schema->typeDecl == NULL)
4610 return (NULL);
4611
4612 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4613 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004614 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004615 return (NULL);
4616 }
4617 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004618 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004619 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004620 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004621 if (val != 0) {
4622 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004623 xmlSchemaPCustomErr(ctxt,
4624 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004625 NULL, NULL, node,
4626 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004627 xmlFree(ret);
4628 return (NULL);
4629 } else {
4630 xmlSchemaTypePtr prev;
4631
4632 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4633 if (prev == NULL) {
4634 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004635 XML_ERR_INTERNAL_ERROR,
4636 "Internal error: xmlSchemaAddType, on type "
4637 "'%s'.\n",
4638 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004639 xmlFree(ret);
4640 return (NULL);
4641 }
4642 ret->redef = prev->redef;
4643 prev->redef = ret;
4644 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004645 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004646 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004647 ret->minOccurs = 1;
4648 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004649 ret->attributeUses = NULL;
4650 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004651 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004652 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004653 return (ret);
4654}
4655
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004656static xmlSchemaQNameRefPtr
4657xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4658 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004659 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004660 const xmlChar *refNs)
4661{
4662 xmlSchemaQNameRefPtr ret;
4663
4664 ret = (xmlSchemaQNameRefPtr)
4665 xmlMalloc(sizeof(xmlSchemaQNameRef));
4666 if (ret == NULL) {
4667 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4668 NULL);
4669 return (NULL);
4670 }
4671 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4672 ret->name = refName;
4673 ret->targetNamespace = refNs;
4674 ret->item = NULL;
4675 ret->itemType = refType;
4676 /*
4677 * Store the reference item in the schema.
4678 */
4679 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4680 return (ret);
4681}
4682
4683/**
4684 * xmlSchemaAddModelGroup:
4685 * @ctxt: a schema parser context
4686 * @schema: the schema being built
4687 * @type: the "compositor" type of the model group
4688 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004689 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004690 *
4691 * Adds a schema model group
4692 * *WARNING* this interface is highly subject to change
4693 *
4694 * Returns the new struture or NULL in case of error
4695 */
4696static xmlSchemaModelGroupPtr
4697xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4698 xmlSchemaTypeType type, const xmlChar **container,
4699 xmlNodePtr node)
4700{
4701 xmlSchemaModelGroupPtr ret = NULL;
4702 xmlChar buf[30];
4703
4704 if ((ctxt == NULL) || (schema == NULL))
4705 return (NULL);
4706
4707#ifdef DEBUG
4708 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004709#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004710 ret = (xmlSchemaModelGroupPtr)
4711 xmlMalloc(sizeof(xmlSchemaModelGroup));
4712 if (ret == NULL) {
4713 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4714 NULL);
4715 return (NULL);
4716 }
4717 ret->type = type;
4718 ret->annot = NULL;
4719 ret->node = node;
4720 ret->children = NULL;
4721 ret->next = NULL;
4722 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4723 if (container != NULL)
4724 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4725 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004726 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004727 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4728 } else {
4729 if (container != NULL)
4730 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4731 }
4732 if (container != NULL)
4733 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4734 /*
4735 * Add to volatile items.
4736 * TODO: this should be changed someday.
4737 */
4738 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4739 xmlFree(ret);
4740 return (NULL);
4741 }
4742 return (ret);
4743}
4744
4745
4746/**
4747 * xmlSchemaAddParticle:
4748 * @ctxt: a schema parser context
4749 * @schema: the schema being built
4750 * @node: the corresponding node in the schema doc
4751 * @min: the minOccurs
4752 * @max: the maxOccurs
4753 *
4754 * Adds an XML schema particle component.
4755 * *WARNING* this interface is highly subject to change
4756 *
4757 * Returns the new struture or NULL in case of error
4758 */
4759static xmlSchemaParticlePtr
4760xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4761 xmlNodePtr node, int min, int max)
4762{
4763 xmlSchemaParticlePtr ret = NULL;
4764 if ((ctxt == NULL) || (schema == NULL))
4765 return (NULL);
4766
4767#ifdef DEBUG
4768 fprintf(stderr, "Adding particle component\n");
4769#endif
4770 ret = (xmlSchemaParticlePtr)
4771 xmlMalloc(sizeof(xmlSchemaParticle));
4772 if (ret == NULL) {
4773 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4774 NULL);
4775 return (NULL);
4776 }
4777 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4778 ret->annot = NULL;
4779 ret->node = node;
4780 ret->minOccurs = min;
4781 ret->maxOccurs = max;
4782 ret->next = NULL;
4783 ret->children = NULL;
4784
4785 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4786 xmlFree(ret);
4787 return (NULL);
4788 }
4789 return (ret);
4790}
4791
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004792/**
4793 * xmlSchemaAddGroup:
4794 * @ctxt: a schema validation context
4795 * @schema: the schema being built
4796 * @name: the group name
4797 *
4798 * Add an XML schema Group definition
4799 *
4800 * Returns the new struture or NULL in case of error
4801 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004802static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004803xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004804 const xmlChar *name, const xmlChar *namespaceName,
4805 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004806{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004807 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004808 int val;
4809
4810 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4811 return (NULL);
4812
4813 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004814 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004815 if (schema->groupDecl == NULL)
4816 return (NULL);
4817
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004818 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004819 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004821 return (NULL);
4822 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004823 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004824 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004825 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004826 ret->node = node;
4827 ret->targetNamespace = namespaceName;
4828 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004829 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004830 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004831 XML_SCHEMAP_REDEFINED_GROUP,
4832 NULL, NULL, node,
4833 "A global model group definition with the name '%s' does already "
4834 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004835 xmlFree(ret);
4836 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004837 }
4838 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004839 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004840 return (ret);
4841}
4842
Daniel Veillard3646d642004-06-02 19:19:14 +00004843/**
4844 * xmlSchemaNewWildcardNs:
4845 * @ctxt: a schema validation context
4846 *
4847 * Creates a new wildcard namespace constraint.
4848 *
4849 * Returns the new struture or NULL in case of error
4850 */
4851static xmlSchemaWildcardNsPtr
4852xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4853{
4854 xmlSchemaWildcardNsPtr ret;
4855
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004856 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004857 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4858 if (ret == NULL) {
4859 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004860 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004861 }
4862 ret->value = NULL;
4863 ret->next = NULL;
4864 return (ret);
4865}
4866
4867/**
4868 * xmlSchemaAddWildcard:
4869 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004870 * @schema: a schema
4871 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004872 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004873 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004874 *
4875 * Returns the new struture or NULL in case of error
4876 */
4877static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004878xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4879 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004880{
4881 xmlSchemaWildcardPtr ret = NULL;
4882
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004883 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004884 return (NULL);
4885
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004886#ifdef DEBUG
4887 fprintf(stderr, "Adding wildcard component\n");
4888#endif
4889
Daniel Veillard3646d642004-06-02 19:19:14 +00004890 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4891 if (ret == NULL) {
4892 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4893 return (NULL);
4894 }
4895 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004896 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004897 ret->minOccurs = 1;
4898 ret->maxOccurs = 1;
4899
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004900 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4901 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4902 "Failed to add a wildcard component to the list", NULL);
4903 xmlFree(ret);
4904 return (NULL);
4905 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004906 return (ret);
4907}
4908
Daniel Veillard4255d502002-04-16 15:50:10 +00004909/************************************************************************
4910 * *
4911 * Utilities for parsing *
4912 * *
4913 ************************************************************************/
4914
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004915#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004916/**
4917 * xmlGetQNameProp:
4918 * @ctxt: a schema validation context
4919 * @node: a subtree containing XML Schema informations
4920 * @name: the attribute name
4921 * @namespace: the result namespace if any
4922 *
4923 * Extract a QName Attribute value
4924 *
4925 * Returns the NCName or NULL if not found, and also update @namespace
4926 * with the namespace URI
4927 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004928static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004929xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004930 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004931{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004932 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004933 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004934 const xmlChar *ret, *prefix;
4935 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004936 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004937
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004938 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004939 attr = xmlSchemaGetPropNode(node, name);
4940 if (attr == NULL)
4941 return (NULL);
4942 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004943
Daniel Veillard4255d502002-04-16 15:50:10 +00004944 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004945 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004946
Daniel Veillardba0153a2004-04-01 10:42:31 +00004947 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004948 ns = xmlSearchNs(node->doc, node, 0);
4949 if (ns) {
4950 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4951 return (val);
4952 }
4953 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004954 ret = xmlSplitQName3(val, &len);
4955 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004956 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004957 }
4958 ret = xmlDictLookup(ctxt->dict, ret, -1);
4959 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004960
4961 ns = xmlSearchNs(node->doc, node, prefix);
4962 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004963 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4964 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004965 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004966 "The QName value '%s' has no corresponding namespace "
4967 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004968 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004969 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004970 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004972}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004973#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004974
4975/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004976 * xmlSchemaPValAttrNodeQNameValue:
4977 * @ctxt: a schema parser context
4978 * @schema: the schema context
4979 * @ownerDes: the designation of the parent element
4980 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004981 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004982 * @local: the resulting local part if found, the attribute value otherwise
4983 * @uri: the resulting namespace URI if found
4984 *
4985 * Extracts the local name and the URI of a QName value and validates it.
4986 * This one is intended to be used on attribute values that
4987 * should resolve to schema components.
4988 *
4989 * Returns 0, in case the QName is valid, a positive error code
4990 * if not valid and -1 if an internal error occurs.
4991 */
4992static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004993xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004994 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004995 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004996 xmlSchemaTypePtr ownerItem,
4997 xmlAttrPtr attr,
4998 const xmlChar *value,
4999 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005000 const xmlChar **local)
5001{
5002 const xmlChar *pref;
5003 xmlNsPtr ns;
5004 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005005
Daniel Veillardc0826a72004-08-10 14:17:33 +00005006 *uri = NULL;
5007 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005008 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005009 if (ret > 0) {
5010 xmlSchemaPSimpleTypeErr(ctxt,
5011 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5012 ownerItem, (xmlNodePtr) attr,
5013 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5014 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005015 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005016 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005017 } else if (ret < 0)
5018 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005019
5020 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 ns = xmlSearchNs(attr->doc, attr->parent, 0);
5022 if (ns)
5023 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5024 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5025 /*
5026 * This one takes care of included schemas with no
5027 * target namespace.
5028 */
5029 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005030 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005031 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005032 return (0);
5033 }
5034 /*
5035 * At this point xmlSplitQName3 has to return a local name.
5036 */
5037 *local = xmlSplitQName3(value, &len);
5038 *local = xmlDictLookup(ctxt->dict, *local, -1);
5039 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005040 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5041 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005042 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005043 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005044 ownerItem, (xmlNodePtr) attr,
5045 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5046 "The value '%s' of simple type 'xs:QName' has no "
5047 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005048 return (ctxt->err);
5049 } else {
5050 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005051 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005052 return (0);
5053}
5054
5055/**
5056 * xmlSchemaPValAttrNodeQName:
5057 * @ctxt: a schema parser context
5058 * @schema: the schema context
5059 * @ownerDes: the designation of the owner element
5060 * @ownerItem: the owner as a schema object
5061 * @attr: the attribute node
5062 * @local: the resulting local part if found, the attribute value otherwise
5063 * @uri: the resulting namespace URI if found
5064 *
5065 * Extracts and validates the QName of an attribute value.
5066 * This one is intended to be used on attribute values that
5067 * should resolve to schema components.
5068 *
5069 * Returns 0, in case the QName is valid, a positive error code
5070 * if not valid and -1 if an internal error occurs.
5071 */
5072static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005073xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005074 xmlSchemaPtr schema,
5075 xmlChar **ownerDes,
5076 xmlSchemaTypePtr ownerItem,
5077 xmlAttrPtr attr,
5078 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005079 const xmlChar **local)
5080{
5081 const xmlChar *value;
5082
5083 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005084 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5085 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005086}
5087
5088/**
5089 * xmlSchemaPValAttrQName:
5090 * @ctxt: a schema parser context
5091 * @schema: the schema context
5092 * @ownerDes: the designation of the parent element
5093 * @ownerItem: the owner as a schema object
5094 * @ownerElem: the parent node of the attribute
5095 * @name: the name of the attribute
5096 * @local: the resulting local part if found, the attribute value otherwise
5097 * @uri: the resulting namespace URI if found
5098 *
5099 * Extracts and validates the QName of an attribute value.
5100 *
5101 * Returns 0, in case the QName is valid, a positive error code
5102 * if not valid and -1 if an internal error occurs.
5103 */
5104static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005105xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5106 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005107 xmlChar **ownerDes,
5108 xmlSchemaTypePtr ownerItem,
5109 xmlNodePtr ownerElem,
5110 const char *name,
5111 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005112 const xmlChar **local)
5113{
5114 xmlAttrPtr attr;
5115
5116 attr = xmlSchemaGetPropNode(ownerElem, name);
5117 if (attr == NULL) {
5118 *local = NULL;
5119 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005120 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005121 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005122 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5123 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005124}
5125
5126/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005127 * xmlSchemaPValAttrID:
5128 * @ctxt: a schema parser context
5129 * @schema: the schema context
5130 * @ownerDes: the designation of the parent element
5131 * @ownerItem: the owner as a schema object
5132 * @ownerElem: the parent node of the attribute
5133 * @name: the name of the attribute
5134 *
5135 * Extracts and validates the ID of an attribute value.
5136 *
5137 * Returns 0, in case the ID is valid, a positive error code
5138 * if not valid and -1 if an internal error occurs.
5139 */
5140static int
5141xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005142 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005143 xmlSchemaTypePtr ownerItem,
5144 xmlNodePtr ownerElem,
5145 const xmlChar *name)
5146{
5147 int ret;
5148 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005149 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005150
5151 value = xmlGetNoNsProp(ownerElem, name);
5152 if (value == NULL)
5153 return (0);
5154
5155 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5156 if (attr == NULL)
5157 return (-1);
5158
5159 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005160 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005161 /*
5162 * NOTE: the IDness might have already be declared in the DTD
5163 */
5164 if (attr->atype != XML_ATTRIBUTE_ID) {
5165 xmlIDPtr res;
5166 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005167
5168 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005169 * TODO: Use xmlSchemaStrip here; it's not exported at this
5170 * moment.
5171 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005172 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005173 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005174 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005175 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5176 if (res == NULL) {
5177 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005178 xmlSchemaPSimpleTypeErr(ctxt,
5179 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5180 ownerItem, (xmlNodePtr) attr,
5181 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5182 NULL, NULL, "Duplicate value '%s' of simple "
5183 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005184 } else
5185 attr->atype = XML_ATTRIBUTE_ID;
5186 if (strip != NULL)
5187 xmlFree(strip);
5188 }
5189 } else if (ret > 0) {
5190 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005191 xmlSchemaPSimpleTypeErr(ctxt,
5192 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5193 ownerItem, (xmlNodePtr) attr,
5194 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5195 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5196 "not a valid 'xs:NCName'",
5197 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005198 }
5199 xmlFree(value);
5200
5201 return (ret);
5202}
5203
5204/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005205 * xmlGetMaxOccurs:
5206 * @ctxt: a schema validation context
5207 * @node: a subtree containing XML Schema informations
5208 *
5209 * Get the maxOccurs property
5210 *
5211 * Returns the default if not found, or the value
5212 */
5213static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5215 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005216{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005217 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005218 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005219 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005220
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005221 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5222 if (attr == NULL)
5223 return (def);
5224 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005225
5226 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005227 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005228 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005229 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5230 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005231 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005232 val, NULL, NULL, NULL);
5233 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005234 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005235 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 }
5237
5238 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005239 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005241 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005242 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5244 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005245 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005246 val, NULL, NULL, NULL);
5247 return (def);
5248 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250 ret = ret * 10 + (*cur - '0');
5251 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 }
William M. Brack76e95df2003-10-18 16:20:14 +00005253 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005254 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005255 /*
5256 * TODO: Restrict the maximal value to Integer.
5257 */
5258 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005259 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005260 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5261 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005262 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005263 val, NULL, NULL, NULL);
5264 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005265 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005266 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005267}
5268
5269/**
5270 * xmlGetMinOccurs:
5271 * @ctxt: a schema validation context
5272 * @node: a subtree containing XML Schema informations
5273 *
5274 * Get the minOccurs property
5275 *
5276 * Returns the default if not found, or the value
5277 */
5278static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005279xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005280 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005281{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005282 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005283 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005284 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005285
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005286 attr = xmlSchemaGetPropNode(node, "minOccurs");
5287 if (attr == NULL)
5288 return (def);
5289 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005290 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005291 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005292 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005293 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005294 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005295 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5296 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005297 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005298 val, NULL, NULL, NULL);
5299 return (def);
5300 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005301 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005302 ret = ret * 10 + (*cur - '0');
5303 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 }
William M. Brack76e95df2003-10-18 16:20:14 +00005305 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005306 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005307 /*
5308 * TODO: Restrict the maximal value to Integer.
5309 */
5310 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005311 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005312 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5313 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005314 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005315 val, NULL, NULL, NULL);
5316 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005318 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005319}
5320
5321/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005322 * xmlSchemaPGetBoolNodeValue:
5323 * @ctxt: a schema validation context
5324 * @ownerDes: owner designation
5325 * @ownerItem: the owner as a schema item
5326 * @node: the node holding the value
5327 *
5328 * Converts a boolean string value into 1 or 0.
5329 *
5330 * Returns 0 or 1.
5331 */
5332static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005333xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5334 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005335 xmlSchemaTypePtr ownerItem,
5336 xmlNodePtr node)
5337{
5338 xmlChar *value = NULL;
5339 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005340
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005341 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005342 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005343 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005344 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005345 * can have the following legal literals {true, false, 1, 0}.
5346 */
5347 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5348 res = 1;
5349 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5350 res = 0;
5351 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5352 res = 1;
5353 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005354 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005355 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005356 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005357 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005358 ownerItem, node,
5359 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5360 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005361 NULL, NULL, NULL);
5362 }
5363 if (value != NULL)
5364 xmlFree(value);
5365 return (res);
5366}
5367
5368/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005369 * xmlGetBooleanProp:
5370 * @ctxt: a schema validation context
5371 * @node: a subtree containing XML Schema informations
5372 * @name: the attribute name
5373 * @def: the default value
5374 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005375 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005376 *
5377 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005378 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005379 */
5380static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005381xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5382 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005383 xmlSchemaTypePtr ownerItem,
5384 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005385 const char *name, int def)
5386{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005387 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005388
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005389 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005390 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005391 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005392 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005393 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005394 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005395 * can have the following legal literals {true, false, 1, 0}.
5396 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005397 if (xmlStrEqual(val, BAD_CAST "true"))
5398 def = 1;
5399 else if (xmlStrEqual(val, BAD_CAST "false"))
5400 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005401 else if (xmlStrEqual(val, BAD_CAST "1"))
5402 def = 1;
5403 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005404 def = 0;
5405 else {
5406 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005407 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005408 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005409 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005410 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5411 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005412 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005414}
5415
5416/************************************************************************
5417 * *
5418 * Shema extraction from an Infoset *
5419 * *
5420 ************************************************************************/
5421static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5422 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005423 xmlNodePtr node,
5424 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005425static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5426 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005427 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005429 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005430static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5431 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005432 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005433 xmlNodePtr node,
5434 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005435static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5436 ctxt,
5437 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005438 xmlNodePtr node,
5439 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005440static xmlSchemaAttributeGroupPtr
5441xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005442 xmlSchemaPtr schema, xmlNodePtr node,
5443 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005444static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5445 xmlSchemaPtr schema,
5446 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005447static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005448xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5449 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005450
5451/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005452 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005453 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005454 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005455 * @ownerDes: the designation of the parent element
5456 * @ownerItem: the schema object owner if existent
5457 * @attr: the schema attribute node being validated
5458 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005460 *
5461 * Validates a value against the given built-in type.
5462 * This one is intended to be used internally for validation
5463 * of schema attribute values during parsing of the schema.
5464 *
5465 * Returns 0 if the value is valid, a positive error code
5466 * number otherwise and -1 in case of an internal or API error.
5467 */
5468static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005469xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5470 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5471 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005472 xmlAttrPtr attr,
5473 const xmlChar *value,
5474 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005476
5477 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005478
5479 /*
5480 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5481 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005482 */
5483 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005484 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005485 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5486 PERROR_INT("xmlSchemaPValAttrNodeValue",
5487 "the given type is not a built-in type");
5488 return (-1);
5489 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005490 switch (type->builtInType) {
5491 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005492 case XML_SCHEMAS_QNAME:
5493 case XML_SCHEMAS_ANYURI:
5494 case XML_SCHEMAS_TOKEN:
5495 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005496 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5497 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005498 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005499 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005500 PERROR_INT("xmlSchemaPValAttrNodeValue",
5501 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005502 return (-1);
5503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005504 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 /*
5506 * TODO: Should we use the S4S error codes instead?
5507 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005508 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005509 PERROR_INT("xmlSchemaPValAttrNodeValue",
5510 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005511 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005512 } else if (ret > 0) {
5513 if (VARIETY_LIST(type))
5514 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5515 else
5516 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5517 xmlSchemaPSimpleTypeErr(pctxt,
5518 ret, ownerItem, (xmlNodePtr) attr,
5519 type, NULL, value, NULL, NULL, NULL);
5520 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005521 return (ret);
5522}
5523
5524/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005525 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005526 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005527 * @ctxt: a schema parser context
5528 * @ownerDes: the designation of the parent element
5529 * @ownerItem: the schema object owner if existent
5530 * @attr: the schema attribute node being validated
5531 * @type: the built-in type to be validated against
5532 * @value: the resulting value if any
5533 *
5534 * Extracts and validates a value against the given built-in type.
5535 * This one is intended to be used internally for validation
5536 * of schema attribute values during parsing of the schema.
5537 *
5538 * Returns 0 if the value is valid, a positive error code
5539 * number otherwise and -1 in case of an internal or API error.
5540 */
5541static int
5542xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5543 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005544 xmlSchemaTypePtr ownerItem,
5545 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 xmlSchemaTypePtr type,
5547 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005548{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005549 const xmlChar *val;
5550
5551 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005552 return (-1);
5553
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5555 if (value != NULL)
5556 *value = val;
5557
5558 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005560}
5561
5562/**
5563 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005564 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005565 * @ctxt: a schema parser context
5566 * @node: the element node of the attribute
5567 * @ownerDes: the designation of the parent element
5568 * @ownerItem: the schema object owner if existent
5569 * @ownerElem: the owner element node
5570 * @name: the name of the schema attribute node
5571 * @type: the built-in type to be validated against
5572 * @value: the resulting value if any
5573 *
5574 * Extracts and validates a value against the given built-in type.
5575 * This one is intended to be used internally for validation
5576 * of schema attribute values during parsing of the schema.
5577 *
5578 * Returns 0 if the value is valid, a positive error code
5579 * number otherwise and -1 in case of an internal or API error.
5580 */
5581static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005582xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 xmlChar **ownerDes,
5584 xmlSchemaTypePtr ownerItem,
5585 xmlNodePtr ownerElem,
5586 const char *name,
5587 xmlSchemaTypePtr type,
5588 const xmlChar **value)
5589{
5590 xmlAttrPtr attr;
5591
5592 if ((ctxt == NULL) || (type == NULL)) {
5593 if (value != NULL)
5594 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005595 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596 }
5597 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5598 if (value != NULL)
5599 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005600 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005601 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005602 "Internal error: xmlSchemaPValAttr, the given "
5603 "type '%s' is not a built-in type.\n",
5604 type->name, NULL);
5605 return (-1);
5606 }
5607 attr = xmlSchemaGetPropNode(ownerElem, name);
5608 if (attr == NULL) {
5609 if (value != NULL)
5610 *value = NULL;
5611 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005612 }
5613 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 type, value));
5615}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005616
5617static int
5618xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5619 xmlSchemaPtr schema,
5620 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005621 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005622 const xmlChar *namespaceName)
5623{
5624 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005625 return (1);
5626 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5627 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005628 if (pctxt->localImports != NULL) {
5629 int i;
5630 for (i = 0; i < pctxt->nbLocalImports; i++)
5631 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5632 return (1);
5633 }
5634 if (namespaceName == NULL)
5635 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005636 NULL, (xmlSchemaTypePtr) item, node,
5637 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005638 "namespace are not valid, since not indicated by an import "
5639 "statement", NULL);
5640 else
5641 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005642 NULL, (xmlSchemaTypePtr) item, node,
5643 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005644 "namespace '%s' are not valid, since not indicated by an import "
5645 "statement", namespaceName);
5646 return (0);
5647}
5648
Daniel Veillardc0826a72004-08-10 14:17:33 +00005649/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005650 * xmlSchemaParseAttrDecls:
5651 * @ctxt: a schema validation context
5652 * @schema: the schema being built
5653 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005654 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 *
5656 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005657 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005658 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5659 */
5660static xmlNodePtr
5661xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5662 xmlNodePtr child, xmlSchemaTypePtr type)
5663{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005664 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005665
Daniel Veillard4255d502002-04-16 15:50:10 +00005666 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005667 (IS_SCHEMA(child, "attributeGroup"))) {
5668 attr = NULL;
5669 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005670 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005671 } else if (IS_SCHEMA(child, "attributeGroup")) {
5672 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005673 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005674 }
5675 if (attr != NULL) {
5676 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005677 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5678 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5679 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005680 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005681 lastattr = attr;
5682 } else {
5683 lastattr->next = attr;
5684 lastattr = attr;
5685 }
5686 }
5687 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005688 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005689 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005690}
5691
5692/**
5693 * xmlSchemaParseAnnotation:
5694 * @ctxt: a schema validation context
5695 * @schema: the schema being built
5696 * @node: a subtree containing XML Schema informations
5697 *
5698 * parse a XML schema Attrribute declaration
5699 * *WARNING* this interface is highly subject to change
5700 *
William M. Bracke7091952004-05-11 15:09:58 +00005701 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005702 * 1 in case of success.
5703 */
5704static xmlSchemaAnnotPtr
5705xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5706 xmlNodePtr node)
5707{
5708 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005709 xmlNodePtr child = NULL;
5710 xmlAttrPtr attr;
5711 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005712
Daniel Veillardc0826a72004-08-10 14:17:33 +00005713 /*
5714 * INFO: S4S completed.
5715 */
5716 /*
5717 * id = ID
5718 * {any attributes with non-schema namespace . . .}>
5719 * Content: (appinfo | documentation)*
5720 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005721 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5722 return (NULL);
5723 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 attr = node->properties;
5725 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005726 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005727 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005728 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005729 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005730
5731 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005732 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5733 NULL, NULL, attr);
5734 }
5735 attr = attr->next;
5736 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005737 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005738 /*
5739 * And now for the children...
5740 */
5741 child = node->children;
5742 while (child != NULL) {
5743 if (IS_SCHEMA(child, "appinfo")) {
5744 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005745 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 * source = anyURI
5747 * {any attributes with non-schema namespace . . .}>
5748 * Content: ({any})*
5749 */
5750 attr = child->properties;
5751 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005752 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005754 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005755 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005756
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005757 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005758 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5759 NULL, NULL, attr);
5760 }
5761 attr = attr->next;
5762 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005763 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5764 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005765 child = child->next;
5766 } else if (IS_SCHEMA(child, "documentation")) {
5767 /* TODO: make available the content of "documentation". */
5768 /*
5769 * source = anyURI
5770 * {any attributes with non-schema namespace . . .}>
5771 * Content: ({any})*
5772 */
5773 attr = child->properties;
5774 while (attr != NULL) {
5775 if (attr->ns == NULL) {
5776 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005777 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005778 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5779 NULL, NULL, attr);
5780 }
5781 } else {
5782 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5783 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5784 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005785
5786 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005787 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5788 NULL, NULL, attr);
5789 }
5790 }
5791 attr = attr->next;
5792 }
5793 /*
5794 * Attribute "xml:lang".
5795 */
5796 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5797 if (attr != NULL)
5798 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005799 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005800 child = child->next;
5801 } else {
5802 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005803 xmlSchemaPContentErr(ctxt,
5804 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005805 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5806 barked = 1;
5807 child = child->next;
5808 }
5809 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005810
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 return (ret);
5812}
5813
5814/**
5815 * xmlSchemaParseFacet:
5816 * @ctxt: a schema validation context
5817 * @schema: the schema being built
5818 * @node: a subtree containing XML Schema informations
5819 *
5820 * parse a XML schema Facet declaration
5821 * *WARNING* this interface is highly subject to change
5822 *
5823 * Returns the new type structure or NULL in case of error
5824 */
5825static xmlSchemaFacetPtr
5826xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005827 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005828{
5829 xmlSchemaFacetPtr facet;
5830 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005831 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005832
5833 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5834 return (NULL);
5835
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005836 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005837 if (facet == NULL) {
5838 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5839 return (NULL);
5840 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005841 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005842 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005843 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005844 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5845 "Facet %s has no value\n", node->name, NULL);
5846 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 return (NULL);
5848 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005849 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005851 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005852 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005853 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005854 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005855 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005857 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005858 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005859 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005860 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005861 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005862 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005863 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005864 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005865 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005866 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005867 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005868 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005869 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005870 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5871 } else if (IS_SCHEMA(node, "minLength")) {
5872 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5873 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005874 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5875 "Unknown facet type %s\n", node->name, NULL);
5876 xmlSchemaFreeFacet(facet);
5877 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005878 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005879 xmlSchemaPValAttrID(ctxt, NULL,
5880 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005881 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005882 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5883 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5884 const xmlChar *fixed;
5885
5886 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5887 if (fixed != NULL) {
5888 if (xmlStrEqual(fixed, BAD_CAST "true"))
5889 facet->fixed = 1;
5890 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005891 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005892 child = node->children;
5893
5894 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005895 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5896 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005897 }
5898 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005899 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5900 "Facet %s has unexpected child content\n",
5901 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005902 }
5903 return (facet);
5904}
5905
5906/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005907 * xmlSchemaParseWildcardNs:
5908 * @ctxt: a schema parser context
5909 * @wildc: the wildcard, already created
5910 * @node: a subtree containing XML Schema informations
5911 *
5912 * Parses the attribute "processContents" and "namespace"
5913 * of a xsd:anyAttribute and xsd:any.
5914 * *WARNING* this interface is highly subject to change
5915 *
5916 * Returns 0 if everything goes fine, a positive error code
5917 * if something is not valid and -1 if an internal error occurs.
5918 */
5919static int
5920xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5921 xmlSchemaPtr schema,
5922 xmlSchemaWildcardPtr wildc,
5923 xmlNodePtr node)
5924{
5925 const xmlChar *pc, *ns, *dictnsItem;
5926 int ret = 0;
5927 xmlChar *nsItem;
5928 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5929 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005930
Daniel Veillardc0826a72004-08-10 14:17:33 +00005931 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5932 if ((pc == NULL)
5933 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5934 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5935 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5936 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5937 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5938 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5939 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005940 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005941 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005942 NULL, node,
5943 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005944 NULL, NULL, NULL);
5945 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005946 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005947 }
5948 /*
5949 * Build the namespace constraints.
5950 */
5951 attr = xmlSchemaGetPropNode(node, "namespace");
5952 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005953 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005954 wildc->any = 1;
5955 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5956 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005957 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005958 return (-1);
5959 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005960 wildc->negNsSet->value = schema->targetNamespace;
5961 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005962 const xmlChar *end, *cur;
5963
5964 cur = ns;
5965 do {
5966 while (IS_BLANK_CH(*cur))
5967 cur++;
5968 end = cur;
5969 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5970 end++;
5971 if (end == cur)
5972 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5975 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005976 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005977 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978 NULL, (xmlNodePtr) attr,
5979 NULL,
5980 "((##any | ##other) | List of (xs:anyURI | "
5981 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005982 nsItem, NULL, NULL, NULL);
5983 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5984 } else {
5985 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5986 dictnsItem = schema->targetNamespace;
5987 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5988 dictnsItem = NULL;
5989 } else {
5990 /*
5991 * Validate the item (anyURI).
5992 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005993 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005994 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5995 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5996 }
5997 /*
5998 * Avoid dublicate namespaces.
5999 */
6000 tmp = wildc->nsSet;
6001 while (tmp != NULL) {
6002 if (dictnsItem == tmp->value)
6003 break;
6004 tmp = tmp->next;
6005 }
6006 if (tmp == NULL) {
6007 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6008 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006009 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006010 return (-1);
6011 }
6012 tmp->value = dictnsItem;
6013 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006014 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006015 wildc->nsSet = tmp;
6016 else
6017 lastNs->next = tmp;
6018 lastNs = tmp;
6019 }
6020
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006021 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006022 xmlFree(nsItem);
6023 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006024 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006025 }
6026 return (ret);
6027}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006028
6029static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006030xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6031 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006032 xmlNodePtr node,
6033 int minOccurs,
6034 int maxOccurs) {
6035
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006036 if ((maxOccurs == 0) && ( minOccurs == 0))
6037 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006038 if (maxOccurs != UNBOUNDED) {
6039 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006040 * TODO: Maybe we should better not create the particle,
6041 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006042 * content model.
6043 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006044 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006045 * 3.9.6 Schema Component Constraint: Particle Correct
6046 *
6047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006048 if (maxOccurs < 1) {
6049 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006050 * 2.2 {max occurs} must be greater than or equal to 1.
6051 */
6052 xmlSchemaPCustomAttrErr(ctxt,
6053 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006054 NULL, NULL,
6055 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006056 "The value must be greater than or equal to 1");
6057 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6058 } else if (minOccurs > maxOccurs) {
6059 /*
6060 * 2.1 {min occurs} must not be greater than {max occurs}.
6061 */
6062 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006063 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006064 NULL, NULL,
6065 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006066 "The value must not be greater than the value of 'maxOccurs'");
6067 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006069 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006070 return (0);
6071}
6072
Daniel Veillardc0826a72004-08-10 14:17:33 +00006073/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006074 * xmlSchemaParseAny:
6075 * @ctxt: a schema validation context
6076 * @schema: the schema being built
6077 * @node: a subtree containing XML Schema informations
6078 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006079 * Parsea a XML schema <any> element. A particle and wildcard
6080 * will be created (except if minOccurs==maxOccurs==0, in this case
6081 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006082 * *WARNING* this interface is highly subject to change
6083 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006084 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006085 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006086static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006087xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6088 xmlNodePtr node)
6089{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006090 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006092 xmlSchemaWildcardPtr wild;
6093 int min, max;
6094 xmlAttrPtr attr;
6095 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006096
6097 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6098 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006099 /*
6100 * Check for illegal attributes.
6101 */
6102 attr = node->properties;
6103 while (attr != NULL) {
6104 if (attr->ns == NULL) {
6105 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6106 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6107 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6108 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6109 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006110 xmlSchemaPIllegalAttrErr(ctxt,
6111 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6112 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006113 }
6114 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006115 xmlSchemaPIllegalAttrErr(ctxt,
6116 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6117 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006118 }
6119 attr = attr->next;
6120 }
6121 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6122 /*
6123 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006124 */
6125 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6126 "(xs:nonNegativeInteger | unbounded)");
6127 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6128 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006129 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6130 /*
6131 * Create & parse the wildcard.
6132 */
6133 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6134 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006135 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006136 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006137 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006138 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006139 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006140 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006141 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006142 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006143 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006144 }
6145 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006146 xmlSchemaPContentErr(ctxt,
6147 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006148 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006149 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006150 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006151 /*
6152 * No component if minOccurs==maxOccurs==0.
6153 */
6154 if ((min == 0) && (max == 0)) {
6155 /* Don't free the wildcard, since it's already on the list. */
6156 return (NULL);
6157 }
6158 /*
6159 * Create the particle.
6160 */
6161 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6162 if (particle == NULL)
6163 return (NULL);
6164 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006165 wild->minOccurs = min;
6166 wild->maxOccurs = max;
6167 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006168
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006169 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006170}
6171
6172/**
6173 * xmlSchemaParseNotation:
6174 * @ctxt: a schema validation context
6175 * @schema: the schema being built
6176 * @node: a subtree containing XML Schema informations
6177 *
6178 * parse a XML schema Notation declaration
6179 *
6180 * Returns the new structure or NULL in case of error
6181 */
6182static xmlSchemaNotationPtr
6183xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006184 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006185{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006186 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 xmlSchemaNotationPtr ret;
6188 xmlNodePtr child = NULL;
6189
6190 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6191 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006192 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006193 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006194 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6195 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 return (NULL);
6197 }
6198 ret = xmlSchemaAddNotation(ctxt, schema, name);
6199 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006200 return (NULL);
6201 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006202 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006203
6204 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6205 node, BAD_CAST "id");
6206
6207 if (IS_SCHEMA(child, "annotation")) {
6208 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6209 child = child->next;
6210 }
6211
Daniel Veillard4255d502002-04-16 15:50:10 +00006212 child = node->children;
6213 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006214 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6215 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006216 }
6217 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006218 xmlSchemaPContentErr(ctxt,
6219 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006220 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006221 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006222 }
6223
6224 return (ret);
6225}
6226
6227/**
6228 * xmlSchemaParseAnyAttribute:
6229 * @ctxt: a schema validation context
6230 * @schema: the schema being built
6231 * @node: a subtree containing XML Schema informations
6232 *
6233 * parse a XML schema AnyAttrribute declaration
6234 * *WARNING* this interface is highly subject to change
6235 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006236 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006238static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006239xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6240 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006241{
Daniel Veillard3646d642004-06-02 19:19:14 +00006242 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006243 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006244 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006245
6246 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6247 return (NULL);
6248
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006249 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6250 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006251 if (ret == NULL) {
6252 return (NULL);
6253 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006254 /*
6255 * Check for illegal attributes.
6256 */
6257 attr = node->properties;
6258 while (attr != NULL) {
6259 if (attr->ns == NULL) {
6260 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6261 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6262 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006263 xmlSchemaPIllegalAttrErr(ctxt,
6264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6265 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006266 }
6267 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006268 xmlSchemaPIllegalAttrErr(ctxt,
6269 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6270 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006271 }
6272 attr = attr->next;
6273 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006274 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6275 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006276 /*
6277 * Parse the namespace list.
6278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006279 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006280 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006281 /*
6282 * And now for the children...
6283 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006284 child = node->children;
6285 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006286 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6287 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006288 }
6289 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006290 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006291 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006292 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006293 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006294 }
6295
6296 return (ret);
6297}
6298
6299
6300/**
6301 * xmlSchemaParseAttribute:
6302 * @ctxt: a schema validation context
6303 * @schema: the schema being built
6304 * @node: a subtree containing XML Schema informations
6305 *
6306 * parse a XML schema Attrribute declaration
6307 * *WARNING* this interface is highly subject to change
6308 *
William M. Bracke7091952004-05-11 15:09:58 +00006309 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006310 */
6311static xmlSchemaAttributePtr
6312xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006313 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006314{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315 const xmlChar *name, *attrValue;
6316 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006317 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 xmlAttrPtr attr, nameAttr;
6320 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006321
6322 /*
6323 * Note that the w3c spec assumes the schema to be validated with schema
6324 * for schemas beforehand.
6325 *
6326 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006327 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006328
6329 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6330 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006331 attr = xmlSchemaGetPropNode(node, "ref");
6332 nameAttr = xmlSchemaGetPropNode(node, "name");
6333
6334 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006335 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006337 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006339 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6340 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006341 "One of the attributes 'ref' or 'name' must be present");
6342 return (NULL);
6343 }
6344 if ((topLevel) || (attr == NULL)) {
6345 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6347 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006348 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006349 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006350 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006351 isRef = 1;
6352
Daniel Veillardc0826a72004-08-10 14:17:33 +00006353 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006354 char buf[50];
6355 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006356
6357 /*
6358 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006359 */
6360 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6361 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6362 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006363 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006365 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006367 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006368 if (ret == NULL) {
6369 if (repName != NULL)
6370 xmlFree(repName);
6371 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006372 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006373 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6374 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006375 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006376 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006377 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6378 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006379 /*
6380 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6381 */
6382 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006383 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6384 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006385 "ref", "name");
6386 /*
6387 * Check for illegal attributes.
6388 */
6389 attr = node->properties;
6390 while (attr != NULL) {
6391 if (attr->ns == NULL) {
6392 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6393 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006394 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 * 3.2.3 : 3.2
6396 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006397 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006399 xmlSchemaPIllegalAttrErr(ctxt,
6400 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006401 (xmlSchemaTypePtr) ret, attr);
6402 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6403 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6404 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006405 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6406 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006407 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006408 xmlSchemaPIllegalAttrErr(ctxt,
6409 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6410 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006411 }
6412 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006413 xmlSchemaPIllegalAttrErr(ctxt,
6414 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6415 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006416 }
6417 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006418 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006419 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006420 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006421
Daniel Veillardc0826a72004-08-10 14:17:33 +00006422 /*
6423 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006424 */
6425 if (xmlSchemaPValAttrNode(ctxt,
6426 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006427 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6428 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006429 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006430 /*
6431 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6432 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006433 /*
6434 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6435 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 */
6437 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 xmlSchemaPSimpleTypeErr(ctxt,
6439 XML_SCHEMAP_NO_XMLNS,
6440 NULL, (xmlNodePtr) nameAttr,
6441 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6442 "The value of type 'xs:NCName' must not match 'xmlns'",
6443 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 if (repName != NULL)
6445 xmlFree(repName);
6446 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006447 }
6448 /*
6449 * Evaluate the target namespace
6450 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006451 if (topLevel) {
6452 ns = schema->targetNamespace;
6453 } else {
6454 attr = xmlSchemaGetPropNode(node, "form");
6455 if (attr != NULL) {
6456 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6457 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6458 ns = schema->targetNamespace;
6459 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 xmlSchemaPSimpleTypeErr(ctxt,
6461 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6462 NULL, (xmlNodePtr) attr,
6463 NULL, "(qualified | unqualified)",
6464 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006465 }
6466 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006467 ns = schema->targetNamespace;
6468 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006469 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006470 if (ret == NULL) {
6471 if (repName != NULL)
6472 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006473 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006474 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006475 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006476 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006477 if (topLevel)
6478 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006479 /*
6480 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6481 * TODO: Move this to the component layer.
6482 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006484 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 XML_SCHEMAP_NO_XSI,
6486 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006487 "The target namespace must not match '%s'",
6488 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 }
6490 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006491 * Check for illegal attributes.
6492 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 attr = node->properties;
6494 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006495 if (attr->ns == NULL) {
6496 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6497 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6498 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006499 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6500 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006502 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6503 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006504 xmlSchemaPIllegalAttrErr(ctxt,
6505 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6506 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006507 }
6508 }
6509 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006510 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6511 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006512 }
6513 attr = attr->next;
6514 }
6515 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006516 node, "type", &ret->typeNs, &ret->typeName);
6517 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006518 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6519 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006520 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006521 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006522 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006523 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6524 if (ret->defValue != NULL)
6525 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 * Attribute "default".
6528 */
6529 attr = xmlSchemaGetPropNode(node, "default");
6530 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006532 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006533 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 */
6535 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6536 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6537 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6538 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006539 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6540 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006542 /*
6543 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006544 */
6545 attr = xmlSchemaGetPropNode(node, "use");
6546 if (attr != NULL) {
6547 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6548 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6549 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6550 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6551 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6552 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6553 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6554 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 xmlSchemaPSimpleTypeErr(ctxt,
6556 XML_SCHEMAP_INVALID_ATTR_USE,
6557 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6558 NULL, "(optional | prohibited | required)",
6559 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 } else
6561 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006562 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006563 * 3.2.3 : 2
6564 * If default and use are both present, use must have
6565 * the actual value optional.
6566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006567 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6568 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006569 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006570 xmlSchemaPSimpleTypeErr(ctxt,
6571 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6572 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6573 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006575 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006577 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006578 /*
6579 * And now for the children...
6580 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006581 child = node->children;
6582 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006583 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6584 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006585 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006586 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006587 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006588 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006589 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006590 * 3.2.3 : 3.2
6591 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006592 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006593 */
6594 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6595 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6596 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006597 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006598 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6599 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006600 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006601 }
6602 } else {
6603 if (IS_SCHEMA(child, "simpleType")) {
6604 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006605 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006607 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608 */
6609 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6610 &repName, (xmlSchemaTypePtr) ret, node, child,
6611 "The attribute 'type' and the <simpleType> child "
6612 "are mutually exclusive", NULL);
6613 } else
6614 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6615 child = child->next;
6616 }
6617 if (child != NULL)
6618 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6619 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6620 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006621 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006622 /*
6623 * Cleanup.
6624 */
6625 if (repName != NULL)
6626 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006627 return (ret);
6628}
6629
6630/**
6631 * xmlSchemaParseAttributeGroup:
6632 * @ctxt: a schema validation context
6633 * @schema: the schema being built
6634 * @node: a subtree containing XML Schema informations
6635 *
6636 * parse a XML schema Attribute Group declaration
6637 * *WARNING* this interface is highly subject to change
6638 *
6639 * Returns the attribute group or NULL in case of error.
6640 */
6641static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006642xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006643 xmlSchemaPtr schema, xmlNodePtr node,
6644 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006645{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006646 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006647 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006648 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006649 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006650 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006651
6652 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6653 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006654
6655 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006656 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006657 if ((topLevel) || (attr == NULL)) {
6658 /*
6659 * Parse as an attribute group definition.
6660 * Note that those are allowed at top level only.
6661 */
6662 if (nameAttr == NULL) {
6663 xmlSchemaPMissingAttrErr(ctxt,
6664 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006665 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006666 return (NULL);
6667 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006669 * (xmlNodePtr) nameAttr);
6670 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006671 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006672 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006673 */
6674 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006675 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006676 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6677 return (NULL);
6678 }
6679 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6680 if (ret == NULL)
6681 return (NULL);
6682 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6683 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6684 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006685 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006686 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006687 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006688 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006689
6690 /*
6691 * Parse as an attribute group definition reference.
6692 */
6693 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006694 xmlSchemaPMissingAttrErr(ctxt,
6695 XML_SCHEMAP_S4S_ATTR_MISSING,
6696 NULL, node, "ref", NULL);
6697 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006698 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006699 NULL, NULL, attr, &refNs,&ref);
6700
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006701 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006702 name = (const xmlChar *) buf;
6703 if (name == NULL) {
6704 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6705 "attribute group definition reference", node);
6706 return (NULL);
6707 }
6708 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6709 if (ret == NULL)
6710 return (NULL);
6711 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6712 ret->ref = ref;
6713 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006714 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006715 xmlSchemaCheckReference(ctxt, schema, node,
6716 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006717 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006718 /*
6719 * Check for illegal attributes.
6720 */
6721 attr = node->properties;
6722 while (attr != NULL) {
6723 if (attr->ns == NULL) {
6724 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6725 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006726 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006727 {
6728 xmlSchemaPIllegalAttrErr(ctxt,
6729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6730 NULL, NULL, attr);
6731 }
6732 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6733 xmlSchemaPIllegalAttrErr(ctxt,
6734 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6735 NULL, NULL, attr);
6736 }
6737 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006738 }
6739 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006740 /*
6741 * And now for the children...
6742 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006743 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006744 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006745 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006746 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006747 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6748 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006749 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006750 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006751 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006752 if (IS_SCHEMA(child, "anyAttribute")) {
6753 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6754 child = child->next;
6755 }
6756 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006757 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006758 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006759 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6760 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006761 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006762 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006763 ctxt->container = oldcontainer;
6764 return (ret);
6765}
6766
6767/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006768 * xmlSchemaPValAttrFormDefault:
6769 * @value: the value
6770 * @flags: the flags to be modified
6771 * @flagQualified: the specific flag for "qualified"
6772 *
6773 * Returns 0 if the value is valid, 1 otherwise.
6774 */
6775static int
6776xmlSchemaPValAttrFormDefault(const xmlChar *value,
6777 int *flags,
6778 int flagQualified)
6779{
6780 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6781 if ((*flags & flagQualified) == 0)
6782 *flags |= flagQualified;
6783 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006784 return (1);
6785
William M. Brack2f2a6632004-08-20 23:09:47 +00006786 return (0);
6787}
6788
6789/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006790 * xmlSchemaPValAttrBlockFinal:
6791 * @value: the value
6792 * @flags: the flags to be modified
6793 * @flagAll: the specific flag for "#all"
6794 * @flagExtension: the specific flag for "extension"
6795 * @flagRestriction: the specific flag for "restriction"
6796 * @flagSubstitution: the specific flag for "substitution"
6797 * @flagList: the specific flag for "list"
6798 * @flagUnion: the specific flag for "union"
6799 *
6800 * Validates the value of the attribute "final" and "block". The value
6801 * is converted into the specified flag values and returned in @flags.
6802 *
6803 * Returns 0 if the value is valid, 1 otherwise.
6804 */
6805
6806static int
6807xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006808 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809 int flagAll,
6810 int flagExtension,
6811 int flagRestriction,
6812 int flagSubstitution,
6813 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815{
6816 int ret = 0;
6817
6818 /*
6819 * TODO: This does not check for dublicate entries.
6820 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006821 if ((flags == NULL) || (value == NULL))
6822 return (-1);
6823 if (value[0] == 0)
6824 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006825 if (xmlStrEqual(value, BAD_CAST "#all")) {
6826 if (flagAll != -1)
6827 *flags |= flagAll;
6828 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006829 if (flagExtension != -1)
6830 *flags |= flagExtension;
6831 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006832 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006833 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006834 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006835 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006836 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006837 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006838 *flags |= flagUnion;
6839 }
6840 } else {
6841 const xmlChar *end, *cur = value;
6842 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006843
Daniel Veillardc0826a72004-08-10 14:17:33 +00006844 do {
6845 while (IS_BLANK_CH(*cur))
6846 cur++;
6847 end = cur;
6848 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6849 end++;
6850 if (end == cur)
6851 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 if (xmlStrEqual(item, BAD_CAST "extension")) {
6854 if (flagExtension != -1) {
6855 if ((*flags & flagExtension) == 0)
6856 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006858 ret = 1;
6859 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6860 if (flagRestriction != -1) {
6861 if ((*flags & flagRestriction) == 0)
6862 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006864 ret = 1;
6865 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6866 if (flagSubstitution != -1) {
6867 if ((*flags & flagSubstitution) == 0)
6868 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006869 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006870 ret = 1;
6871 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6872 if (flagList != -1) {
6873 if ((*flags & flagList) == 0)
6874 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006875 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006876 ret = 1;
6877 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6878 if (flagUnion != -1) {
6879 if ((*flags & flagUnion) == 0)
6880 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006881 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006882 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006883 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006884 ret = 1;
6885 if (item != NULL)
6886 xmlFree(item);
6887 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006888 } while ((ret == 0) && (*cur != 0));
6889 }
6890
Daniel Veillardc0826a72004-08-10 14:17:33 +00006891 return (ret);
6892}
6893
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006894static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006895xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006896 xmlSchemaIDCPtr idc,
6897 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006898 xmlAttrPtr attr,
6899 int isField)
6900{
6901 xmlNodePtr node;
6902
6903 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006904 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006905 * Schema Component Constraint: Selector Value OK
6906 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006907 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006908 * in [XPath].
6909 */
6910 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006911 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006912 XML_SCHEMAP_INTERNAL,
6913 "Internal error: xmlSchemaCheckCSelectorXPath, "
6914 "the selector is not specified.\n", NULL, NULL);
6915 return (-1);
6916 }
6917 if (attr == NULL)
6918 node = idc->node;
6919 else
6920 node = (xmlNodePtr) attr;
6921 if (selector->xpath == NULL) {
6922 xmlSchemaPCustomErr(ctxt,
6923 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006924 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6925 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006926 "The XPath expression of the selector is not valid", NULL);
6927 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6928 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006929 const xmlChar **nsArray = NULL;
6930 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006931 /*
6932 * Compile the XPath expression.
6933 */
6934 /*
6935 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006936 * TODO: Call xmlPatterncompile with different options for selector/
6937 * field.
6938 */
6939 nsList = xmlGetNsList(attr->doc, attr->parent);
6940 /*
6941 * Build an array of prefixes and namespaces.
6942 */
6943 if (nsList != NULL) {
6944 int i, count = 0;
6945 xmlNsPtr ns;
6946
6947 for (i = 0; nsList[i] != NULL; i++)
6948 count++;
6949
6950 nsArray = (const xmlChar **) xmlMalloc(
6951 (count * 2 + 1) * sizeof(const xmlChar *));
6952 if (nsArray == NULL) {
6953 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6954 NULL);
6955 return (-1);
6956 }
6957 for (i = 0; i < count; i++) {
6958 ns = nsList[i];
6959 nsArray[2 * i] = nsList[i]->href;
6960 nsArray[2 * i + 1] = nsList[i]->prefix;
6961 }
6962 nsArray[count * 2] = NULL;
6963 xmlFree(nsList);
6964 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006965 /*
6966 * TODO: Differentiate between "selector" and "field".
6967 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006968 if (isField)
6969 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006970 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006971 else
6972 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006973 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006974 if (nsArray != NULL)
6975 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006976
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006977 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006978 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006979 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006980 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6981 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006982 "The XPath expression '%s' could not be "
6983 "compiled", selector->xpath);
6984 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006985 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006986 }
6987 return (0);
6988}
6989
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006990#define ADD_ANNOTATION(annot) \
6991 xmlSchemaAnnotPtr cur = item->annot; \
6992 if (item->annot == NULL) { \
6993 item->annot = annot; \
6994 return (annot); \
6995 } \
6996 cur = item->annot; \
6997 if (cur->next != NULL) { \
6998 cur = cur->next; \
6999 } \
7000 cur->next = annot;
7001
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007002/**
7003 * xmlSchemaAssignAnnotation:
7004 * @item: the schema component
7005 * @annot: the annotation
7006 *
7007 * Adds the annotation to the given schema component.
7008 *
7009 * Returns the given annotaion.
7010 */
7011static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007012xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7013 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007014{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007015 if ((annItem == NULL) || (annot == NULL))
7016 return (NULL);
7017 switch (annItem->type) {
7018 case XML_SCHEMA_TYPE_ELEMENT: {
7019 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7020 ADD_ANNOTATION(annot)
7021 }
7022 break;
7023 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7024 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
7027 break;
7028 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7029 case XML_SCHEMA_TYPE_ANY: {
7030 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7031 ADD_ANNOTATION(annot)
7032 }
7033 break;
7034 case XML_SCHEMA_TYPE_PARTICLE:
7035 case XML_SCHEMA_TYPE_IDC_KEY:
7036 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007037 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007038 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7039 ADD_ANNOTATION(annot)
7040 }
7041 break;
7042 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7043 xmlSchemaAttributeGroupPtr item =
7044 (xmlSchemaAttributeGroupPtr) annItem;
7045 ADD_ANNOTATION(annot)
7046 }
7047 break;
7048 case XML_SCHEMA_TYPE_NOTATION: {
7049 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7050 ADD_ANNOTATION(annot)
7051 }
7052 break;
7053 case XML_SCHEMA_FACET_MININCLUSIVE:
7054 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7055 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7056 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7057 case XML_SCHEMA_FACET_TOTALDIGITS:
7058 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7059 case XML_SCHEMA_FACET_PATTERN:
7060 case XML_SCHEMA_FACET_ENUMERATION:
7061 case XML_SCHEMA_FACET_WHITESPACE:
7062 case XML_SCHEMA_FACET_LENGTH:
7063 case XML_SCHEMA_FACET_MAXLENGTH:
7064 case XML_SCHEMA_FACET_MINLENGTH: {
7065 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7066 ADD_ANNOTATION(annot)
7067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007068 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007069 case XML_SCHEMA_TYPE_SIMPLE:
7070 case XML_SCHEMA_TYPE_COMPLEX: {
7071 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7072 ADD_ANNOTATION(annot)
7073 }
7074 break;
7075 case XML_SCHEMA_TYPE_GROUP: {
7076 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7077 ADD_ANNOTATION(annot)
7078 }
7079 break;
7080 case XML_SCHEMA_TYPE_SEQUENCE:
7081 case XML_SCHEMA_TYPE_CHOICE:
7082 case XML_SCHEMA_TYPE_ALL: {
7083 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7084 ADD_ANNOTATION(annot)
7085 }
7086 break;
7087 default:
7088 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007089 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007090 NULL, NULL, NULL,
7091 "Internal error: xmlSchemaAddAnnotation, "
7092 "The item is not a annotated schema component", NULL);
7093 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007094 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095 return (annot);
7096}
7097
7098/**
7099 * xmlSchemaParseIDCSelectorAndField:
7100 * @ctxt: a schema validation context
7101 * @schema: the schema being built
7102 * @node: a subtree containing XML Schema informations
7103 *
7104 * Parses a XML Schema identity-contraint definition's
7105 * <selector> and <field> elements.
7106 *
7107 * Returns the parsed identity-constraint definition.
7108 */
7109static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007110xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007111 xmlSchemaPtr schema,
7112 xmlSchemaIDCPtr idc,
7113 xmlNodePtr node,
7114 int isField)
7115{
7116 xmlSchemaIDCSelectPtr item;
7117 xmlNodePtr child = NULL;
7118 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007119
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007120 /*
7121 * Check for illegal attributes.
7122 */
7123 attr = node->properties;
7124 while (attr != NULL) {
7125 if (attr->ns == NULL) {
7126 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7127 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007128 xmlSchemaPIllegalAttrErr(ctxt,
7129 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7130 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007131 }
7132 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007133 xmlSchemaPIllegalAttrErr(ctxt,
7134 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7135 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 }
7137 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007138 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007139 /*
7140 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007141 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007142 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7143 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 xmlSchemaPErrMemory(ctxt,
7145 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007146 NULL);
7147 return (NULL);
7148 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007149 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007150 /*
7151 * Attribute "xpath" (mandatory).
7152 */
7153 attr = xmlSchemaGetPropNode(node, "xpath");
7154 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007155 xmlSchemaPMissingAttrErr(ctxt,
7156 XML_SCHEMAP_S4S_ATTR_MISSING,
7157 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007158 "name", NULL);
7159 } else {
7160 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7161 /*
7162 * URGENT TODO: "field"s have an other syntax than "selector"s.
7163 */
7164
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007165 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7166 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007167 xmlSchemaPErr(ctxt,
7168 (xmlNodePtr) attr,
7169 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007170 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007171 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007172 NULL, NULL);
7173 }
7174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007175 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007176 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007177 /*
7178 * And now for the children...
7179 */
7180 child = node->children;
7181 if (IS_SCHEMA(child, "annotation")) {
7182 /*
7183 * Add the annotation to the parent IDC.
7184 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007185 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007186 xmlSchemaParseAnnotation(ctxt, schema, child));
7187 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007188 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007189 if (child != NULL) {
7190 xmlSchemaPContentErr(ctxt,
7191 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007192 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007193 NULL, "(annotation?)");
7194 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007195
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007196 return (item);
7197}
7198
7199/**
7200 * xmlSchemaParseIDC:
7201 * @ctxt: a schema validation context
7202 * @schema: the schema being built
7203 * @node: a subtree containing XML Schema informations
7204 *
7205 * Parses a XML Schema identity-contraint definition.
7206 *
7207 * Returns the parsed identity-constraint definition.
7208 */
7209static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007210xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 xmlSchemaPtr schema,
7212 xmlNodePtr node,
7213 xmlSchemaTypeType idcCategory,
7214 const xmlChar *targetNamespace)
7215{
7216 xmlSchemaIDCPtr item = NULL;
7217 xmlNodePtr child = NULL;
7218 xmlAttrPtr attr;
7219 const xmlChar *name = NULL;
7220 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7221 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007222
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007223 /*
7224 * Check for illegal attributes.
7225 */
7226 attr = node->properties;
7227 while (attr != NULL) {
7228 if (attr->ns == NULL) {
7229 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7230 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7231 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7232 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007233 xmlSchemaPIllegalAttrErr(ctxt,
7234 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7235 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007236 }
7237 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007238 xmlSchemaPIllegalAttrErr(ctxt,
7239 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7240 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007241 }
7242 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007243 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007244 /*
7245 * Attribute "name" (mandatory).
7246 */
7247 attr = xmlSchemaGetPropNode(node, "name");
7248 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007249 xmlSchemaPMissingAttrErr(ctxt,
7250 XML_SCHEMAP_S4S_ATTR_MISSING,
7251 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 "name", NULL);
7253 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007254 } else if (xmlSchemaPValAttrNode(ctxt,
7255 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007256 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7257 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007258 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007259 /*
7260 * Create the component.
7261 */
7262 if (schema->idcDef == NULL)
7263 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007265 return (NULL);
7266
7267 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7268 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007269 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007270 "allocating an identity-constraint definition", NULL);
7271 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007272 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007273 /*
7274 * Add the IDC to the list of IDCs on the schema component.
7275 */
7276 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007277 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007278 xmlSchemaPCustomErrExt(ctxt,
7279 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007280 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007281 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007282 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007283 name, targetNamespace, NULL);
7284 xmlFree(item);
7285 return (NULL);
7286 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007287 memset(item, 0, sizeof(xmlSchemaIDC));
7288 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007289 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007290 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007291 if (ctxt->assemble != NULL)
7292 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007293 /*
7294 * The target namespace of the parent element declaration.
7295 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007296 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007297 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7298 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007299 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7300 /*
7301 * Attribute "refer" (mandatory).
7302 */
7303 attr = xmlSchemaGetPropNode(node, "refer");
7304 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007305 xmlSchemaPMissingAttrErr(ctxt,
7306 XML_SCHEMAP_S4S_ATTR_MISSING,
7307 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007308 "refer", NULL);
7309 } else {
7310 /*
7311 * Create a reference item.
7312 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007313 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007314 NULL, NULL);
7315 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007316 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007317 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 NULL, NULL, attr,
7319 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007320 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007321 xmlSchemaCheckReference(ctxt, schema, node,
7322 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007323 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007324 }
7325 }
7326 /*
7327 * And now for the children...
7328 */
7329 child = node->children;
7330 if (IS_SCHEMA(child, "annotation")) {
7331 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7332 child = child->next;
7333 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007334 if (child == NULL) {
7335 xmlSchemaPContentErr(ctxt,
7336 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007337 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007338 "A child element is missing",
7339 "(annotation?, (selector, field+))");
7340 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007341 /*
7342 * Child element <selector>.
7343 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007344 if (IS_SCHEMA(child, "selector")) {
7345 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007346 item, child, 0);
7347 child = child->next;
7348 /*
7349 * Child elements <field>.
7350 */
7351 if (IS_SCHEMA(child, "field")) {
7352 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007353 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007354 item, child, 1);
7355 if (field != NULL) {
7356 field->index = item->nbFields;
7357 item->nbFields++;
7358 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007359 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007360 else
7361 item->fields = field;
7362 lastField = field;
7363 }
7364 child = child->next;
7365 } while (IS_SCHEMA(child, "field"));
7366 } else {
7367 xmlSchemaPContentErr(ctxt,
7368 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007369 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007370 NULL, "(annotation?, (selector, field+))");
7371 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007373 if (child != NULL) {
7374 xmlSchemaPContentErr(ctxt,
7375 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007376 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007377 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007378 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007379
7380 return (item);
7381}
7382
Daniel Veillardc0826a72004-08-10 14:17:33 +00007383/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007384 * xmlSchemaParseElement:
7385 * @ctxt: a schema validation context
7386 * @schema: the schema being built
7387 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007388 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007389 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007390 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007391 * *WARNING* this interface is highly subject to change
7392 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007393 * Returns the element declaration or a particle; NULL in case
7394 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007395 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007396static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007397xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007398 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007399{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007400 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007401 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007402 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007403 xmlNodePtr child = NULL;
7404 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007405 int min, max, isRef = 0;
7406 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007407
7408 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7409 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007410
Daniel Veillard4255d502002-04-16 15:50:10 +00007411 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007413 /*
7414 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007415 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 * robust.
7417 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007418 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007420 if ((topLevel) || (attr == NULL)) {
7421 if (nameAttr == NULL) {
7422 xmlSchemaPMissingAttrErr(ctxt,
7423 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007424 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007425 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007426 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007427 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007428 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007429
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007430 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007431 child = node->children;
7432 if (IS_SCHEMA(child, "annotation")) {
7433 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7434 child = child->next;
7435 }
7436 /*
7437 * Skip particle part if a global declaration.
7438 */
7439 if (topLevel)
7440 goto declaration_part;
7441 /*
7442 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007443 */
7444 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7445 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7446 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7448 if (particle == NULL)
7449 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007450
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007451 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7452
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007453 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007454 const xmlChar *refNs = NULL, *ref = NULL;
7455 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007457 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007458 */
7459 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007460 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007461 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007462 /*
7463 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007464 */
7465 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007466 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007467 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007468 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007469 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007470 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007471 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007472 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007473 attr = node->properties;
7474 while (attr != NULL) {
7475 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007476 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7477 xmlStrEqual(attr->name, BAD_CAST "name") ||
7478 xmlStrEqual(attr->name, BAD_CAST "id") ||
7479 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7480 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7481 {
7482 attr = attr->next;
7483 continue;
7484 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007485 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007486 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007487 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007488 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007489 "Only the attributes 'minOccurs', 'maxOccurs' and "
7490 "'id' are allowed in addition to 'ref'");
7491 break;
7492 }
7493 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7494 xmlSchemaPIllegalAttrErr(ctxt,
7495 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007496 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007497 }
7498 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007500 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007501 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007502 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007503 if (child != NULL) {
7504 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7505 NULL, NULL, node, child, NULL, "(annotation?)");
7506 }
7507 if ((min == 0) && (max == 0))
7508 goto return_null;
7509 /*
7510 * Create the reference item.
7511 */
7512 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7513 ref, refNs);
7514 if (refer == NULL)
7515 goto return_null;
7516 particle->children = (xmlSchemaTreeItemPtr) refer;
7517 particle->annot = annot;
7518 /*
7519 * Add to assembled items; the reference need to be resolved.
7520 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007521 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007522 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7523
7524 return ((xmlSchemaBasicItemPtr) particle);
7525 }
7526 /*
7527 * The declaration part ===============================================
7528 */
7529declaration_part:
7530 {
7531 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7532 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7533
7534 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007536 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007537 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007538 * Evaluate the target namespace.
7539 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007540 if (topLevel) {
7541 ns = schema->targetNamespace;
7542 } else {
7543 attr = xmlSchemaGetPropNode(node, "form");
7544 if (attr != NULL) {
7545 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7546 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007547 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007548 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549 xmlSchemaPSimpleTypeErr(ctxt,
7550 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7551 NULL, (xmlNodePtr) attr,
7552 NULL, "(qualified | unqualified)",
7553 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007554 }
7555 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007556 ns = schema->targetNamespace;
7557 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007558 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007559 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007560 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007561 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007562 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7563 decl->node = node;
7564 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007565 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566 * Check for illegal attributes.
7567 */
William M. Bracke7091952004-05-11 15:09:58 +00007568 attr = node->properties;
7569 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007570 if (attr->ns == NULL) {
7571 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7572 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007574 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007575 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007576 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007577 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7578 {
7579 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007580 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007581 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007582 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007583 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007584 xmlSchemaPIllegalAttrErr(ctxt,
7585 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7586 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7589 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007590 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7591
7592 xmlSchemaPIllegalAttrErr(ctxt,
7593 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 }
7596 }
7597 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007598
Daniel Veillardc0826a72004-08-10 14:17:33 +00007599 xmlSchemaPIllegalAttrErr(ctxt,
7600 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007601 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007602 }
7603 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007604 }
William M. Bracke7091952004-05-11 15:09:58 +00007605 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 * Extract/validate attributes.
7607 */
7608 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007610 * Process top attributes of global element declarations here.
7611 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007612 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7613 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007614 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7615 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7616 &(decl->substGroupNs), &(decl->substGroup));
7617 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007618 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007619 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007620 /*
7621 * Attribute "final".
7622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007623 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007624 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007625 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7626 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7627 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7628 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007630 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7631 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 -1,
7633 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7634 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007636 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007637 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7638 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007639 attrValue, NULL, NULL, NULL);
7640 }
7641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007642 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007643 /*
7644 * Attribute "block".
7645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007646 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007647 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007648 /*
7649 * Apply default "block" values.
7650 */
7651 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7652 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7653 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7654 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7655 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7656 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007657 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007658 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7659 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007660 -1,
7661 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007662 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7664 xmlSchemaPSimpleTypeErr(ctxt,
7665 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007666 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007667 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007668 "restriction | substitution))", attrValue,
7669 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007670 }
7671 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007672 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007674 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007675
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007676 attr = xmlSchemaGetPropNode(node, "type");
7677 if (attr != NULL) {
7678 xmlSchemaPValAttrNodeQName(ctxt, schema,
7679 NULL, (xmlSchemaTypePtr) decl, attr,
7680 &(decl->namedTypeNs), &(decl->namedType));
7681 xmlSchemaCheckReference(ctxt, schema, node,
7682 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7683 }
7684 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7685 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 if (attr != NULL) {
7687 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007688 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007689 /*
7690 * 3.3.3 : 1
7691 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007692 */
7693 xmlSchemaPMutualExclAttrErr(ctxt,
7694 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007695 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007696 "default", "fixed");
7697 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007698 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7699 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007700 }
William M. Bracke7091952004-05-11 15:09:58 +00007701 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007702 /*
7703 * And now for the children...
7704 */
7705 oldcontainer = ctxt->container;
7706 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007707 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007708 /*
7709 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007710 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007711 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007712 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007713 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007714 xmlSchemaPContentErr(ctxt,
7715 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007716 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007718 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007719 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007720 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007721 child = child->next;
7722 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007723 /*
7724 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007726 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007728 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007729 xmlSchemaPContentErr(ctxt,
7730 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007731 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007733 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007734 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007735 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007736 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007737 }
William M. Bracke7091952004-05-11 15:09:58 +00007738 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007739 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007740 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007741 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007742 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007743 } else if (IS_SCHEMA(child, "key")) {
7744 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007746 } else if (IS_SCHEMA(child, "keyref")) {
7747 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007748 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007749 }
7750 if (lastIDC != NULL)
7751 lastIDC->next = curIDC;
7752 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007753 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007754 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007755 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007756 }
7757 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007758 xmlSchemaPContentErr(ctxt,
7759 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007760 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007761 NULL, "(annotation?, ((simpleType | complexType)?, "
7762 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007763 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007764 ctxt->container = oldcontainer;
7765 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007766 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007767 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007768 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007769 * different layer.
7770 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007771 FREE_AND_NULL(des)
7772 if (topLevel)
7773 return ((xmlSchemaBasicItemPtr) decl);
7774 else {
7775 particle->children = (xmlSchemaTreeItemPtr) decl;
7776 return ((xmlSchemaBasicItemPtr) particle);
7777 }
7778
7779return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007780 FREE_AND_NULL(des);
7781 if (annot != NULL) {
7782 if (particle != NULL)
7783 particle->annot = NULL;
7784 if (decl != NULL)
7785 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007786 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007788 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007789}
7790
7791/**
7792 * xmlSchemaParseUnion:
7793 * @ctxt: a schema validation context
7794 * @schema: the schema being built
7795 * @node: a subtree containing XML Schema informations
7796 *
7797 * parse a XML schema Union definition
7798 * *WARNING* this interface is highly subject to change
7799 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007800 * Returns -1 in case of internal error, 0 in case of success and a positive
7801 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007802 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007803static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007804xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007805 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007806{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007807 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007808 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007809 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007810 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007811
7812 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007813 return (-1);
7814 /* Not a component, don't create it. */
7815 type = ctxt->ctxtType;
7816 /*
7817 * Mark the simple type as being of variety "union".
7818 */
7819 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007820 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007821 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7822 * then the ·simple ur-type definition·."
7823 */
7824 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007825 /*
7826 * Check for illegal attributes.
7827 */
7828 attr = node->properties;
7829 while (attr != NULL) {
7830 if (attr->ns == NULL) {
7831 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7832 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007833 xmlSchemaPIllegalAttrErr(ctxt,
7834 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7835 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007836 }
7837 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007838 xmlSchemaPIllegalAttrErr(ctxt,
7839 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7840 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007841 }
7842 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007843 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007844 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007845 /*
7846 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007847 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007848 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007849 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007850 if (attr != NULL) {
7851 const xmlChar *end;
7852 xmlChar *tmp;
7853 const xmlChar *localName, *nsName;
7854 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7855 xmlSchemaQNameRefPtr ref;
7856
7857 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007858 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007859 do {
7860 while (IS_BLANK_CH(*cur))
7861 cur++;
7862 end = cur;
7863 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7864 end++;
7865 if (end == cur)
7866 break;
7867 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007868 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7869 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007870 /*
7871 * Create the member type link.
7872 */
7873 link = (xmlSchemaTypeLinkPtr)
7874 xmlMalloc(sizeof(xmlSchemaTypeLink));
7875 if (link == NULL) {
7876 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7877 "allocating a type link", NULL);
7878 return (-1);
7879 }
7880 link->type = NULL;
7881 link->next = NULL;
7882 if (lastLink == NULL)
7883 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007884 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007885 lastLink->next = link;
7886 lastLink = link;
7887 /*
7888 * Create a reference item.
7889 */
7890 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7891 localName, nsName);
7892 if (ref == NULL) {
7893 FREE_AND_NULL(tmp)
7894 return (-1);
7895 }
7896 /*
7897 * Assign the reference to the link, it will be resolved
7898 * later during fixup of the union simple type.
7899 */
7900 link->type = (xmlSchemaTypePtr) ref;
7901 }
7902 FREE_AND_NULL(tmp)
7903 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007904 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007905
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007906 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007907 /*
7908 * And now for the children...
7909 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007910 child = node->children;
7911 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007912 /*
7913 * Add the annotation to the simple type ancestor.
7914 */
7915 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7916 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007917 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007918 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007919 if (IS_SCHEMA(child, "simpleType")) {
7920 xmlSchemaTypePtr subtype, last = NULL;
7921
7922 /*
7923 * Anchor the member types in the "subtypes" field of the
7924 * simple type.
7925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007926 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007927 subtype = (xmlSchemaTypePtr)
7928 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7929 if (subtype != NULL) {
7930 if (last == NULL) {
7931 type->subtypes = subtype;
7932 last = subtype;
7933 } else {
7934 last->next = subtype;
7935 last = subtype;
7936 }
7937 last->next = NULL;
7938 }
7939 child = child->next;
7940 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007941 }
7942 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007943 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007944 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007945 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007946 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007947 if ((attr == NULL) && (type->subtypes == NULL)) {
7948 /*
7949 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007950 * Either the memberTypes [attribute] of the <union> element must
7951 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007952 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007953 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007954 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7955 NULL, NULL, node,
7956 "Either the attribute 'memberTypes' or "
7957 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007958 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007959 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007960}
7961
7962/**
7963 * xmlSchemaParseList:
7964 * @ctxt: a schema validation context
7965 * @schema: the schema being built
7966 * @node: a subtree containing XML Schema informations
7967 *
7968 * parse a XML schema List definition
7969 * *WARNING* this interface is highly subject to change
7970 *
William M. Bracke7091952004-05-11 15:09:58 +00007971 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007972 * 1 in case of success.
7973 */
7974static xmlSchemaTypePtr
7975xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007976 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007977{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007978 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007979 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007980 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007981
7982 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7983 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007984 /* Not a component, don't create it. */
7985 type = ctxt->ctxtType;
7986 /*
7987 * Mark the type as being of variety "list".
7988 */
7989 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007991 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7992 * then the ·simple ur-type definition·."
7993 */
7994 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007995 /*
7996 * Check for illegal attributes.
7997 */
7998 attr = node->properties;
7999 while (attr != NULL) {
8000 if (attr->ns == NULL) {
8001 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8002 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008003 xmlSchemaPIllegalAttrErr(ctxt,
8004 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8005 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008006 }
8007 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPIllegalAttrErr(ctxt,
8009 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8010 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008011 }
8012 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008013 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014
8015 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8016
William M. Brack2f2a6632004-08-20 23:09:47 +00008017 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008018 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8019 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008020 */
8021 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008023 /*
8024 * And now for the children...
8025 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008026 child = node->children;
8027 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008028 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8029 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008031 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008032 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033 /*
8034 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008035 * Either the itemType [attribute] or the <simpleType> [child] of
8036 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008037 */
8038 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008039 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008040 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008041 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008042 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008043 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008044 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008045 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008046 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008047 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008048 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008049 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008050 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008051 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008052 "Either the attribute 'itemType' or the <simpleType> child "
8053 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008054 }
8055 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008056 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008057 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008058 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008059 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008060 if ((type->ref == NULL) &&
8061 (type->subtypes == NULL) &&
8062 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008063 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008064 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008065 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008066 "Either the attribute 'itemType' or the <simpleType> child "
8067 "must be present", NULL);
8068 }
8069 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008070}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008071
Daniel Veillard4255d502002-04-16 15:50:10 +00008072/**
8073 * xmlSchemaParseSimpleType:
8074 * @ctxt: a schema validation context
8075 * @schema: the schema being built
8076 * @node: a subtree containing XML Schema informations
8077 *
8078 * parse a XML schema Simple Type definition
8079 * *WARNING* this interface is highly subject to change
8080 *
William M. Bracke7091952004-05-11 15:09:58 +00008081 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008082 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008083 */
8084static xmlSchemaTypePtr
8085xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008086 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008087{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008088 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008089 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008090 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008091 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008092
8093 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8094 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008095
Daniel Veillardc0826a72004-08-10 14:17:33 +00008096 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008097 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008098 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008099 xmlSchemaPMissingAttrErr(ctxt,
8100 XML_SCHEMAP_S4S_ATTR_MISSING,
8101 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008102 "name", NULL);
8103 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008104 } else {
8105 if (xmlSchemaPValAttrNode(ctxt,
8106 NULL, NULL, attr,
8107 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8108 return (NULL);
8109 /*
8110 * Skip built-in types.
8111 */
8112 if (ctxt->isS4S) {
8113 xmlSchemaTypePtr biType;
8114
8115 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8116 if (biType != NULL)
8117 return (biType);
8118 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008119 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008120 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008121
Daniel Veillardc0826a72004-08-10 14:17:33 +00008122 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008123 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124
Daniel Veillard01fa6152004-06-29 17:04:39 +00008125 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008126 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008127 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008128 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008129 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008130 if (type == NULL)
8131 return (NULL);
8132 type->node = node;
8133 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008135 /*
8136 * Check for illegal attributes.
8137 */
8138 attr = node->properties;
8139 while (attr != NULL) {
8140 if (attr->ns == NULL) {
8141 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008142 xmlSchemaPIllegalAttrErr(ctxt,
8143 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8144 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008145 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008146 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008147 xmlSchemaPIllegalAttrErr(ctxt,
8148 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8149 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008150 }
8151 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008152 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008153 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008154 /*
8155 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008156 *
8157 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008159 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008160 if (type == NULL)
8161 return (NULL);
8162 type->node = node;
8163 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008164 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008165 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8166 /*
8167 * Check for illegal attributes.
8168 */
8169 attr = node->properties;
8170 while (attr != NULL) {
8171 if (attr->ns == NULL) {
8172 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8173 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008174 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 xmlSchemaPIllegalAttrErr(ctxt,
8176 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8177 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 }
8179 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008180 xmlSchemaPIllegalAttrErr(ctxt,
8181 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8182 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008183 }
8184 attr = attr->next;
8185 }
8186 /*
8187 * Attribute "final".
8188 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008189 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008190 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008191 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8192 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8193 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8194 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8195 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8196 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008197 } else {
8198 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008199 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8200 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008201 XML_SCHEMAS_TYPE_FINAL_LIST,
8202 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8203
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008204 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008205 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 type, (xmlNodePtr) attr,
8207 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008208 attrValue, NULL, NULL, NULL);
8209 }
8210 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008211 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008212 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008213 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008214 /*
8215 * And now for the children...
8216 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008217 oldCtxtType = ctxt->ctxtType;
8218 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008219 ctxt->ctxtType = type;
8220 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 child = node->children;
8222 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008223 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008225 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008226 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008227 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8228 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008229 "(annotation?, (restriction | list | union))");
8230 } else if (IS_SCHEMA(child, "restriction")) {
8231 xmlSchemaParseRestriction(ctxt, schema, child,
8232 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008233 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008234 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008235 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008236 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008239 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008240 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8243 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008244 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008245 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008246 ctxt->parentItem = oldParentItem;
8247 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008248
Daniel Veillard4255d502002-04-16 15:50:10 +00008249 return (type);
8250}
8251
Daniel Veillard4255d502002-04-16 15:50:10 +00008252/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008253 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008254 * @ctxt: a schema validation context
8255 * @schema: the schema being built
8256 * @node: a subtree containing XML Schema informations
8257 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008259 * *WARNING* this interface is highly subject to change
8260 *
William M. Bracke7091952004-05-11 15:09:58 +00008261 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008262 * 1 in case of success.
8263 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008264static xmlSchemaTreeItemPtr
8265xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8266 xmlSchemaPtr schema,
8267 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008268{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008269 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008270 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008271 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008272 const xmlChar *ref = NULL, *refNs = NULL;
8273 int min, max;
8274
8275 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008276 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008277
8278 attr = xmlSchemaGetPropNode(node, "ref");
8279 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008280 xmlSchemaPMissingAttrErr(ctxt,
8281 XML_SCHEMAP_S4S_ATTR_MISSING,
8282 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008283 "ref", NULL);
8284 return (NULL);
8285 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008286 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008287 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008288 }
8289 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008290 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292 /*
8293 * Check for illegal attributes.
8294 */
8295 attr = node->properties;
8296 while (attr != NULL) {
8297 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008299 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8300 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8301 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008302 xmlSchemaPIllegalAttrErr(ctxt,
8303 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8304 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008305 }
8306 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008307 xmlSchemaPIllegalAttrErr(ctxt,
8308 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8309 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008310 }
8311 attr = attr->next;
8312 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008313 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008314 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8315 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008316 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008317 /*
8318 * Create a reference item as the term; it will be substituted for
8319 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008320 */
8321 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008322 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8323 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8324 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8325 /*
8326 * And now for the children...
8327 */
8328 child = node->children;
8329 /* TODO: Is annotation even allowed for a model group reference? */
8330 if (IS_SCHEMA(child, "annotation")) {
8331 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008332 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008333 */
8334 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8335 child = child->next;
8336 }
8337 if (child != NULL) {
8338 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008339 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008340 NULL, NULL, node, child, NULL,
8341 "(annotation?)");
8342 }
8343 /*
8344 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8345 */
8346 if ((min == 0) && (max == 0))
8347 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008348 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008349 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8350 return ((xmlSchemaTreeItemPtr) item);
8351}
8352
8353/**
8354 * xmlSchemaParseModelGroupDefinition:
8355 * @ctxt: a schema validation context
8356 * @schema: the schema being built
8357 * @node: a subtree containing XML Schema informations
8358 *
8359 * Parses a XML schema model group definition.
8360 * *WARNING* this interface is highly subject to change
8361 *
8362 * Returns -1 in case of error, 0 if the declaration is improper and
8363 * 1 in case of success.
8364 */
8365static xmlSchemaModelGroupDefPtr
8366xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8367 xmlSchemaPtr schema,
8368 xmlNodePtr node)
8369{
8370 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008371 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008372 xmlAttrPtr attr;
8373 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008374
8375 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008376 return (NULL);
8377
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008378 attr = xmlSchemaGetPropNode(node, "name");
8379 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008380 xmlSchemaPMissingAttrErr(ctxt,
8381 XML_SCHEMAP_S4S_ATTR_MISSING,
8382 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008383 "name", NULL);
8384 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008385 } else if (xmlSchemaPValAttrNode(ctxt,
8386 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008387 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8388 return (NULL);
8389 }
8390 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8391 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008392 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008393 /*
8394 * Check for illegal attributes.
8395 */
8396 attr = node->properties;
8397 while (attr != NULL) {
8398 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008399 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008400 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008401 xmlSchemaPIllegalAttrErr(ctxt,
8402 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8403 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008404 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008405 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008406 xmlSchemaPIllegalAttrErr(ctxt,
8407 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8408 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008409 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008410 attr = attr->next;
8411 }
8412 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8413 /*
8414 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008415 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008416 child = node->children;
8417 if (IS_SCHEMA(child, "annotation")) {
8418 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8419 child = child->next;
8420 }
8421 if (IS_SCHEMA(child, "all")) {
8422 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8423 XML_SCHEMA_TYPE_ALL, 0);
8424 child = child->next;
8425 } else if (IS_SCHEMA(child, "choice")) {
8426 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8427 XML_SCHEMA_TYPE_CHOICE, 0);
8428 child = child->next;
8429 } else if (IS_SCHEMA(child, "sequence")) {
8430 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8431 XML_SCHEMA_TYPE_SEQUENCE, 0);
8432 child = child->next;
8433 }
8434 if (child != NULL) {
8435 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008436 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8437 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008438 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008439 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008440
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008441 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008442}
8443
8444/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008445 * xmlSchemaCleanupDoc:
8446 * @ctxt: a schema validation context
8447 * @node: the root of the document.
8448 *
8449 * removes unwanted nodes in a schemas document tree
8450 */
8451static void
8452xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8453{
8454 xmlNodePtr delete, cur;
8455
8456 if ((ctxt == NULL) || (root == NULL)) return;
8457
8458 /*
8459 * Remove all the blank text nodes
8460 */
8461 delete = NULL;
8462 cur = root;
8463 while (cur != NULL) {
8464 if (delete != NULL) {
8465 xmlUnlinkNode(delete);
8466 xmlFreeNode(delete);
8467 delete = NULL;
8468 }
8469 if (cur->type == XML_TEXT_NODE) {
8470 if (IS_BLANK_NODE(cur)) {
8471 if (xmlNodeGetSpacePreserve(cur) != 1) {
8472 delete = cur;
8473 }
8474 }
8475 } else if ((cur->type != XML_ELEMENT_NODE) &&
8476 (cur->type != XML_CDATA_SECTION_NODE)) {
8477 delete = cur;
8478 goto skip_children;
8479 }
8480
8481 /*
8482 * Skip to next node
8483 */
8484 if (cur->children != NULL) {
8485 if ((cur->children->type != XML_ENTITY_DECL) &&
8486 (cur->children->type != XML_ENTITY_REF_NODE) &&
8487 (cur->children->type != XML_ENTITY_NODE)) {
8488 cur = cur->children;
8489 continue;
8490 }
8491 }
8492 skip_children:
8493 if (cur->next != NULL) {
8494 cur = cur->next;
8495 continue;
8496 }
8497
8498 do {
8499 cur = cur->parent;
8500 if (cur == NULL)
8501 break;
8502 if (cur == root) {
8503 cur = NULL;
8504 break;
8505 }
8506 if (cur->next != NULL) {
8507 cur = cur->next;
8508 break;
8509 }
8510 } while (cur != NULL);
8511 }
8512 if (delete != NULL) {
8513 xmlUnlinkNode(delete);
8514 xmlFreeNode(delete);
8515 delete = NULL;
8516 }
8517}
8518
William M. Brack2f2a6632004-08-20 23:09:47 +00008519
8520/**
8521 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008522 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008523 * @ctxt: a schema validation context
8524 * @schemaLocation: an URI defining where to find the imported schema
8525 *
8526 * import a XML schema
8527 * *WARNING* this interface is highly subject to change
8528 *
8529 * Returns -1 in case of error and 1 in case of success.
8530 */
8531#if 0
8532static xmlSchemaImportPtr
8533xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8534 const xmlChar *schemaLocation)
8535{
8536 xmlSchemaImportPtr import;
8537 xmlSchemaParserCtxtPtr newctxt;
8538
8539 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8540 if (newctxt == NULL) {
8541 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8542 NULL);
8543 return (NULL);
8544 }
8545 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8546 /* Keep the same dictionnary for parsing, really */
8547 xmlDictReference(ctxt->dict);
8548 newctxt->dict = ctxt->dict;
8549 newctxt->includes = 0;
8550 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8551
8552 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8553 ctxt->userData);
8554
8555 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8556 if (import == NULL) {
8557 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8558 NULL);
8559 xmlSchemaFreeParserCtxt(newctxt);
8560 return (NULL);
8561 }
8562
8563 memset(import, 0, sizeof(xmlSchemaImport));
8564 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8565 import->schema = xmlSchemaParse(newctxt);
8566
8567 if (import->schema == NULL) {
8568 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008569 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008570 "Failed to import schema from location \"%s\".\n",
8571 schemaLocation, NULL);
8572
8573 xmlSchemaFreeParserCtxt(newctxt);
8574 /* The schemaLocation is held by the dictionary.
8575 if (import->schemaLocation != NULL)
8576 xmlFree((xmlChar *)import->schemaLocation);
8577 */
8578 xmlFree(import);
8579 return NULL;
8580 }
8581
8582 xmlSchemaFreeParserCtxt(newctxt);
8583 return import;
8584}
8585#endif
8586
8587static void
8588xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8589{
8590 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8591 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8592
8593 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8594 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8595
8596 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8597 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8598 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8599 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8600 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8601 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8602 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8603 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8604
8605 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8606 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8607 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8608 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8609 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8610 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8611}
8612
8613static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008614xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008615 xmlSchemaPtr schema,
8616 xmlNodePtr node)
8617{
8618 xmlAttrPtr attr;
8619 const xmlChar *val;
8620
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008621 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8622 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008624 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8625 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008627 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8628
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008629 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 if (attr != NULL) {
8631 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008632 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008633 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008634 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008635 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008636 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008637 "(qualified | unqualified)", val, NULL, NULL, NULL);
8638 }
8639 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008640
8641 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008642 if (attr != NULL) {
8643 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008644 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008645 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008646 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008647 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008648 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008649 "(qualified | unqualified)", val, NULL, NULL, NULL);
8650 }
8651 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008652
8653 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008654 if (attr != NULL) {
8655 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8656 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8657 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8658 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8659 -1,
8660 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8661 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8662 xmlSchemaPSimpleTypeErr(ctxt,
8663 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008664 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008665 "(#all | List of (extension | restriction | list | union))",
8666 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008667 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008668 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008669
8670 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008671 if (attr != NULL) {
8672 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8673 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8674 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8675 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8676 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8677 xmlSchemaPSimpleTypeErr(ctxt,
8678 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008680 "(#all | List of (extension | restriction | substitution))",
8681 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008682 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008683 }
8684}
8685
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008686/**
8687 * xmlSchemaParseSchemaTopLevel:
8688 * @ctxt: a schema validation context
8689 * @schema: the schemas
8690 * @nodes: the list of top level nodes
8691 *
8692 * Returns the internal XML Schema structure built from the resource or
8693 * NULL in case of error
8694 */
8695static void
8696xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8697 xmlSchemaPtr schema, xmlNodePtr nodes)
8698{
8699 xmlNodePtr child;
8700 xmlSchemaAnnotPtr annot;
8701
8702 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8703 return;
8704
8705 child = nodes;
8706 while ((IS_SCHEMA(child, "include")) ||
8707 (IS_SCHEMA(child, "import")) ||
8708 (IS_SCHEMA(child, "redefine")) ||
8709 (IS_SCHEMA(child, "annotation"))) {
8710 if (IS_SCHEMA(child, "annotation")) {
8711 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8712 if (schema->annot == NULL)
8713 schema->annot = annot;
8714 else
8715 xmlSchemaFreeAnnot(annot);
8716 } else if (IS_SCHEMA(child, "import")) {
8717 xmlSchemaParseImport(ctxt, schema, child);
8718 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008719 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008720 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008721 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008722 } else if (IS_SCHEMA(child, "redefine")) {
8723 TODO
8724 }
8725 child = child->next;
8726 }
8727 while (child != NULL) {
8728 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008729 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008730 child = child->next;
8731 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008732 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008733 child = child->next;
8734 } else if (IS_SCHEMA(child, "element")) {
8735 xmlSchemaParseElement(ctxt, schema, child, 1);
8736 child = child->next;
8737 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008738 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008739 child = child->next;
8740 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008741 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008742 child = child->next;
8743 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008744 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008745 child = child->next;
8746 } else if (IS_SCHEMA(child, "notation")) {
8747 xmlSchemaParseNotation(ctxt, schema, child);
8748 child = child->next;
8749 } else {
8750 xmlSchemaPErr2(ctxt, NULL, child,
8751 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008752 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008753 child->name, NULL);
8754 child = child->next;
8755 }
8756 while (IS_SCHEMA(child, "annotation")) {
8757 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8758 if (schema->annot == NULL)
8759 schema->annot = annot;
8760 else
8761 xmlSchemaFreeAnnot(annot);
8762 child = child->next;
8763 }
8764 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008765 ctxt->parentItem = NULL;
8766 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008767}
8768
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008769static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008770xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008771 xmlHashTablePtr *imports,
8772 const xmlChar *nsName)
8773{
8774 xmlSchemaImportPtr ret;
8775
8776 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008777 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008778 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008779 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008780 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8781 NULL, NULL, (xmlNodePtr) ctxt->doc,
8782 "Internal error: failed to build the import table",
8783 NULL);
8784 return (NULL);
8785 }
8786 }
8787 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8788 if (ret == NULL) {
8789 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8790 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008791 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008792 memset(ret, 0, sizeof(xmlSchemaImport));
8793 if (nsName == NULL)
8794 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008795 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008796
8797 return (ret);
8798}
8799
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008800/**
8801 * xmlSchemaNewParserCtxtUseDict:
8802 * @URL: the location of the schema
8803 * @dict: the dictionary to be used
8804 *
8805 * Create an XML Schemas parse context for that file/resource expected
8806 * to contain an XML Schemas file.
8807 *
8808 * Returns the parser context or NULL in case of error
8809 */
8810static xmlSchemaParserCtxtPtr
8811xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8812{
8813 xmlSchemaParserCtxtPtr ret;
8814 /*
8815 if (URL == NULL)
8816 return (NULL);
8817 */
8818
8819 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8820 if (ret == NULL) {
8821 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8822 NULL);
8823 return (NULL);
8824 }
8825 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8826 ret->dict = dict;
8827 xmlDictReference(dict);
8828 if (URL != NULL)
8829 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8830 ret->includes = 0;
8831 return (ret);
8832}
8833
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008834static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008835xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8836{
8837 if (vctxt->pctxt == NULL) {
8838 if (vctxt->schema != NULL)
8839 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8840 else
8841 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8842 if (vctxt->pctxt == NULL) {
8843 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8844 "failed to create a temp. parser context");
8845 return (-1);
8846 }
8847 /* TODO: Pass user data. */
8848 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8849 }
8850 return (0);
8851}
8852
8853static int
8854xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008855 xmlSchemaPtr schema,
8856 xmlNodePtr node,
8857 const xmlChar *nsName,
8858 const xmlChar *location,
8859 xmlDocPtr *doc,
8860 const xmlChar **targetNamespace,
8861 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008862{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 xmlParserCtxtPtr parserCtxt;
8865 xmlSchemaImportPtr import;
8866 const xmlChar *ns;
8867 xmlNodePtr root;
8868
8869 /*
8870 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8871 * <xsi:noNamespaceSchemaLocation>.
8872 */
8873 *doc = NULL;
8874 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008875 * Given that the schemaLocation [attribute] is only a hint, it is open
8876 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877 * namespace, regardless of the ·actual value· of schemaLocation, but
8878 * such a strategy risks missing useful information when new
8879 * schemaLocations are offered.
8880 *
8881 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8882 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8883 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008884 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008885 */
8886 if (location == NULL) {
8887 /*
8888 * Schema Document Location Strategy:
8889 *
8890 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008891 * either as a resource which is an XML document or a <schema> element
8892 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008893 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008894 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008895 *
8896 * NOTE: Those stategies are not supported, so we will skip.
8897 */
8898 return (0);
8899 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008900 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008901 ns = XML_SCHEMAS_NO_NAMESPACE;
8902 else
8903 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008904
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008905 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008906 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008907 /*
8908 * There was a valid resource for the specified namespace already
8909 * defined, so skip.
8910 * TODO: This might be changed someday to allow import of
8911 * components from multiple documents for a single target namespace.
8912 */
8913 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008914 }
8915 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8916 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8917 else {
8918 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8919 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8920 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008921 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008922 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008923 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008924 * 2 Based on the location URI, identify an existing schema document,
8925 * either as a resource which is an XML document or a <schema> element
8926 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008927 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008928 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * web which is or contains or references a <schema> element;
8930 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8931 *
8932 */
8933 if ((absolute == 0) && (node != NULL)) {
8934 xmlChar *base, *URI;
8935
8936 base = xmlNodeGetBase(node->doc, node);
8937 if (base == NULL) {
8938 URI = xmlBuildURI(location, node->doc->URL);
8939 } else {
8940 URI = xmlBuildURI(location, base);
8941 xmlFree(base);
8942 }
8943 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008944 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008945 xmlFree(URI);
8946 }
8947 }
8948 parserCtxt = xmlNewParserCtxt();
8949 if (parserCtxt == NULL) {
8950 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8951 "allocating a parser context", NULL);
8952 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008953 }
8954 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008955 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008956 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008957 xmlDictReference(parserCtxt->dict);
8958 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008961 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008962 * 2.1 The referent is (a fragment of) a resource which is an
8963 * XML document (see clause 1.1), which in turn corresponds to
8964 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008965 * set, which in turn corresponds to a valid schema.
8966 * TODO: What to do with the "fragment" stuff?
8967 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008968 * 2.2 The referent is a <schema> element information item in
8969 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008973 */
8974 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008975 xmlErrorPtr lerr;
8976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008977 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008978 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008979 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 * If the doc is NULL and the parser error is an IO error we
8981 * will assume that the resource could not be located or accessed.
8982 *
8983 * TODO: Try to find specific error codes to react only on
8984 * localisation failures.
8985 *
8986 * TODO, FIXME: Check the spec: is a namespace added to the imported
8987 * namespaces, even if the schemaLocation did not provide
8988 * a resource? I guess so, since omitting the "schemaLocation"
8989 * attribute, imports a namespace as well.
8990 */
8991 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 xmlFreeParserCtxt(parserCtxt);
8994 return(0);
8995 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008997 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008998 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008999 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 xmlFreeParserCtxt(parserCtxt);
9002 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9003 }
9004 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009005
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009006 root = xmlDocGetRootElement(*doc);
9007 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009008 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009009 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009010 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009011 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009012 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009013 xmlFreeDoc(*doc);
9014 *doc = NULL;
9015 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 }
9017
9018 xmlSchemaCleanupDoc(pctxt, root);
9019
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009020 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009022 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009023 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009024 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009025 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009026 xmlFreeDoc(*doc);
9027 *doc = NULL;
9028 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009029 }
9030 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009031 /*
9032 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009033 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009034 if (nsName == NULL) {
9035 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009037 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009039 "The XML schema to be imported is not expected "
9040 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009041 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009042 xmlFreeDoc(*doc);
9043 *doc = NULL;
9044 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9045 }
9046 } else {
9047 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009049 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009050 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009051 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009052 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009053 xmlFreeDoc(*doc);
9054 *doc = NULL;
9055 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9056 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009057 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009058 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009059 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009060 "The XML schema to be imported is expected to have a "
9061 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009062 "its target namespace of '%s'",
9063 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009064 xmlFreeDoc(*doc);
9065 *doc = NULL;
9066 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9067 }
9068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009069 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009070 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009071 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9072 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009073 xmlFreeDoc(*doc);
9074 *doc = NULL;
9075 return (-1);
9076 }
9077 import->schemaLocation = location;
9078 import->doc = *doc;
9079 return (0);
9080}
William M. Brack2f2a6632004-08-20 23:09:47 +00009081
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009082static void
9083xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9084 xmlSchemaPtr schema,
9085 const xmlChar *targetNamespace,
9086 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009087{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009088 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009089 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009090
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009091 /*
9092 * Save and reset the context & schema.
9093 */
9094 oldURL = pctxt->URL;
9095 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009096 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009097 oldLocImps = pctxt->localImports;
9098 pctxt->localImports = NULL;
9099 oldNumLocImps = pctxt->nbLocalImports;
9100 pctxt->nbLocalImports = 0;
9101 oldSizeLocImps = pctxt->sizeLocalImports;
9102 pctxt->sizeLocalImports = 0;
9103 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009104 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009105 xmlSchemaClearSchemaDefaults(schema);
9106 oldTNS = schema->targetNamespace;
9107 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009108 if ((targetNamespace != NULL) &&
9109 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9110 /*
9111 * We are parsing the schema for schema!
9112 */
9113 pctxt->isS4S = 1;
9114 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009115 /*
9116 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009117 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009118 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9119 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9120 /*
9121 * Restore the context & schema.
9122 */
9123 schema->flags = oldFlags;
9124 schema->targetNamespace = oldTNS;
9125 if (pctxt->localImports != NULL)
9126 xmlFree((xmlChar *) pctxt->localImports);
9127 pctxt->localImports = oldLocImps;
9128 pctxt->nbLocalImports = oldNumLocImps;
9129 pctxt->sizeLocalImports = oldSizeLocImps;
9130 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009131 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009132}
9133
William M. Brack2f2a6632004-08-20 23:09:47 +00009134/**
9135 * xmlSchemaParseImport:
9136 * @ctxt: a schema validation context
9137 * @schema: the schema being built
9138 * @node: a subtree containing XML Schema informations
9139 *
9140 * parse a XML schema Import definition
9141 * *WARNING* this interface is highly subject to change
9142 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 * Returns 0 in case of success, a positive error code if
9144 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009145 */
9146static int
9147xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9148 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009149{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009150 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009151 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009152 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009153 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009154 xmlAttrPtr attr;
9155 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009156 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009157
9158 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9159 return (-1);
9160
9161 /*
9162 * Check for illegal attributes.
9163 */
9164 attr = node->properties;
9165 while (attr != NULL) {
9166 if (attr->ns == NULL) {
9167 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9168 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9169 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009170 xmlSchemaPIllegalAttrErr(ctxt,
9171 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9172 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009173 }
9174 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009175 xmlSchemaPIllegalAttrErr(ctxt,
9176 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9177 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009178 }
9179 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009180 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009181 /*
9182 * Extract and validate attributes.
9183 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009184 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9185 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009186 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009187 xmlSchemaPSimpleTypeErr(ctxt,
9188 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9189 NULL, node,
9190 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009191 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009192 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9193 }
9194
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009195 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9196 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009197 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009198 xmlSchemaPSimpleTypeErr(ctxt,
9199 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9200 NULL, node,
9201 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009202 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009203 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009204 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009205 /*
9206 * And now for the children...
9207 */
9208 child = node->children;
9209 if (IS_SCHEMA(child, "annotation")) {
9210 /*
9211 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009212 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009213 */
9214 child = child->next;
9215 }
9216 if (child != NULL) {
9217 xmlSchemaPContentErr(ctxt,
9218 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9219 NULL, NULL, node, child, NULL,
9220 "(annotation?)");
9221 }
9222 /*
9223 * Apply additional constraints.
9224 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009225 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009226 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009227 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9228 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009229 * targetNamespace [attribute].
9230 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009231 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009232 xmlSchemaPCustomErr(ctxt,
9233 XML_SCHEMAP_SRC_IMPORT_1_1,
9234 NULL, NULL, node,
9235 "The value of the attribute 'namespace' must not match "
9236 "the target namespace '%s' of the importing schema",
9237 schema->targetNamespace);
9238 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9239 }
9240 } else {
9241 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009242 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009243 * <schema> must have a targetNamespace [attribute].
9244 */
9245 if (schema->targetNamespace == NULL) {
9246 xmlSchemaPCustomErr(ctxt,
9247 XML_SCHEMAP_SRC_IMPORT_1_2,
9248 NULL, NULL, node,
9249 "The attribute 'namespace' must be existent if "
9250 "the importing schema has no target namespace",
9251 NULL);
9252 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9253 }
9254 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009255 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009256 * Add the namespace to the list of locally imported namespace.
9257 */
9258 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009259 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009260 sizeof(const xmlChar*));
9261 ctxt->sizeLocalImports = 10;
9262 ctxt->nbLocalImports = 0;
9263 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9264 ctxt->sizeLocalImports *= 2;
9265 ctxt->localImports = (const xmlChar **) xmlRealloc(
9266 (xmlChar **) ctxt->localImports,
9267 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9268 }
9269 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9270 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009271 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009272 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009273 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9274 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009275 schemaLocation, &doc, &targetNamespace, 0);
9276 if (ret != 0) {
9277 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009278 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009279 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009280 } else if (doc != NULL) {
9281 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9282 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009283 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009284
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009285 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009286}
9287
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009288/**
9289 * xmlSchemaParseInclude:
9290 * @ctxt: a schema validation context
9291 * @schema: the schema being built
9292 * @node: a subtree containing XML Schema informations
9293 *
9294 * parse a XML schema Include definition
9295 *
William M. Bracke7091952004-05-11 15:09:58 +00009296 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009297 * 1 in case of success.
9298 */
9299static int
9300xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9301 xmlNodePtr node)
9302{
9303 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009304 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009305 xmlDocPtr doc = NULL;
9306 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009307 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009308 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009309 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009310 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009311
9312
9313 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9314 return (-1);
9315
9316 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009317 * Check for illegal attributes.
9318 */
9319 attr = node->properties;
9320 while (attr != NULL) {
9321 if (attr->ns == NULL) {
9322 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9323 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009324 xmlSchemaPIllegalAttrErr(ctxt,
9325 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9326 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009327 }
9328 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 xmlSchemaPIllegalAttrErr(ctxt,
9330 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9331 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009332 }
9333 attr = attr->next;
9334 }
9335 /*
9336 * Extract and validate attributes.
9337 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009338 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009339 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009340 * Preliminary step, extract the URI-Reference for the include and
9341 * make an URI from the base.
9342 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009343 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9344 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009345 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009346 xmlChar *uri = NULL;
9347
9348 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9349 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009350 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009351 base = xmlNodeGetBase(node->doc, node);
9352 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009353 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009354 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009355 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009356 xmlFree(base);
9357 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009358 if (uri == NULL) {
9359 xmlSchemaPErr(ctxt,
9360 node,
9361 XML_SCHEMAP_INTERNAL,
9362 "Internal error: xmlSchemaParseInclude, "
9363 "could not build an URI from the schemaLocation.\n",
9364 NULL, NULL);
9365 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009366 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009367 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9368 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009369 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009370 xmlSchemaPMissingAttrErr(ctxt,
9371 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9372 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009373 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009374 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009375 /*
9376 * And now for the children...
9377 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009378 child = node->children;
9379 while (IS_SCHEMA(child, "annotation")) {
9380 /*
9381 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009382 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009383 */
9384 child = child->next;
9385 }
9386 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009387 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009388 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9389 NULL, NULL, node, child, NULL,
9390 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009391 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009392 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009393 * Report self-inclusion.
9394 */
9395 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9396 xmlSchemaPCustomErr(ctxt,
9397 XML_SCHEMAP_SRC_INCLUDE,
9398 NULL, NULL, node,
9399 "The schema document '%s' cannot include itself.",
9400 schemaLocation);
9401 return (XML_SCHEMAP_SRC_INCLUDE);
9402 }
9403 /*
9404 * Check if this one was already processed to avoid incorrect
9405 * duplicate component errors and infinite circular inclusion.
9406 */
9407 include = schema->includes;
9408 while (include != NULL) {
9409 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9410 targetNamespace = include->origTargetNamespace;
9411 if (targetNamespace == NULL) {
9412 /*
9413 * Chameleon include: skip only if it was build for
9414 * the targetNamespace of the including schema.
9415 */
9416 if (xmlStrEqual(schema->targetNamespace,
9417 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009418 goto check_targetNamespace;
9419 }
9420 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009421 goto check_targetNamespace;
9422 }
9423 }
9424 include = include->next;
9425 }
9426 /*
9427 * First step is to parse the input document into an DOM/Infoset
9428 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009429 */
9430 parserCtxt = xmlNewParserCtxt();
9431 if (parserCtxt == NULL) {
9432 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9433 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009434 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009435 }
9436
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009437 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9438 xmlDictFree(parserCtxt->dict);
9439 parserCtxt->dict = ctxt->dict;
9440 xmlDictReference(parserCtxt->dict);
9441 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009442
9443 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009444 NULL, SCHEMAS_PARSE_OPTIONS);
9445 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009446 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009447 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448 * TODO: It is not an error for the ·actual value· of the
9449 * schemaLocation [attribute] to fail to resolve it all, in which
9450 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009451 * So do we need a warning report here?
9452 */
9453 xmlSchemaPCustomErr(ctxt,
9454 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009455 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009456 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009457 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009458 }
9459
9460 /*
9461 * Then extract the root of the schema
9462 */
9463 root = xmlDocGetRootElement(doc);
9464 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009465 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009466 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009467 NULL, NULL, node,
9468 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009469 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009470 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009471 }
9472
9473 /*
9474 * Remove all the blank text nodes
9475 */
9476 xmlSchemaCleanupDoc(ctxt, root);
9477
9478 /*
9479 * Check the schemas top level element
9480 */
9481 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009482 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009483 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009484 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009485 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009486 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009487 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009488 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009489
William M. Brack2f2a6632004-08-20 23:09:47 +00009490 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009491 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009492 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9493 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009494 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9495 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009496check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009497 if (targetNamespace != NULL) {
9498 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009499 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009500 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009501 NULL, NULL, node,
9502 "The target namespace of the included schema "
9503 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009504 "has no target namespace",
9505 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009506 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009507 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9508 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009510 NULL, NULL, node,
9511 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009512 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009513 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009514 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009515 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009516 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009517 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009518 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009519 } else
9520 wasConvertingNs = 1;
9521 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009522
9523 if (include != NULL)
9524 goto exit;
9525
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009526 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009527 * URGENT TODO: If the schema is a chameleon-include then copy the
9528 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009529 * of those components, do nothing otherwise.
9530 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009531 * for every destinct including targetNamespace; thus not performant at
9532 * the moment.
9533 * TODO: Check when the namespace in wildcards for chameleons needs
9534 * to be converted: before we built wildcard intersections or after.
9535 */
9536 /*
9537 * Register the include.
9538 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009539 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9540 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009541 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9542 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009543 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009544 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009545 include->next = schema->includes;
9546 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009547 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009548 * TODO: Use the resolved URI for the this location, since it might
9549 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009550 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009551 include->schemaLocation = schemaLocation;
9552 include->doc = doc;
9553 /*
9554 * In case of chameleons, the original target namespace will differ
9555 * from the resulting namespace.
9556 */
9557 include->origTargetNamespace = targetNamespace;
9558 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009559#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009560 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009561 xmlGenericError(xmlGenericErrorContext,
9562 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9563 " into TNS '%s'\n", schemaLocation,
9564 targetNamespace, schema->targetNamespace);
9565 else
9566 xmlGenericError(xmlGenericErrorContext,
9567 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9568 targetNamespace);
9569#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009570 /*
9571 * Compile the included schema.
9572 */
9573 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9574
9575exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009576 /*
9577 * Remove the converting flag.
9578 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009579 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009580 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009581 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009582 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009583
9584exit_invalid:
9585 if (doc != NULL) {
9586 if (include != NULL)
9587 include->doc = NULL;
9588 xmlFreeDoc(doc);
9589 }
9590 return (ctxt->err);
9591
9592exit_failure:
9593 if (doc != NULL) {
9594 if (include != NULL)
9595 include->doc = NULL;
9596 xmlFreeDoc(doc);
9597 }
9598 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009599}
9600
9601/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009602 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009603 * @ctxt: a schema validation context
9604 * @schema: the schema being built
9605 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009606 * @type: the "compositor" type
9607 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009608 *
9609 * parse a XML schema Sequence definition
9610 * *WARNING* this interface is highly subject to change
9611 *
William M. Bracke7091952004-05-11 15:09:58 +00009612 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009613 * 1 in case of success.
9614 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009615static xmlSchemaTreeItemPtr
9616xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9617 xmlNodePtr node, xmlSchemaTypeType type,
9618 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009619{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009620 xmlSchemaModelGroupPtr item;
9621 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009622 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009623 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009624 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009625 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009626
9627 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009628 return (NULL);
9629 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009630 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009631 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009632 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9633 if (item == NULL)
9634 return (NULL);
9635
9636 if (withParticle) {
9637 if (type == XML_SCHEMA_TYPE_ALL) {
9638 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009639 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009640 } else {
9641 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009642 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9643 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9644 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009645 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9647 /*
9648 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 */
9650 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9651 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009652 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009653 particle->children = (xmlSchemaTreeItemPtr) item;
9654 /*
9655 * Check for illegal attributes.
9656 */
9657 attr = node->properties;
9658 while (attr != NULL) {
9659 if (attr->ns == NULL) {
9660 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9661 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9662 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009663 xmlSchemaPIllegalAttrErr(ctxt,
9664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9665 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009666 }
9667 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009668 xmlSchemaPIllegalAttrErr(ctxt,
9669 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9670 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009671 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009672 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009673 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009674 } else {
9675 /*
9676 * Check for illegal attributes.
9677 */
9678 attr = node->properties;
9679 while (attr != NULL) {
9680 if (attr->ns == NULL) {
9681 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 xmlSchemaPIllegalAttrErr(ctxt,
9683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9684 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009685 }
9686 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009687 xmlSchemaPIllegalAttrErr(ctxt,
9688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9689 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009690 }
9691 attr = attr->next;
9692 }
9693
William M. Brack2f2a6632004-08-20 23:09:47 +00009694 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009695
William M. Brack2f2a6632004-08-20 23:09:47 +00009696 /*
9697 * Extract and validate attributes.
9698 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009699 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009700 /*
9701 * And now for the children...
9702 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009703 child = node->children;
9704 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009705 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009706 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009707 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009708 oldcontainer = ctxt->container;
9709 ctxt->container = container;
9710 if (type == XML_SCHEMA_TYPE_ALL) {
9711 xmlSchemaParticlePtr part, last = NULL;
9712
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009713 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9715 schema, child, 0);
9716 if (part != NULL) {
9717 if (part->minOccurs > 1)
9718 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009719 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009720 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9721 if (part->maxOccurs > 1)
9722 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009723 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009724 "Invalid value for maxOccurs (must be 0 or 1)",
9725 NULL);
9726 if (last == NULL)
9727 item->children = (xmlSchemaTreeItemPtr) part;
9728 else
9729 last->next = (xmlSchemaTreeItemPtr) part;
9730 last = part;
9731 }
9732 child = child->next;
9733 }
9734 if (child != NULL) {
9735 xmlSchemaPContentErr(ctxt,
9736 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9737 NULL, NULL, node, child, NULL,
9738 "(annotation?, (annotation?, element*)");
9739 }
9740 } else {
9741 /* choice + sequence */
9742 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9743
9744 while ((IS_SCHEMA(child, "element")) ||
9745 (IS_SCHEMA(child, "group")) ||
9746 (IS_SCHEMA(child, "any")) ||
9747 (IS_SCHEMA(child, "choice")) ||
9748 (IS_SCHEMA(child, "sequence"))) {
9749
9750 if (IS_SCHEMA(child, "element")) {
9751 part = (xmlSchemaTreeItemPtr)
9752 xmlSchemaParseElement(ctxt, schema, child, 0);
9753 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009754 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009755 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9756 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009757 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009758 xmlSchemaParseAny(ctxt, schema, child);
9759 } else if (IS_SCHEMA(child, "choice")) {
9760 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9761 XML_SCHEMA_TYPE_CHOICE, 1);
9762 } else if (IS_SCHEMA(child, "sequence")) {
9763 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9764 XML_SCHEMA_TYPE_SEQUENCE, 1);
9765 }
9766 if (part != NULL) {
9767 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009768 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009769 else
9770 last->next = part;
9771 last = part;
9772 }
9773 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009774 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009775 if (child != NULL) {
9776 xmlSchemaPContentErr(ctxt,
9777 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9778 NULL, NULL, node, child, NULL,
9779 "(annotation?, (element | group | choice | sequence | any)*)");
9780 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009781 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009782 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009783 if (withParticle) {
9784 if ((min == 0) && (max == 0))
9785 return (NULL);
9786 else
9787 return ((xmlSchemaTreeItemPtr) particle);
9788 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009789 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009790}
9791
9792/**
9793 * xmlSchemaParseRestriction:
9794 * @ctxt: a schema validation context
9795 * @schema: the schema being built
9796 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009797 *
9798 * parse a XML schema Restriction definition
9799 * *WARNING* this interface is highly subject to change
9800 *
9801 * Returns the type definition or NULL in case of error
9802 */
9803static xmlSchemaTypePtr
9804xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009805 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009806{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009807 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009808 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009809 char buf[30];
9810 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009811 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009812
9813 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9814 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009815 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009816 type = ctxt->ctxtType;
9817 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009818
9819 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 * TODO: Is the container needed at all? the anonymous
9821 * items inside should generate unique names already.
9822 */
9823 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009824 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 /*
9826 * Check for illegal attributes.
9827 */
9828 attr = node->properties;
9829 while (attr != NULL) {
9830 if (attr->ns == NULL) {
9831 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9832 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009833 xmlSchemaPIllegalAttrErr(ctxt,
9834 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9835 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009836 }
9837 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009838 xmlSchemaPIllegalAttrErr(ctxt,
9839 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9840 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009841 }
9842 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009843 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009844 /*
9845 * Extract and validate attributes.
9846 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009847 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009848 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009849 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009850 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009851 /*
9852 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9853 * among its [children]), the simple type definition which is
9854 * the {content type} of the type definition ·resolved· to by
9855 * the ·actual value· of the base [attribute]"
9856 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009857 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009858 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009859 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009860 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009861 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009862 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009863 XML_SCHEMAP_S4S_ATTR_MISSING,
9864 type, node, "base", NULL);
9865 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009866 /*
9867 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009868 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009869 child = node->children;
9870 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009871 /*
9872 * Add the annotation to the simple type ancestor.
9873 */
9874 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9875 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009876 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009877 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009878 oldcontainer = ctxt->container;
9879 ctxt->container = container;
9880 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9881 /*
9882 * Corresponds to <simpleType><restriction><simpleType>.
9883 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009884 if (IS_SCHEMA(child, "simpleType")) {
9885 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009886 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009887 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009888 * Either the base [attribute] or the simpleType [child] of the
9889 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009890 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009891 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009892 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009893 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009894 "The attribute 'base' and the <simpleType> child are "
9895 "mutually exclusive", NULL);
9896 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009897 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009898 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009899 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009900 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009902 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009903 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9904 NULL, NULL, node, child,
9905 "Either the attribute 'base' or a <simpleType> child "
9906 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009907 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009908 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9909 /*
9910 * Corresponds to <complexType><complexContent><restriction>...
9911 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009912 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 * Model groups <all>, <choice> and <sequence>.
9914 */
9915 if (IS_SCHEMA(child, "all")) {
9916 type->subtypes = (xmlSchemaTypePtr)
9917 xmlSchemaParseModelGroup(ctxt, schema, child,
9918 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009919 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009920 } else if (IS_SCHEMA(child, "choice")) {
9921 type->subtypes = (xmlSchemaTypePtr)
9922 xmlSchemaParseModelGroup(ctxt,
9923 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9924 child = child->next;
9925 } else if (IS_SCHEMA(child, "sequence")) {
9926 type->subtypes = (xmlSchemaTypePtr)
9927 xmlSchemaParseModelGroup(ctxt, schema, child,
9928 XML_SCHEMA_TYPE_SEQUENCE, 1);
9929 child = child->next;
9930 /*
9931 * Model group reference <group>.
9932 */
9933 } else if (IS_SCHEMA(child, "group")) {
9934 type->subtypes = (xmlSchemaTypePtr)
9935 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9936 child = child->next;
9937 }
9938 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009939 /*
9940 * Corresponds to <complexType><simpleContent><restriction>...
9941 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009942 * "1.1 the simple type definition corresponding to the <simpleType>
9943 * among the [children] of <restriction> if there is one;"
9944 */
9945 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009946 /*
9947 * We will store the to-be-restricted simple type in
9948 * type->contentTypeDef *temporarily*.
9949 */
9950 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009951 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009952 if ( type->contentTypeDef == NULL)
9953 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009954 child = child->next;
9955 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009956 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009957
9958 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009959 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009960 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009961 /*
9962 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009963 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009964 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009965
Daniel Veillard01fa6152004-06-29 17:04:39 +00009966 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009967 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009968 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009969 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9971 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009972 * *Single Facet Value*
9973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009974 while ((IS_SCHEMA(child, "minInclusive")) ||
9975 (IS_SCHEMA(child, "minExclusive")) ||
9976 (IS_SCHEMA(child, "maxInclusive")) ||
9977 (IS_SCHEMA(child, "maxExclusive")) ||
9978 (IS_SCHEMA(child, "totalDigits")) ||
9979 (IS_SCHEMA(child, "fractionDigits")) ||
9980 (IS_SCHEMA(child, "pattern")) ||
9981 (IS_SCHEMA(child, "enumeration")) ||
9982 (IS_SCHEMA(child, "whiteSpace")) ||
9983 (IS_SCHEMA(child, "length")) ||
9984 (IS_SCHEMA(child, "maxLength")) ||
9985 (IS_SCHEMA(child, "minLength"))) {
9986 facet = xmlSchemaParseFacet(ctxt, schema, child);
9987 if (facet != NULL) {
9988 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009989 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009990 else
9991 lastfacet->next = facet;
9992 lastfacet = facet;
9993 lastfacet->next = NULL;
9994 }
9995 child = child->next;
9996 }
9997 /*
9998 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009999 */
10000 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010001 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10002
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010003 facet = type->facets;
10004 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010005 facetLink = (xmlSchemaFacetLinkPtr)
10006 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010007 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010008 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010009 xmlFree(facetLink);
10010 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010011 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010012 facetLink->facet = facet;
10013 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010014 if (lastFacetLink == NULL)
10015 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010016 else
10017 lastFacetLink->next = facetLink;
10018 lastFacetLink = facetLink;
10019 facet = facet->next;
10020 } while (facet != NULL);
10021 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010022 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010023 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10024 /*
10025 * Attribute uses/declarations.
10026 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010027 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010028 /*
10029 * Attribute wildcard.
10030 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010031 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 type->attributeWildcard =
10033 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010034 child = child->next;
10035 }
10036 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010037 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010038 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10039 xmlSchemaPContentErr(ctxt,
10040 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010041 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010042 "annotation?, (group | all | choice | sequence)?, "
10043 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010045 xmlSchemaPContentErr(ctxt,
10046 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010047 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010048 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10049 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10050 "length | minLength | maxLength | enumeration | whiteSpace | "
10051 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10052 } else {
10053 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010054 xmlSchemaPContentErr(ctxt,
10055 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010056 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010057 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10058 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10059 "length | minLength | maxLength | enumeration | whiteSpace | "
10060 "pattern)*))");
10061 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010062 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010063 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010064 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010065}
10066
10067/**
10068 * xmlSchemaParseExtension:
10069 * @ctxt: a schema validation context
10070 * @schema: the schema being built
10071 * @node: a subtree containing XML Schema informations
10072 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010073 * Parses an <extension>, which is found inside a
10074 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010075 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010076 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010077 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010078 */
10079static xmlSchemaTypePtr
10080xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010081 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010082{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010083 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010084 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010085 char buf[30];
10086 const xmlChar *oldcontainer, *container;
10087 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010088
10089 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10090 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010091 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010092 type = ctxt->ctxtType;
10093 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010094
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010095 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10096 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10097 /*
10098 * Check for illegal attributes.
10099 */
10100 attr = node->properties;
10101 while (attr != NULL) {
10102 if (attr->ns == NULL) {
10103 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10104 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010105 xmlSchemaPIllegalAttrErr(ctxt,
10106 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10107 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010108 }
10109 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010110 xmlSchemaPIllegalAttrErr(ctxt,
10111 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10112 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010113 }
10114 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010115 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010116
10117 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010118
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010119 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010120 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010121 */
10122 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010123 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10124 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010125 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010126 XML_SCHEMAP_S4S_ATTR_MISSING,
10127 NULL, node, "base", NULL);
10128 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010129 /*
10130 * And now for the children...
10131 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010132 child = node->children;
10133 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 /*
10135 * Add the annotation to the type ancestor.
10136 */
10137 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10138 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010139 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010140 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010141 oldcontainer = ctxt->container;
10142 ctxt->container = container;
10143 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10144 /*
10145 * Corresponds to <complexType><complexContent><extension>... and:
10146 *
10147 * Model groups <all>, <choice>, <sequence> and <group>.
10148 */
10149 if (IS_SCHEMA(child, "all")) {
10150 type->subtypes = (xmlSchemaTypePtr)
10151 xmlSchemaParseModelGroup(ctxt, schema,
10152 child, XML_SCHEMA_TYPE_ALL, 1);
10153 child = child->next;
10154 } else if (IS_SCHEMA(child, "choice")) {
10155 type->subtypes = (xmlSchemaTypePtr)
10156 xmlSchemaParseModelGroup(ctxt, schema,
10157 child, XML_SCHEMA_TYPE_CHOICE, 1);
10158 child = child->next;
10159 } else if (IS_SCHEMA(child, "sequence")) {
10160 type->subtypes = (xmlSchemaTypePtr)
10161 xmlSchemaParseModelGroup(ctxt, schema,
10162 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10163 child = child->next;
10164 } else if (IS_SCHEMA(child, "group")) {
10165 type->subtypes = (xmlSchemaTypePtr)
10166 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10167 child = child->next;
10168 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010169 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010170 if (child != NULL) {
10171 /*
10172 * Attribute uses/declarations.
10173 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010174 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175 /*
10176 * Attribute wildcard.
10177 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010178 if (IS_SCHEMA(child, "anyAttribute")) {
10179 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010180 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10181 child = child->next;
10182 }
10183 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010184 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10186 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010187 xmlSchemaPContentErr(ctxt,
10188 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010189 NULL, NULL, node, child, NULL,
10190 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010191 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010192 } else {
10193 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010194 xmlSchemaPContentErr(ctxt,
10195 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010196 NULL, NULL, node, child, NULL,
10197 "(annotation?, ((attribute | attributeGroup)*, "
10198 "anyAttribute?))");
10199 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010200 }
10201 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010202 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010203}
10204
10205/**
10206 * xmlSchemaParseSimpleContent:
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 SimpleContent 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 +000010217xmlSchemaParseSimpleContent(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. Buchcikaba15f72005-04-01 15:17:27 +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;
10228 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10229 /*
10230 * Check for illegal attributes.
10231 */
10232 attr = node->properties;
10233 while (attr != NULL) {
10234 if (attr->ns == NULL) {
10235 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010236 xmlSchemaPIllegalAttrErr(ctxt,
10237 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10238 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010239 }
10240 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010241 xmlSchemaPIllegalAttrErr(ctxt,
10242 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10243 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010244 }
10245 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010246 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010247
10248 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010249
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010250 /*
10251 * And now for the children...
10252 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010253 child = node->children;
10254 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010255 /*
10256 * Add the annotation to the complex type ancestor.
10257 */
10258 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10259 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010260 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010261 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010262 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010263 xmlSchemaParseRestriction(ctxt, schema, child,
10264 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010265 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010266 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010267 xmlSchemaParseExtension(ctxt, schema, child,
10268 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010269 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010270 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010271 if (child != NULL) {
10272 xmlSchemaPContentErr(ctxt,
10273 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010274 NULL, NULL, node, child, NULL,
10275 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010276 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010277 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010278}
10279
10280/**
10281 * xmlSchemaParseComplexContent:
10282 * @ctxt: a schema validation context
10283 * @schema: the schema being built
10284 * @node: a subtree containing XML Schema informations
10285 *
10286 * parse a XML schema ComplexContent definition
10287 * *WARNING* this interface is highly subject to change
10288 *
10289 * Returns the type definition or NULL in case of error
10290 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010291static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010292xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10293 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010294{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010295 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010296 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010297 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010298
10299 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010300 return (-1);
10301 /* Not a component, don't create it. */
10302 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010303 /*
10304 * Check for illegal attributes.
10305 */
10306 attr = node->properties;
10307 while (attr != NULL) {
10308 if (attr->ns == NULL) {
10309 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010310 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010311 {
10312 xmlSchemaPIllegalAttrErr(ctxt,
10313 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10314 NULL, NULL, attr);
10315 }
10316 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10317 xmlSchemaPIllegalAttrErr(ctxt,
10318 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10319 NULL, NULL, attr);
10320 }
10321 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010322 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010323
10324 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10325
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010326 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010327 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010328 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010329 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10330 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10331 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010332 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010333 child = node->children;
10334 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010335 /*
10336 * Add the annotation to the complex type ancestor.
10337 */
10338 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10339 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010340 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010341 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010342 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010343 xmlSchemaParseRestriction(ctxt, schema, child,
10344 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010345 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010346 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010347 xmlSchemaParseExtension(ctxt, schema, child,
10348 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010349 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010350 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010351 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010352 xmlSchemaPContentErr(ctxt,
10353 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10354 NULL, NULL, node, child,
10355 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010356 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010357 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010358}
10359
10360/**
10361 * xmlSchemaParseComplexType:
10362 * @ctxt: a schema validation context
10363 * @schema: the schema being built
10364 * @node: a subtree containing XML Schema informations
10365 *
10366 * parse a XML schema Complex Type definition
10367 * *WARNING* this interface is highly subject to change
10368 *
10369 * Returns the type definition or NULL in case of error
10370 */
10371static xmlSchemaTypePtr
10372xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010373 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010374{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010375 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010376 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010377 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010378 xmlAttrPtr attr;
10379 const xmlChar *attrValue;
10380 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010381 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010382 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010383
Daniel Veillard4255d502002-04-16 15:50:10 +000010384
10385 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10386 return (NULL);
10387
Daniel Veillard01fa6152004-06-29 17:04:39 +000010388 ctxtType = ctxt->ctxtType;
10389
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010390 if (topLevel) {
10391 attr = xmlSchemaGetPropNode(node, "name");
10392 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010393 xmlSchemaPMissingAttrErr(ctxt,
10394 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010395 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010396 } else if (xmlSchemaPValAttrNode(ctxt,
10397 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010398 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10399 return (NULL);
10400 }
10401 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010402
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010403 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010404 /*
10405 * Parse as local complex type definition.
10406 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010407 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10409 if (type == NULL)
10410 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010411 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010412 type->node = node;
10413 type->type = XML_SCHEMA_TYPE_COMPLEX;
10414 /*
10415 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010416 */
10417 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010418 /*
10419 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010420 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010421 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010422 if (type == NULL)
10423 return (NULL);
10424 type->node = node;
10425 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010426 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010427 }
10428 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010429 /*
10430 * Handle attributes.
10431 */
10432 attr = node->properties;
10433 while (attr != NULL) {
10434 if (attr->ns == NULL) {
10435 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10436 /*
10437 * Attribute "id".
10438 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010439 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10440 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010441 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10442 /*
10443 * Attribute "mixed".
10444 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010445 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010446 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010447 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10448 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010449 /*
10450 * Attributes of global complex type definitions.
10451 */
10452 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10453 /* Pass. */
10454 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10455 /*
10456 * Attribute "abstract".
10457 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010458 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10459 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010460 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10461 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10462 /*
10463 * Attribute "final".
10464 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010465 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010466 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010467 if (xmlSchemaPValAttrBlockFinal(attrValue,
10468 &(type->flags),
10469 -1,
10470 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10471 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10472 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010473 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010474 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010475 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010476 type, (xmlNodePtr) attr, NULL,
10477 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010478 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010479 } else
10480 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010481 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10482 /*
10483 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010484 */
10485 attrValue = xmlSchemaGetNodeContent(ctxt,
10486 (xmlNodePtr) attr);
10487 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010488 -1,
10489 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010490 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010491 -1, -1, -1) != 0) {
10492 xmlSchemaPSimpleTypeErr(ctxt,
10493 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010494 type, (xmlNodePtr) attr, NULL,
10495 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010496 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010497 } else
10498 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010499 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010500 xmlSchemaPIllegalAttrErr(ctxt,
10501 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010502 &des, type, attr);
10503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010504 } else {
10505 xmlSchemaPIllegalAttrErr(ctxt,
10506 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010507 &des, type, attr);
10508 }
10509 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010510 xmlSchemaPIllegalAttrErr(ctxt,
10511 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10512 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010513 }
10514 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010515 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010516 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010517 /*
10518 * Apply default "block" values.
10519 */
10520 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10521 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10522 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10523 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10524 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010525 if (! final) {
10526 /*
10527 * Apply default "block" values.
10528 */
10529 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10530 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10531 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10532 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10533 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010534 /*
10535 * And now for the children...
10536 */
10537 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010538 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010539 child = node->children;
10540 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010541 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10542 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010543 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010544 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010545 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010546 /*
10547 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010548 * Specifying mixed='true' when the <simpleContent>
10549 * alternative is chosen has no effect
10550 */
William M. Bracke7091952004-05-11 15:09:58 +000010551 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10552 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010553 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010554 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010555 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010556 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10557 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010558 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010559 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010560 /*
10561 * SPEC
10562 * "...the third alternative (neither <simpleContent> nor
10563 * <complexContent>) is chosen. This case is understood as shorthand
10564 * for complex content restricting the ·ur-type definition·, and the
10565 * details of the mappings should be modified as necessary.
10566 */
10567 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10568 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010569 /*
10570 * Parse model groups.
10571 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010572 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010573 type->subtypes = (xmlSchemaTypePtr)
10574 xmlSchemaParseModelGroup(ctxt, schema, child,
10575 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010576 child = child->next;
10577 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010578 type->subtypes = (xmlSchemaTypePtr)
10579 xmlSchemaParseModelGroup(ctxt, schema, child,
10580 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010581 child = child->next;
10582 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010583 type->subtypes = (xmlSchemaTypePtr)
10584 xmlSchemaParseModelGroup(ctxt, schema, child,
10585 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010586 child = child->next;
10587 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010588 type->subtypes = (xmlSchemaTypePtr)
10589 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010590 child = child->next;
10591 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010592 /*
10593 * Parse attribute decls/refs.
10594 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010595 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010596 /*
10597 * Parse attribute wildcard.
10598 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010599 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010600 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10601 child = child->next;
10602 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010603 }
10604 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010605 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010606 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010607 &des, type, node, child,
10608 NULL, "(annotation?, (simpleContent | complexContent | "
10609 "((group | all | choice | sequence)?, ((attribute | "
10610 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010611 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010612 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010613 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010614 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010615 return (type);
10616}
10617
Daniel Veillard4255d502002-04-16 15:50:10 +000010618/**
10619 * xmlSchemaParseSchema:
10620 * @ctxt: a schema validation context
10621 * @node: a subtree containing XML Schema informations
10622 *
10623 * parse a XML schema definition from a node set
10624 * *WARNING* this interface is highly subject to change
10625 *
10626 * Returns the internal XML Schema structure built from the resource or
10627 * NULL in case of error
10628 */
10629static xmlSchemaPtr
10630xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10631{
10632 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010633 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010634 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010635 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010636
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010637 /*
10638 * This one is called by xmlSchemaParse only and is used if
10639 * the schema to be parsed was specified via the API; i.e. not
10640 * automatically by the validated instance document.
10641 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010642 if ((ctxt == NULL) || (node == NULL))
10643 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010644 nberrors = ctxt->nberrors;
10645 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010646 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010647 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010648 xmlSchemaImportPtr import;
10649
Daniel Veillard4255d502002-04-16 15:50:10 +000010650 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010651 if (schema == NULL)
10652 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010653 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010654 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010655 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010656 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10657 /*
10658 * TODO: Should we proceed with an invalid target namespace?
10659 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010660 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010661 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10662 /*
10663 * We are parsing the schema for schema!
10664 */
10665 ctxt->isS4S = 1;
10666 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010667 } else {
10668 schema->targetNamespace = NULL;
10669 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010670 /*
10671 * Add the current ns name and location to the import table;
10672 * this is needed to have a consistent mechanism, regardless
10673 * if all schemata are constructed dynamically fired by the
10674 * instance or if the schema to be used was specified via
10675 * the API.
10676 */
10677 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10678 schema->targetNamespace);
10679 if (import == NULL) {
10680 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10681 NULL, NULL, (xmlNodePtr) ctxt->doc,
10682 "Internal error: xmlSchemaParseSchema, "
10683 "failed to add an import entry", NULL);
10684 xmlSchemaFree(schema);
10685 schema = NULL;
10686 return (NULL);
10687 }
10688 import->schemaLocation = ctxt->URL;
10689 /*
10690 * NOTE: We won't set the doc here, otherwise it will be freed
10691 * if the import struct is freed.
10692 * import->doc = ctxt->doc;
10693 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010694 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010695 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10696 } else {
10697 xmlDocPtr doc;
10698
10699 doc = node->doc;
10700
10701 if ((doc != NULL) && (doc->URL != NULL)) {
10702 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10703 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010704 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010705 } else {
10706 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10707 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010708 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010709 }
10710 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010711 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010712 if (ctxt->nberrors != 0) {
10713 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010714 xmlSchemaFree(schema);
10715 schema = NULL;
10716 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010717 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010718 if (schema != NULL)
10719 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010720 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010721#ifdef DEBUG
10722 if (schema == NULL)
10723 xmlGenericError(xmlGenericErrorContext,
10724 "xmlSchemaParse() failed\n");
10725#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010726 return (schema);
10727}
10728
10729/************************************************************************
10730 * *
10731 * Validating using Schemas *
10732 * *
10733 ************************************************************************/
10734
10735/************************************************************************
10736 * *
10737 * Reading/Writing Schemas *
10738 * *
10739 ************************************************************************/
10740
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010741#if 0 /* Will be enabled if it is clear what options are needed. */
10742/**
10743 * xmlSchemaParserCtxtSetOptions:
10744 * @ctxt: a schema parser context
10745 * @options: a combination of xmlSchemaParserOption
10746 *
10747 * Sets the options to be used during the parse.
10748 *
10749 * Returns 0 in case of success, -1 in case of an
10750 * API error.
10751 */
10752static int
10753xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10754 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010755
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010756{
10757 int i;
10758
10759 if (ctxt == NULL)
10760 return (-1);
10761 /*
10762 * WARNING: Change the start value if adding to the
10763 * xmlSchemaParseOption.
10764 */
10765 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10766 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010767 return (-1);
10768 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010769 }
10770 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010771 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010772}
10773
10774/**
10775 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010776 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010777 *
10778 * Returns the option combination of the parser context.
10779 */
10780static int
10781xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010782
10783{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010784 if (ctxt == NULL)
10785 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010786 else
10787 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010788}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010789#endif
10790
Daniel Veillard4255d502002-04-16 15:50:10 +000010791/**
10792 * xmlSchemaNewParserCtxt:
10793 * @URL: the location of the schema
10794 *
10795 * Create an XML Schemas parse context for that file/resource expected
10796 * to contain an XML Schemas file.
10797 *
10798 * Returns the parser context or NULL in case of error
10799 */
10800xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010801xmlSchemaNewParserCtxt(const char *URL)
10802{
Daniel Veillard4255d502002-04-16 15:50:10 +000010803 xmlSchemaParserCtxtPtr ret;
10804
10805 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010806 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010807
10808 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10809 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010810 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010811 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010812 return (NULL);
10813 }
10814 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010815 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010816 ret->dict = xmlDictCreate();
10817 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010818 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010819 return (ret);
10820}
10821
10822/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010823 * xmlSchemaNewMemParserCtxt:
10824 * @buffer: a pointer to a char array containing the schemas
10825 * @size: the size of the array
10826 *
10827 * Create an XML Schemas parse context for that memory buffer expected
10828 * to contain an XML Schemas file.
10829 *
10830 * Returns the parser context or NULL in case of error
10831 */
10832xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010833xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10834{
Daniel Veillard6045c902002-10-09 21:13:59 +000010835 xmlSchemaParserCtxtPtr ret;
10836
10837 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010838 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010839
10840 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10841 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010842 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010843 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010844 return (NULL);
10845 }
10846 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10847 ret->buffer = buffer;
10848 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010849 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010850 return (ret);
10851}
10852
10853/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010854 * xmlSchemaNewDocParserCtxt:
10855 * @doc: a preparsed document tree
10856 *
10857 * Create an XML Schemas parse context for that document.
10858 * NB. The document may be modified during the parsing process.
10859 *
10860 * Returns the parser context or NULL in case of error
10861 */
10862xmlSchemaParserCtxtPtr
10863xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10864{
10865 xmlSchemaParserCtxtPtr ret;
10866
10867 if (doc == NULL)
10868 return (NULL);
10869
10870 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10871 if (ret == NULL) {
10872 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10873 NULL);
10874 return (NULL);
10875 }
10876 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10877 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010878 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010879 /* The application has responsibility for the document */
10880 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010881
10882 return (ret);
10883}
10884
10885/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010886 * xmlSchemaFreeParserCtxt:
10887 * @ctxt: the schema parser context
10888 *
10889 * Free the resources associated to the schema parser context
10890 */
10891void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010892xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10893{
Daniel Veillard4255d502002-04-16 15:50:10 +000010894 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010895 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010896 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010897 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010898 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010899 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010900 xmlFree(ctxt->assemble);
10901 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010902 if (ctxt->vctxt != NULL) {
10903 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10904 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010905 if (ctxt->localImports != NULL)
10906 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010907 if (ctxt->substGroups != NULL)
10908 xmlHashFree(ctxt->substGroups,
10909 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010910 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010911 xmlFree(ctxt);
10912}
10913
10914/************************************************************************
10915 * *
10916 * Building the content models *
10917 * *
10918 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010919
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010920static void
10921xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010922 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010923{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010924 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010925 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010926 xmlSchemaSubstGroupPtr substGroup;
10927 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010928
10929 elemDecl = (xmlSchemaElementPtr) particle->children;
10930 /*
10931 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010932 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010933 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010934 if (end == NULL)
10935 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010936 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10937 if (substGroup == NULL) {
10938 xmlSchemaPErr(pctxt, GET_NODE(particle),
10939 XML_SCHEMAP_INTERNAL,
10940 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10941 "declaration is marked having a subst. group but none "
10942 "available.\n", elemDecl->name, NULL);
10943 return;
10944 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010945 if (counter >= 0) {
10946 /*
10947 * NOTE that we put the declaration in, even if it's abstract,
10948 */
10949 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10950 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10951 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10952 /*
10953 * Add subst. group members.
10954 */
10955 for (i = 0; i < substGroup->members->nbItems; i++) {
10956 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10957 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10958 member->name, member->targetNamespace, member);
10959 }
10960 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010961 /*
10962 * NOTE that we put the declaration in, even if it's abstract,
10963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010964 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010965 xmlAutomataNewTransition2(pctxt->am,
10966 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010967 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10968 /*
10969 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010970 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010971 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010972 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010973 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10974 member->name, member->targetNamespace,
10975 1, 1, member);
10976 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010977 }
10978 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010979 xmlAutomataStatePtr hop;
10980 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10981 UNBOUNDED : particle->maxOccurs - 1;
10982 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10983
10984 counter =
10985 xmlAutomataNewCounter(pctxt->am, minOccurs,
10986 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010987 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010988
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010989 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010990 xmlAutomataNewTransition2(pctxt->am,
10991 start, NULL,
10992 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010993 hop);
10994 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000010995 * Add subst. group members.
10996 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010997 for (i = 0; i < substGroup->members->nbItems; i++) {
10998 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10999 xmlAutomataNewEpsilon(pctxt->am,
11000 xmlAutomataNewTransition2(pctxt->am,
11001 start, NULL,
11002 member->name, member->targetNamespace, member),
11003 hop);
11004 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011005 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11006 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11007 }
11008 if (particle->minOccurs == 0)
11009 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011010 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011011}
11012
11013static void
11014xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11015 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011016{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011017 if (((xmlSchemaElementPtr) particle->children)->flags &
11018 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011019 /*
11020 * Substitution groups.
11021 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011022 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011023 } else {
11024 xmlSchemaElementPtr elemDecl;
11025 xmlAutomataStatePtr start;
11026
11027 elemDecl = (xmlSchemaElementPtr) particle->children;
11028
11029 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011030 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011031 if (particle->maxOccurs == 1) {
11032 start = ctxt->state;
11033 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011034 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11035 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11036 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011037 /* Special case. */
11038 start = ctxt->state;
11039 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11040 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011041 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011042 } else {
11043 int counter;
11044 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11045 UNBOUNDED : particle->maxOccurs - 1;
11046 int minOccurs = particle->minOccurs < 1 ?
11047 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011048
11049 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011050 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11051 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11052 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11053 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11054 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11055 NULL, counter);
11056 }
11057 if (particle->minOccurs == 0)
11058 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11059 }
11060}
11061
Daniel Veillard4255d502002-04-16 15:50:10 +000011062/**
11063 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011064 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011065 * @particle: the particle component
11066 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011067 *
11068 * Generate the automata sequence needed for that type
11069 */
11070static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011071xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011072 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011073 const xmlChar * name)
11074{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011075 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011076 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011077 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011078 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011079 if (particle->children == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011080 PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011081 return;
11082 }
11083
11084 switch (particle->children->type) {
11085 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011086 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011087 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011088 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011089
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011090 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011091
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011092 start = pctxt->state;
11093 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011094
11095 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 if (wild->any == 1) {
11097 /*
11098 * We need to add both transitions:
11099 *
11100 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011101 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011102 pctxt->state =
11103 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011104 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011105 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011106 /*
11107 * 2. the {"*"} for elements in no namespace.
11108 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011109 pctxt->state =
11110 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011111 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011112 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113
11114 } else if (wild->nsSet != NULL) {
11115 ns = wild->nsSet;
11116 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011117 pctxt->state = start;
11118 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
11119 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
11120 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 ns = ns->next;
11122 } while (ns != NULL);
11123
11124 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011125
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011126 /*
11127 * Lead nodes with the negated namespace to the sink-state
11128 * {"*", "##other"}.
11129 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011130 pctxt->state = xmlAutomataNewTransition2(pctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011131 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011132 /*
11133 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011134 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011135 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011136 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011137 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011138 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011139 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011140 } else {
11141 int counter;
11142 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011143 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011144 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011145 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011146 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011147
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011148 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11149 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011150 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011151 pctxt->state =
11152 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011153 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011154 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
11155 pctxt->state =
11156 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011158 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011159 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011160 ns = wild->nsSet;
11161 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011162 pctxt->state =
11163 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011165 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011166 ns = ns->next;
11167 } while (ns != NULL);
11168
11169 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011170 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000011171 start, hop, BAD_CAST "*", wild->negNsSet->value,
11172 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011173 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011174 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11175 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011176 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011177 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011178 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011179 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011180 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011181 break;
11182 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011183 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011184 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011185 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011186 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011187 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011188
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011189 /*
11190 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011191 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011192 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011193 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11194 sub = particle->children->children;
11195 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011196 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011197 (xmlSchemaParticlePtr) sub, name);
11198 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011199 }
11200 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011201 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011202
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011203 if (particle->maxOccurs >= UNBOUNDED) {
11204 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011205 xmlAutomataStatePtr tmp;
11206 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011207
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011208 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011209 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011210 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011211
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011212 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011214
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 sub = particle->children->children;
11216 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011217 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 (xmlSchemaParticlePtr) sub, name);
11219 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011220 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011221 tmp = pctxt->state;
11222 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011223 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011224 pctxt->state =
11225 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011226 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011227
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011228 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011229 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000011230 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011231 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011232
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233 sub = particle->children->children;
11234 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011235 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011236 (xmlSchemaParticlePtr) sub, name);
11237 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011238 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011239 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011240 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011241 /*
11242 * epsilon needed to block previous trans from
11243 * being allowed to enter back from another
11244 * construct
11245 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011246 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
11247 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011249 xmlAutomataNewEpsilon(pctxt->am,
11250 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011251 }
11252 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 } else if ((particle->maxOccurs > 1)
11254 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011255 xmlAutomataStatePtr tmp;
11256 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011257
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011258 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011260 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011261
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011262 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011263 particle->minOccurs - 1,
11264 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011265
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 sub = particle->children->children;
11267 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011268 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011269 (xmlSchemaParticlePtr) sub, name);
11270 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011272 tmp = pctxt->state;
11273 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011274 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011275 pctxt->state =
11276 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011277 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011279 xmlAutomataNewEpsilon(pctxt->am,
11280 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011282 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011283 sub = particle->children->children;
11284 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011285 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011286 (xmlSchemaParticlePtr) sub, name);
11287 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011288 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011289 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011290 xmlAutomataNewEpsilon(pctxt->am, oldstate,
11291 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 }
11293 }
11294 }
11295 break;
11296 }
11297 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011298 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011299 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011300
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011301 start = pctxt->state;
11302 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011303
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011304 /*
11305 * iterate over the subtypes and remerge the end with an
11306 * epsilon transition
11307 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011308 if (particle->maxOccurs == 1) {
11309 sub = particle->children->children;
11310 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011311 pctxt->state = start;
11312 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011313 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011314 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011315 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011316 }
11317 } else {
11318 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011319 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011320 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11321 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011322 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011323 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011324
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011325 /*
11326 * use a counter to keep track of the number of transtions
11327 * which went through the choice.
11328 */
11329 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011330 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11331 hop = xmlAutomataNewState(pctxt->am);
11332 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011333
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011334 sub = particle->children->children;
11335 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011336 pctxt->state = base;
11337 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011338 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011339 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011340 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011341 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011342 xmlAutomataNewEpsilon(pctxt->am, start, base);
11343 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
11344 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011345 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011346 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011347 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011348 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011349 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011350 break;
11351 }
11352 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011353 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011354 xmlSchemaParticlePtr sub;
11355 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011356 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011358 sub = (xmlSchemaParticlePtr) particle->children->children;
11359 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011361 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011363 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011364
11365 elemDecl = (xmlSchemaElementPtr) sub->children;
11366 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011367 PERROR_INT("xmlSchemaBuildAContentModel",
11368 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011369 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011370 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011371 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011372 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011373 * {particles} of the group must be 0 or 1; this is
11374 * already ensured during the parse of the content of
11375 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011376 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011377 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11378 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011379
Daniel Veillarda980bef2005-07-18 21:34:03 +000011380 /*
11381 * This is an abstract group, we need to share
11382 * the same counter for all the element transitions
11383 * derived from the group
11384 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011385 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011386 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011387 xmlSchemaBuildContentModelForSubstGroup(pctxt,
11388 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000011389 } else {
11390 if ((sub->minOccurs == 1) &&
11391 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011392 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
11393 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011394 elemDecl->name,
11395 elemDecl->targetNamespace,
11396 1, 1, elemDecl);
11397 } else if ((sub->minOccurs == 0) &&
11398 (sub->maxOccurs == 1)) {
11399
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011400 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
11401 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011402 elemDecl->name,
11403 elemDecl->targetNamespace,
11404 0,
11405 1,
11406 elemDecl);
11407 }
11408 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011409 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011410 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011411 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011412 pctxt->state =
11413 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011414 break;
11415 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011416 case XML_SCHEMA_TYPE_GROUP:
11417 /*
11418 * If we hit a model group definition, then this means that
11419 * it was empty, thus was not substituted for the containing
11420 * model group. Just do nothing in this case.
11421 */
11422 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011423 default:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011424 xmlSchemaPInternalErr(pctxt, "xmlSchemaBuildAContentModel",
11425 "found unexpected term of type '%s' in content model of complex "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011426 "type '%s'.\n",
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011427 xmlSchemaCompTypeToString(particle->children->type), name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011428 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011429 }
11430}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011431
Daniel Veillard4255d502002-04-16 15:50:10 +000011432/**
11433 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011434 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011436 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011437 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011438 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011439 */
11440static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011441xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011442 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011443 const xmlChar * name)
11444{
Daniel Veillard4255d502002-04-16 15:50:10 +000011445 xmlAutomataStatePtr start;
11446
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011447 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11448 (type->contModel != NULL) ||
11449 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11450 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011451 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011452
11453#ifdef DEBUG_CONTENT
11454 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011455 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011456#endif
11457
Daniel Veillard4255d502002-04-16 15:50:10 +000011458 ctxt->am = xmlNewAutomata();
11459 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011460 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011461 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011462 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011463 }
11464 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011465 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011466 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011467 type->contModel = xmlAutomataCompile(ctxt->am);
11468 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011469 xmlSchemaPCustomErr(ctxt,
11470 XML_SCHEMAP_INTERNAL,
11471 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011472 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011473 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011474 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011475 XML_SCHEMAP_NOT_DETERMINISTIC,
11476 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011477 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011478 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011479 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011480#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011481 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011482 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011483 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011484#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011485 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011486 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011487 xmlFreeAutomata(ctxt->am);
11488 ctxt->am = NULL;
11489}
11490
11491/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011492 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011493 * @elem: the schema element context
11494 * @ctxt: the schema parser context
11495 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011496 * Resolves the references of an element declaration
11497 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011498 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011499 */
11500static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011501xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011502 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011503 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011504 const xmlChar * context ATTRIBUTE_UNUSED,
11505 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011506{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011507 if ((ctxt == NULL) || (elemDecl == NULL) ||
11508 ((elemDecl != NULL) &&
11509 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011510 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011511 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011512
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011513 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011514 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011515
11516 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011517 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011519 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011520 elemDecl->namedTypeNs);
11521 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011522 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011523 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011525 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011526 XML_SCHEMA_TYPE_BASIC, "type definition");
11527 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011528 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011529 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011530 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011531 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011532
Daniel Veillardc0826a72004-08-10 14:17:33 +000011533 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011534 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011535 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011536 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11538 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011539 if (substHead == NULL) {
11540 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011541 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011542 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011543 "substitutionGroup", elemDecl->substGroup,
11544 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011545 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011546 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011547 /*
11548 * Set the "substitution group affiliation".
11549 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011550 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011551 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011552 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011553 * (type definition)...otherwise the {type definition} of the
11554 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011555 * the substitutionGroup [attribute], if present
11556 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011558 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011559 }
11560 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011561 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11562 (elemDecl->substGroup == NULL))
11563 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011564}
11565
11566/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011567 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011568 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011569 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011570 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011571 * Checks and builds the "member type definitions" property of the union
11572 * simple type. This handles part (1), part (2) is done in
11573 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11574 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011575 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011576 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011577static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011578xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11579 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011580{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011581
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011582 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011583 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011584
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011585 /*
11586 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11587 * define the explicit members as the type definitions ·resolved·
11588 * to by the items in the ·actual value· of the memberTypes [attribute],
11589 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011590 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011591 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011592 /*
11593 * Resolve references.
11594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011595 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 lastLink = NULL;
11597 while (link != NULL) {
11598 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011599
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011600 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11601 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11602
11603 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11604 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11605 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011606 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011607 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11608 /*
11609 * Remove the member type link.
11610 */
11611 if (lastLink == NULL)
11612 type->memberTypes = link->next;
11613 else
11614 lastLink->next = link->next;
11615 newLink = link;
11616 link = link->next;
11617 xmlFree(newLink);
11618 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011619 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011620 lastLink = link;
11621 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011622 }
11623 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011624 /*
11625 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011626 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011627 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011628 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011629 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11630 if (link == NULL) {
11631 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11632 return (-1);
11633 }
11634 link->type = memberType;
11635 link->next = NULL;
11636 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011637 type->memberTypes = link;
11638 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011639 lastLink->next = link;
11640 lastLink = link;
11641 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011642 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011643 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011644}
11645
Daniel Veillard4255d502002-04-16 15:50:10 +000011646/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011647 * xmlSchemaIsDerivedFromBuiltInType:
11648 * @ctxt: the schema parser context
11649 * @type: the type definition
11650 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011651 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011652 *
11653 * Returns 1 if the type has the given value type, or
11654 * is derived from such a type.
11655 */
William M. Brack803812b2004-06-03 02:11:24 +000011656static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011657xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011658{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011659 if (type == NULL)
11660 return (0);
11661 if (IS_COMPLEX_TYPE(type))
11662 return (0);
11663 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11664 if (type->builtInType == valType)
11665 return(1);
11666 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11667 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11668 return (0);
11669 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11670 } else
11671 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011672
11673 return (0);
11674}
11675
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011676#if 0
11677/**
11678 * xmlSchemaIsDerivedFromBuiltInType:
11679 * @ctxt: the schema parser context
11680 * @type: the type definition
11681 * @valType: the value type
11682 *
11683 *
11684 * Returns 1 if the type has the given value type, or
11685 * is derived from such a type.
11686 */
11687static int
11688xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11689{
11690 if (type == NULL)
11691 return (0);
11692 if (IS_COMPLEX_TYPE(type))
11693 return (0);
11694 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11695 if (type->builtInType == valType)
11696 return(1);
11697 return (0);
11698 } else
11699 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11700
11701 return (0);
11702}
11703#endif
11704
11705static xmlSchemaTypePtr
11706xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11707{
11708 if (type == NULL)
11709 return (NULL);
11710 if (IS_COMPLEX_TYPE(type))
11711 return (NULL);
11712 if (type->type == XML_SCHEMA_TYPE_BASIC)
11713 return(type);
11714 else
11715 return(xmlSchemaQueryBuiltInType(type->subtypes));
11716
11717 return (NULL);
11718}
11719
Daniel Veillard3646d642004-06-02 19:19:14 +000011720/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011721 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011722 * @type: the simpleType definition
11723 *
11724 * Returns the primitive type of the given type or
11725 * NULL in case of error.
11726 */
11727static xmlSchemaTypePtr
11728xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11729{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011730
Daniel Veillard01fa6152004-06-29 17:04:39 +000011731 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011732 /*
11733 * Note that anySimpleType is actually not a primitive type
11734 * but we need that here.
11735 */
11736 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11737 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011738 return (type);
11739 type = type->baseType;
11740 }
11741
11742 return (NULL);
11743}
11744
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011745#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011746/**
11747 * xmlSchemaGetBuiltInTypeAncestor:
11748 * @type: the simpleType definition
11749 *
11750 * Returns the primitive type of the given type or
11751 * NULL in case of error.
11752 */
11753static xmlSchemaTypePtr
11754xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11755{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011756 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011757 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011758 while (type != NULL) {
11759 if (type->type == XML_SCHEMA_TYPE_BASIC)
11760 return (type);
11761 type = type->baseType;
11762 }
11763
11764 return (NULL);
11765}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011766#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011767
Daniel Veillard01fa6152004-06-29 17:04:39 +000011768/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011769 * xmlSchemaBuildAttributeUsesOwned:
11770 * @ctxt: the schema parser context
11771 * @type: the complex type definition
11772 * @cur: the attribute declaration list
11773 * @lastUse: the top of the attribute use list
11774 *
11775 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011776 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011777 * xmlSchemaBuildAttributeValidation only.
11778 */
11779static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011780xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011781 xmlSchemaAttributePtr cur,
11782 xmlSchemaAttributeLinkPtr *uses,
11783 xmlSchemaAttributeLinkPtr *lastUse)
11784{
11785 xmlSchemaAttributeLinkPtr tmp;
11786 while (cur != NULL) {
11787 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011788 /*
11789 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11790 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011791 * <attributeGroup> [children], if any."
11792 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011793 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11794 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011795 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011796 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011797 }
11798 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011800 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011801 */
11802 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011803 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11804 if (tmp == NULL) {
11805 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11806 return (-1);
11807 }
11808 tmp->attr = cur;
11809 tmp->next = NULL;
11810 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011811 *uses = tmp;
11812 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011813 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011814 *lastUse = tmp;
11815 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011816 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011817 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011818 return (0);
11819}
11820
Daniel Veillard50355f02004-06-08 17:52:16 +000011821/**
11822 * xmlSchemaCloneWildcardNsConstraints:
11823 * @ctxt: the schema parser context
11824 * @dest: the destination wildcard
11825 * @source: the source wildcard
11826 *
11827 * Clones the namespace constraints of source
11828 * and assignes them to dest.
11829 * Returns -1 on internal error, 0 otherwise.
11830 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011831static int
11832xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11833 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011834 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011835{
11836 xmlSchemaWildcardNsPtr cur, tmp, last;
11837
11838 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011839 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011840 (*dest)->any = source->any;
11841 cur = source->nsSet;
11842 last = NULL;
11843 while (cur != NULL) {
11844 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11845 if (tmp == NULL)
11846 return(-1);
11847 tmp->value = cur->value;
11848 if (last == NULL)
11849 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011850 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011851 last->next = tmp;
11852 last = tmp;
11853 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011854 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011855 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011856 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011857 if (source->negNsSet != NULL) {
11858 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11859 if ((*dest)->negNsSet == NULL)
11860 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011861 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011862 } else
11863 (*dest)->negNsSet = NULL;
11864 return(0);
11865}
11866
Daniel Veillard50355f02004-06-08 17:52:16 +000011867/**
11868 * xmlSchemaUnionWildcards:
11869 * @ctxt: the schema parser context
11870 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011871 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011872 *
11873 * Unions the namespace constraints of the given wildcards.
11874 * @completeWild will hold the resulting union.
11875 * Returns a positive error code on failure, -1 in case of an
11876 * internal error, 0 otherwise.
11877 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011878static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011879xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011880 xmlSchemaWildcardPtr completeWild,
11881 xmlSchemaWildcardPtr curWild)
11882{
11883 xmlSchemaWildcardNsPtr cur, curB, tmp;
11884
11885 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011886 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011887 * value.
11888 */
11889 if ((completeWild->any == curWild->any) &&
11890 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11891 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892
Daniel Veillard3646d642004-06-02 19:19:14 +000011893 if ((completeWild->negNsSet == NULL) ||
11894 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011895
Daniel Veillard3646d642004-06-02 19:19:14 +000011896 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011897 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011898
11899 /*
11900 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011901 */
11902 cur = completeWild->nsSet;
11903 while (cur != NULL) {
11904 found = 0;
11905 curB = curWild->nsSet;
11906 while (curB != NULL) {
11907 if (cur->value == curB->value) {
11908 found = 1;
11909 break;
11910 }
11911 curB = curB->next;
11912 }
11913 if (!found)
11914 break;
11915 cur = cur->next;
11916 }
11917 if (found)
11918 return(0);
11919 } else
11920 return(0);
11921 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011922 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011923 /*
11924 * 2 If either O1 or O2 is any, then any must be the value
11925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011926 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011927 if (completeWild->any == 0) {
11928 completeWild->any = 1;
11929 if (completeWild->nsSet != NULL) {
11930 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11931 completeWild->nsSet = NULL;
11932 }
11933 if (completeWild->negNsSet != NULL) {
11934 xmlFree(completeWild->negNsSet);
11935 completeWild->negNsSet = NULL;
11936 }
11937 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011938 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011939 }
11940 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011941 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011942 * then the union of those sets must be the value.
11943 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011945 int found;
11946 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011947
Daniel Veillard3646d642004-06-02 19:19:14 +000011948 cur = curWild->nsSet;
11949 start = completeWild->nsSet;
11950 while (cur != NULL) {
11951 found = 0;
11952 curB = start;
11953 while (curB != NULL) {
11954 if (cur->value == curB->value) {
11955 found = 1;
11956 break;
11957 }
11958 curB = curB->next;
11959 }
11960 if (!found) {
11961 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011962 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011963 return (-1);
11964 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011965 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011966 completeWild->nsSet = tmp;
11967 }
11968 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969 }
11970
Daniel Veillard3646d642004-06-02 19:19:14 +000011971 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011972 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011973 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011974 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011975 * or ·absent·), then a pair of not and ·absent· must be the value.
11976 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011978 (curWild->negNsSet != NULL) &&
11979 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11980 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011981
11982 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011984 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011985 * 5.
11986 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011987 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011988 (completeWild->negNsSet->value != NULL) &&
11989 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011991 (curWild->negNsSet->value != NULL) &&
11992 (completeWild->nsSet != NULL))) {
11993
11994 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011995
Daniel Veillard3646d642004-06-02 19:19:14 +000011996 if (completeWild->nsSet != NULL) {
11997 cur = completeWild->nsSet;
11998 curB = curWild->negNsSet;
11999 } else {
12000 cur = curWild->nsSet;
12001 curB = completeWild->negNsSet;
12002 }
12003 nsFound = 0;
12004 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012005 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012006 absentFound = 1;
12007 else if (cur->value == curB->value)
12008 nsFound = 1;
12009 if (nsFound && absentFound)
12010 break;
12011 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012012 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012013
12014 if (nsFound && absentFound) {
12015 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012016 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012017 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012018 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012019 completeWild->any = 1;
12020 if (completeWild->nsSet != NULL) {
12021 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12022 completeWild->nsSet = NULL;
12023 }
12024 if (completeWild->negNsSet != NULL) {
12025 xmlFree(completeWild->negNsSet);
12026 completeWild->negNsSet = NULL;
12027 }
12028 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012029 /*
12030 * 5.2 If the set S includes the negated namespace name
12031 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012032 * be the value.
12033 */
12034 if (completeWild->nsSet != NULL) {
12035 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12036 completeWild->nsSet = NULL;
12037 }
12038 if (completeWild->negNsSet == NULL) {
12039 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12040 if (completeWild->negNsSet == NULL)
12041 return (-1);
12042 }
12043 completeWild->negNsSet->value = NULL;
12044 } else if ((!nsFound) && absentFound) {
12045 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012046 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012047 * namespace name, then the union is not expressible.
12048 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012049 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012050 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012051 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012052 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012053 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012054 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012055 /*
12056 * 5.4 If the set S does not include either the negated namespace
12057 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012058 * and a namespace name must be the value.
12059 */
12060 if (completeWild->negNsSet == NULL) {
12061 if (completeWild->nsSet != NULL) {
12062 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12063 completeWild->nsSet = NULL;
12064 }
12065 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12066 if (completeWild->negNsSet == NULL)
12067 return (-1);
12068 completeWild->negNsSet->value = curWild->negNsSet->value;
12069 }
12070 }
12071 return (0);
12072 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012073 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012074 * 6.
12075 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012076 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012077 (completeWild->negNsSet->value == NULL) &&
12078 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012079 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012080 (curWild->negNsSet->value == NULL) &&
12081 (completeWild->nsSet != NULL))) {
12082
12083 if (completeWild->nsSet != NULL) {
12084 cur = completeWild->nsSet;
12085 } else {
12086 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012087 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012088 while (cur != NULL) {
12089 if (cur->value == NULL) {
12090 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012091 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012092 * value.
12093 */
12094 completeWild->any = 1;
12095 if (completeWild->nsSet != NULL) {
12096 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12097 completeWild->nsSet = NULL;
12098 }
12099 if (completeWild->negNsSet != NULL) {
12100 xmlFree(completeWild->negNsSet);
12101 completeWild->negNsSet = NULL;
12102 }
12103 return (0);
12104 }
12105 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012106 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012107 if (completeWild->negNsSet == NULL) {
12108 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012109 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012110 * and ·absent· must be the value.
12111 */
12112 if (completeWild->nsSet != NULL) {
12113 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12114 completeWild->nsSet = NULL;
12115 }
12116 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12117 if (completeWild->negNsSet == NULL)
12118 return (-1);
12119 completeWild->negNsSet->value = NULL;
12120 }
12121 return (0);
12122 }
12123 return (0);
12124
12125}
12126
Daniel Veillard50355f02004-06-08 17:52:16 +000012127/**
12128 * xmlSchemaIntersectWildcards:
12129 * @ctxt: the schema parser context
12130 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012131 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012132 *
12133 * Intersects the namespace constraints of the given wildcards.
12134 * @completeWild will hold the resulting intersection.
12135 * Returns a positive error code on failure, -1 in case of an
12136 * internal error, 0 otherwise.
12137 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012138static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012139xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012140 xmlSchemaWildcardPtr completeWild,
12141 xmlSchemaWildcardPtr curWild)
12142{
William M. Brack803812b2004-06-03 02:11:24 +000012143 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012144
12145 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012147 * value.
12148 */
12149 if ((completeWild->any == curWild->any) &&
12150 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12151 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012152
Daniel Veillard3646d642004-06-02 19:19:14 +000012153 if ((completeWild->negNsSet == NULL) ||
12154 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012155
Daniel Veillard3646d642004-06-02 19:19:14 +000012156 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012157 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012158
12159 /*
12160 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012161 */
12162 cur = completeWild->nsSet;
12163 while (cur != NULL) {
12164 found = 0;
12165 curB = curWild->nsSet;
12166 while (curB != NULL) {
12167 if (cur->value == curB->value) {
12168 found = 1;
12169 break;
12170 }
12171 curB = curB->next;
12172 }
12173 if (!found)
12174 break;
12175 cur = cur->next;
12176 }
12177 if (found)
12178 return(0);
12179 } else
12180 return(0);
12181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012183 /*
12184 * 2 If either O1 or O2 is any, then the other must be the value.
12185 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012186 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012187 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012188 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012189 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012190 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012191 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012192 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12193 * name or ·absent·) and the other is a set of (namespace names or
12194 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012195 * the set, minus ·absent· if it was in the set, must be the value.
12196 */
12197 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12198 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12199 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012200
Daniel Veillard3646d642004-06-02 19:19:14 +000012201 if (completeWild->nsSet == NULL) {
12202 neg = completeWild->negNsSet->value;
12203 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12204 return(-1);
12205 } else
12206 neg = curWild->negNsSet->value;
12207 /*
12208 * Remove absent and negated.
12209 */
12210 prev = NULL;
12211 cur = completeWild->nsSet;
12212 while (cur != NULL) {
12213 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012214 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012215 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012216 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012217 prev->next = cur->next;
12218 xmlFree(cur);
12219 break;
12220 }
12221 prev = cur;
12222 cur = cur->next;
12223 }
12224 if (neg != NULL) {
12225 prev = NULL;
12226 cur = completeWild->nsSet;
12227 while (cur != NULL) {
12228 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012229 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012230 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012231 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012232 prev->next = cur->next;
12233 xmlFree(cur);
12234 break;
12235 }
12236 prev = cur;
12237 cur = cur->next;
12238 }
12239 }
12240
12241 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012242 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012243 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012244 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012245 * then the intersection of those sets must be the value.
12246 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012247 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012248 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012249
Daniel Veillard3646d642004-06-02 19:19:14 +000012250 cur = completeWild->nsSet;
12251 prev = NULL;
12252 while (cur != NULL) {
12253 found = 0;
12254 curB = curWild->nsSet;
12255 while (curB != NULL) {
12256 if (cur->value == curB->value) {
12257 found = 1;
12258 break;
12259 }
12260 curB = curB->next;
12261 }
12262 if (!found) {
12263 if (prev == NULL)
12264 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012265 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012266 prev->next = cur->next;
12267 tmp = cur->next;
12268 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012269 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012270 continue;
12271 }
12272 prev = cur;
12273 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012274 }
12275
Daniel Veillard3646d642004-06-02 19:19:14 +000012276 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012277 }
12278 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012279 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012280 */
12281 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012282 (curWild->negNsSet != NULL) &&
12283 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012284 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012285 (curWild->negNsSet->value != NULL)) {
12286
12287 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012288 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012289 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012290 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012291 }
12292 /*
12293 * 6 If the one is a negation of a namespace name and the other
12294 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012295 * of a namespace name must be the value.
12296 */
12297 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12298 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012299 (completeWild->negNsSet->value == NULL)) {
12300 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012301 }
12302 return(0);
12303}
12304
Daniel Veillard50355f02004-06-08 17:52:16 +000012305/**
12306 * xmlSchemaIsWildcardNsConstraintSubset:
12307 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012308 * @sub: the first wildcard
12309 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012310 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012311 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12312 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012313 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012314 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012315 */
12316static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012317xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12318 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012319{
Daniel Veillard50355f02004-06-08 17:52:16 +000012320 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012321 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012322 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012323 if (super->any)
12324 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012325 /*
12326 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12327 * 2.2 super must be a pair of not and the same value.
12328 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012329 if ((sub->negNsSet != NULL) &&
12330 (super->negNsSet != NULL) &&
12331 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012332 return (0);
12333 /*
12334 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012335 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012336 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012337 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012338 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012339 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012340 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012341 xmlSchemaWildcardNsPtr cur, curB;
12342 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012343
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012344 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012345 while (cur != NULL) {
12346 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012347 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012348 while (curB != NULL) {
12349 if (cur->value == curB->value) {
12350 found = 1;
12351 break;
12352 }
12353 curB = curB->next;
12354 }
12355 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012356 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012357 cur = cur->next;
12358 }
12359 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012360 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012361 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012362 xmlSchemaWildcardNsPtr cur;
12363 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012364 * 3.2.2 super must be a pair of not and a namespace name or
12365 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012366 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012367 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012368 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012369 if (cur->value == super->negNsSet->value)
12370 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012371 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012372 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012373 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012374 }
12375 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012376 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012377}
12378
12379/**
12380 * xmlSchemaBuildCompleteAttributeWildcard:
12381 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012382 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012383 * @completeWild: the resulting complete wildcard
12384 *
12385 * Returns -1 in case of an internal error, 0 otherwise.
12386 */
12387static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012388xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012389 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012390 xmlSchemaWildcardPtr *completeWild)
12391{
Daniel Veillard3646d642004-06-02 19:19:14 +000012392 while (attrs != NULL) {
12393 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12394 xmlSchemaAttributeGroupPtr group;
12395
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012396 group = (xmlSchemaAttributeGroupPtr) attrs;
12397 /*
12398 * Handle attribute group references.
12399 */
12400 if (group->ref != NULL) {
12401 if (group->refItem == NULL) {
12402 /*
12403 * TODO: Should we raise a warning here?
12404 */
12405 /*
12406 * The referenced attribute group definition could not
12407 * be resolved beforehand, so skip.
12408 */
12409 attrs = attrs->next;
12410 continue;
12411 } else
12412 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012413 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012414 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012415 * For every attribute group definition, an intersected wildcard
12416 * will be created (assumed that a wildcard exists on the
12417 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012418 * at all).
12419 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12420 * that the intersection will be performed only once.
12421 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012422 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12423 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012424 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012425 group->attributes, &group->attributeWildcard) == -1)
12426 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012427 }
12428 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012429 }
12430 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012431 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012432 /*
12433 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012434 *
12435 * Although the complete wildcard might not correspond to any
12436 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012437 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012438 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12439 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12440 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012441 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012442 completeWild, group->attributeWildcard) == -1)
12443 return (-1);
12444 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012445 (*completeWild)->node = group->attributeWildcard->node;
12446 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012447 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012448 }
12449 }
12450 attrs = attrs->next;
12451 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012452
12453 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012454}
12455
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012456static int
12457xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12458 int *fixed,
12459 const xmlChar **value,
12460 xmlSchemaValPtr *val)
12461{
12462 *fixed = 0;
12463 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012464 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012465 *val = NULL;
12466
12467 if (item->defValue == NULL)
12468 item = item->refDecl;
12469
12470 if (item == NULL)
12471 return (0);
12472
12473 if (item->defValue != NULL) {
12474 *value = item->defValue;
12475 if (val != 0)
12476 *val = item->defVal;
12477 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12478 *fixed = 1;
12479 return (1);
12480 }
12481 return (0);
12482}
Daniel Veillard3646d642004-06-02 19:19:14 +000012483/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012484 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012485 * @wild: the wildcard
12486 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012487 *
12488 * Validation Rule: Wildcard allows Namespace Name
12489 * (cvc-wildcard-namespace)
12490 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012491 *
12492 * Returns 1 if the given namespace matches the wildcard,
12493 * 0 otherwise.
12494 */
12495static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012496xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12497 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012498{
12499 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012500 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012501
12502 if (wild->any)
12503 return(1);
12504 else if (wild->nsSet != NULL) {
12505 xmlSchemaWildcardNsPtr cur;
12506
12507 cur = wild->nsSet;
12508 while (cur != NULL) {
12509 if (xmlStrEqual(cur->value, ns))
12510 return(1);
12511 cur = cur->next;
12512 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012514 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012515 return(1);
12516
Daniel Veillard3646d642004-06-02 19:19:14 +000012517 return(0);
12518}
12519
12520/**
12521 * xmlSchemaBuildAttributeValidation:
12522 * @ctxt: the schema parser context
12523 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012524 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012525 *
12526 * Builds the wildcard and the attribute uses on the given complex type.
12527 * Returns -1 if an internal error occurs, 0 otherwise.
12528 */
12529static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12531 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012532{
12533 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012534 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12535 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012536 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012537 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012538 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012539 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012540
Daniel Veillard01fa6152004-06-29 17:04:39 +000012541 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012542 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012543 * Complex Type Definition with complex content Schema Component.
12544 *
12545 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012546 * TODO: Add checks for absent referenced attribute declarations and
12547 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012548 */
12549 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012550 PERROR_INT("xmlSchemaBuildAttributeValidation",
12551 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012552 return (-1);
12553 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012554 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012555 PERROR_INT("xmlSchemaBuildAttributeValidation",
12556 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 return (-1);
12558 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012559 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012560 /*
12561 * Inherit the attribute uses of the base type.
12562 */
12563 /*
12564 * NOTE: It is allowed to "extend" the anyType complex type.
12565 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012566 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012567 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012568 for (cur = baseType->attributeUses; cur != NULL;
12569 cur = cur->next) {
12570 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012571 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12572 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012573 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012574 "building attribute uses of complexType", NULL);
12575 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012576 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012577 tmp->attr = cur->attr;
12578 tmp->next = NULL;
12579 if (type->attributeUses == NULL) {
12580 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012581 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012582 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012584 }
12585 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012586 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012587 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012588 /*
12589 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012590 */
12591 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12592 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012593 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012594 * NOTE: During the parse time, the wildcard is created on the complexType
12595 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012596 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012597 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012598 PERROR_INT("xmlSchemaBuildAttributeValidation",
12599 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012600 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012601 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012602
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012603 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12604 ((IS_ANYTYPE(baseType)) ||
12605 ((baseType != NULL) &&
12606 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12607 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012608 if (type->attributeWildcard != NULL) {
12609 /*
12610 * Union the complete wildcard with the base wildcard.
12611 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012612 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012613 baseType->attributeWildcard) == -1)
12614 return (-1);
12615 } else {
12616 /*
12617 * Just inherit the wildcard.
12618 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012619 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012620 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012621 * wildcard is shared.
12622 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012623 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012624 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012625 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012626
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012627 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12628 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012629 /*
12630 * Derivation Valid (Restriction, Complex)
12631 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012632 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012633 if (baseType->attributeWildcard == NULL) {
12634 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012635 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012636 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012637 "The type has an attribute wildcard, "
12638 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012639 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012640 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012641 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012642 } else if (xmlSchemaCheckCOSNSSubset(
12643 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012644 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012645 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012646 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012647 NULL, type, NULL,
12648 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012649 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012650 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12651 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012652 return (1);
12653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012654 /* 4.3 Unless the {base type definition} is the ·ur-type
12655 * definition·, the complex type definition's {attribute
12656 * wildcard}'s {process contents} must be identical to or
12657 * stronger than the {base type definition}'s {attribute
12658 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012659 * than lax is stronger than skip.
12660 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012661 if ((! IS_ANYTYPE(baseType)) &&
12662 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012663 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012664 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012665 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012666 NULL, type, NULL,
12667 "The 'process contents' of the attribute wildcard is "
12668 "weaker than the one in the base type %s",
12669 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012670 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012671 return (1);
12672 }
12673 }
12674 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12675 /*
12676 * Derivation Valid (Extension)
12677 * At this point the type and the base have both, either
12678 * no wildcard or a wildcard.
12679 */
12680 if ((baseType->attributeWildcard != NULL) &&
12681 (baseType->attributeWildcard != type->attributeWildcard)) {
12682 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012683 if (xmlSchemaCheckCOSNSSubset(
12684 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012685 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012686 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012687 NULL, type, NULL,
12688 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012689 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012690 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12691 FREE_AND_NULL(str)
12692 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012693 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012694 }
12695 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012696
Daniel Veillard3646d642004-06-02 19:19:14 +000012697 /*
12698 * Gather attribute uses defined by this type.
12699 */
12700 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012701 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012702 &uses, &lastUse) == -1) {
12703 return (-1);
12704 }
12705 }
12706 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012707 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012708 * not have identical {name}s and {target namespace}s."
12709 *
12710 * For "extension" this is done further down.
12711 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012712 if ((uses != NULL) && ((type->flags &
12713 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012714 cur = uses;
12715 while (cur != NULL) {
12716 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012717 while (tmp != NULL) {
12718 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012719 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012720 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012721 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12722
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012723 xmlSchemaPAttrUseErr(pctxt,
12724 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12725 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012726 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727 xmlSchemaFormatQName(&str,
12728 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12729 xmlSchemaGetAttrName(tmp->attr)));
12730 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012731 break;
12732 }
12733 tmp = tmp->next;
12734 }
12735 cur = cur->next;
12736 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 }
12738 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012739 /*
12740 * Derive by restriction.
12741 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012742 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012743 type->attributeUses = uses;
12744 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012745 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012746 const xmlChar *bEffValue;
12747 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012748
12749 cur = uses;
12750 while (cur != NULL) {
12751 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012752 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012753 base = type->attributeUses;
12754 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012755 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012756 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012757 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012758 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012759
12760 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012761
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012762 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012763 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12764 (base->attr->occurs ==
12765 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12766 /*
12767 * NOOP.
12768 */
12769 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012770 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12771 (base->attr->occurs ==
12772 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012773 /*
12774 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012775 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776 xmlSchemaPAttrUseErr(pctxt,
12777 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12778 type, cur->attr,
12779 "The 'optional' use is inconsistent with a "
12780 "matching 'required' use of the base type",
12781 NULL);
12782 } else if ((cur->attr->occurs ==
12783 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12784 (base->attr->occurs ==
12785 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12786 /*
12787 * derivation-ok-restriction 3
12788 */
12789 xmlSchemaPCustomErr(pctxt,
12790 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12791 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012792 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012793 "attribute use '%s' of the base type is "
12794 "missing",
12795 xmlSchemaFormatQName(&str,
12796 xmlSchemaGetAttrTargetNsURI(base->attr),
12797 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012798 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012799 } else if (xmlSchemaCheckCOSSTDerivedOK(
12800 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12801
12802 /*
12803 * SPEC (2.1.2) "R's {attribute declaration}'s
12804 * {type definition} must be validly derived from
12805 * B's {type definition} given the empty set as
12806 * defined in Type Derivation OK (Simple) (§3.14.6)."
12807 */
12808 xmlSchemaPAttrUseErr(pctxt,
12809 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12810 type, cur->attr,
12811 "The attribute declaration's type "
12812 "definition is not validly derived from "
12813 "the corresponding definition in the "
12814 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012815 } else {
12816 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012817 * 2.1.3 [Definition:] Let the effective value
12818 * constraint of an attribute use be its {value
12819 * constraint}, if present, otherwise its {attribute
12820 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012821 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012822 xmlSchemaGetEffectiveValueConstraint(base->attr,
12823 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012824 /*
12825 * 2.1.3 ... one of the following must be true
12826 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012827 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012828 * ·absent· or default.
12829 */
12830 if ((bEffValue != NULL) &&
12831 (effFixed == 1)) {
12832 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012833
12834 xmlSchemaGetEffectiveValueConstraint(base->attr,
12835 &effFixed, &rEffValue, 0);
12836 /*
12837 * 2.1.3.2 R's ·effective value constraint· is
12838 * fixed with the same string as B's.
12839 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012840 */
12841 if ((effFixed == 0) ||
12842 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012843 xmlSchemaPAttrUseErr(pctxt,
12844 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12845 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012846 "The effective value constraint of the "
12847 "attribute use is inconsistent with "
12848 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012849 NULL);
12850 } else {
12851 /*
12852 * Override the attribute use.
12853 */
12854 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012855 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012856 } else
12857 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012859
Daniel Veillard3646d642004-06-02 19:19:14 +000012860 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012861 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012862 base = base->next;
12863 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012865 if ((!found) && (cur->attr->occurs !=
12866 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12867 /*
12868 * derivation-ok-restriction 2.2
12869 */
12870 if ((baseType->attributeWildcard == NULL) ||
12871 (xmlSchemaCheckCVCWildcardNamespace(
12872 baseType->attributeWildcard,
12873 cur->attr->targetNamespace) != 1)) {
12874 xmlSchemaPAttrUseErr(pctxt,
12875 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12876 type, cur->attr,
12877 "Neither a matching attribute use, "
12878 "nor a matching wildcard in the base type does exist",
12879 NULL);
12880 } else {
12881 /*
12882 * Add the attribute use.
12883 *
12884 * Note that this may lead to funny derivation error reports, if
12885 * multiple equal attribute uses exist; but this is not
12886 * allowed anyway, and it will be reported beforehand.
12887 */
12888 tmp = cur;
12889 if (prev != NULL)
12890 prev->next = cur->next;
12891 else
12892 uses = cur->next;
12893 cur = cur->next;
12894 tmp->next = NULL;
12895 if (type->attributeUses == NULL) {
12896 type->attributeUses = tmp;
12897 } else
12898 lastBaseUse->next = tmp;
12899 lastBaseUse = tmp;
12900
12901 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012902 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012903 }
12904 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012905 cur = cur->next;
12906 }
12907 if (uses != NULL)
12908 xmlSchemaFreeAttributeUseList(uses);
12909 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012910 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012911 /*
12912 * The spec allows only appending, and not other kinds of extensions.
12913 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012914 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012915 */
12916 if (uses != NULL) {
12917 if (type->attributeUses == NULL) {
12918 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012919 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012920 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012921 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012922 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012923 PERROR_INT("xmlSchemaBuildAttributeValidation",
12924 "no derivation method");
12925 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012926 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012927 /*
12928 * 3.4.6 -> Complex Type Definition Properties Correct
12929 */
12930 if (type->attributeUses != NULL) {
12931 cur = type->attributeUses;
12932 prev = NULL;
12933 while (cur != NULL) {
12934 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012935 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012936 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012937 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012938 * Note that this was already done for "restriction" and types derived from
12939 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012940 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012941 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12942 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012943 while (tmp != NULL) {
12944 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012945 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012946 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012947 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012948
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012949 xmlSchemaPAttrUseErr(pctxt,
12950 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12951 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012952 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012953 break;
12954 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012955 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012956 }
12957 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012958 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012959 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012960 * not have {type definition}s which are or are derived from ID.
12961 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012962 if ((cur->attr->subtypes != NULL) &&
12963 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12964 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012965 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 xmlSchemaPAttrUseErr(pctxt,
12967 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12968 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012969 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012970 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012971 NULL);
12972 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012973 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012974 id = cur;
12975 }
12976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012977 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012978 * stage is to be able to catch dublicate attribute uses. So we had to keep
12979 * prohibited uses in the list as well.
12980 */
12981 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12982 tmp = cur;
12983 if (prev == NULL)
12984 type->attributeUses = cur->next;
12985 else
12986 prev->next = cur->next;
12987 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012988 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012989 } else {
12990 prev = cur;
12991 cur = cur->next;
12992 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012993 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012994 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012995 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012996 * TODO: This check should be removed if we are 100% sure of
12997 * the base type attribute uses already being built.
12998 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012999 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013000 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013001 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013002 PERROR_INT("xmlSchemaBuildAttributeValidation",
13003 "attribute uses not builded on base type");
13004 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013005 return (0);
13006}
13007
13008/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013009 * xmlSchemaTypeFinalContains:
13010 * @schema: the schema
13011 * @type: the type definition
13012 * @final: the final
13013 *
13014 * Evaluates if a type definition contains the given "final".
13015 * This does take "finalDefault" into account as well.
13016 *
13017 * Returns 1 if the type does containt the given "final",
13018 * 0 otherwise.
13019 */
13020static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013021xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013022{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013023 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013024 return (0);
13025 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013026 return (1);
13027 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013028 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013029}
13030
13031/**
13032 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13033 * @type: the Union Simple Type
13034 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013035 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013036 * returns NULL otherwise.
13037 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013038static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013039xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13040{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013041 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013042 if (type->memberTypes != NULL)
13043 return (type->memberTypes);
13044 else
13045 type = type->baseType;
13046 }
13047 return (NULL);
13048}
13049
13050/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013051 * xmlSchemaGetParticleTotalRangeMin:
13052 * @particle: the particle
13053 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013054 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013055 * (all and sequence) + (choice)
13056 *
13057 * Returns the minimun Effective Total Range.
13058 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013059static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013060xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013061{
13062 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013063 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013064 return (0);
13065 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013066 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013067 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013068 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013069
13070 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013071 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013072 while (part != NULL) {
13073 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13074 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013075 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013076 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013077 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013078 if (cur == 0)
13079 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013080 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013081 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013082 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013083 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013084 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013085 } else {
13086 /* <all> and <sequence> */
13087 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013088 xmlSchemaParticlePtr part =
13089 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013090
13091 if (part == NULL)
13092 return (0);
13093 do {
13094 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13095 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013096 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 else
13098 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013099 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013100 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013101 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013102 }
13103}
13104
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013105/**
13106 * xmlSchemaGetParticleTotalRangeMax:
13107 * @particle: the particle
13108 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013109 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013110 * (all and sequence) + (choice)
13111 *
13112 * Returns the maximum Effective Total Range.
13113 */
13114static int
13115xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13116{
13117 if ((particle->children == NULL) ||
13118 (particle->children->children == NULL))
13119 return (0);
13120 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13121 int max = -1, cur;
13122 xmlSchemaParticlePtr part =
13123 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013124
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013125 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13126 if (part->children == NULL)
13127 continue;
13128 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13129 (part->children->type == XML_SCHEMA_TYPE_ANY))
13130 cur = part->maxOccurs;
13131 else
13132 cur = xmlSchemaGetParticleTotalRangeMax(part);
13133 if (cur == UNBOUNDED)
13134 return (UNBOUNDED);
13135 if ((max < cur) || (max == -1))
13136 max = cur;
13137 }
13138 /* TODO: Handle overflows? */
13139 return (particle->maxOccurs * max);
13140 } else {
13141 /* <all> and <sequence> */
13142 int sum = 0, cur;
13143 xmlSchemaParticlePtr part =
13144 (xmlSchemaParticlePtr) particle->children->children;
13145
13146 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13147 if (part->children == NULL)
13148 continue;
13149 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13150 (part->children->type == XML_SCHEMA_TYPE_ANY))
13151 cur = part->maxOccurs;
13152 else
13153 cur = xmlSchemaGetParticleTotalRangeMax(part);
13154 if (cur == UNBOUNDED)
13155 return (UNBOUNDED);
13156 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13157 return (UNBOUNDED);
13158 sum += cur;
13159 }
13160 /* TODO: Handle overflows? */
13161 return (particle->maxOccurs * sum);
13162 }
13163}
13164
13165/**
13166 * xmlSchemaIsParticleEmptiable:
13167 * @particle: the particle
13168 *
13169 * Schema Component Constraint: Particle Emptiable
13170 * Checks whether the given particle is emptiable.
13171 *
13172 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013173 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013174static int
13175xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13176{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013177 /*
13178 * SPEC (1) "Its {min occurs} is 0."
13179 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013180 if ((particle == NULL) || (particle->minOccurs == 0) ||
13181 (particle->children == NULL))
13182 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013183 /*
13184 * SPEC (2) "Its {term} is a group and the minimum part of the
13185 * effective total range of that group, [...] is 0."
13186 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013187 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013188 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013189 return (1);
13190 }
13191 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013192}
13193
13194/**
13195 * xmlSchemaCheckCOSSTDerivedOK:
13196 * @type: the derived simple type definition
13197 * @baseType: the base type definition
13198 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013199 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013200 * Type Derivation OK (Simple) (cos-st-derived-OK)
13201 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013202 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013203 * derived from @baseType.
13204 *
13205 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013206 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013208xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13209 xmlSchemaTypePtr baseType,
13210 int subset)
13211{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013213 * 1 They are the same type definition.
13214 * TODO: The identy check might have to be more complex than this.
13215 */
13216 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013217 return (0);
13218 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013219 * 2.1 restriction is not in the subset, or in the {final}
13220 * of its own {base type definition};
13221 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013222 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013223 (xmlSchemaTypeFinalContains(type->baseType,
13224 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13225 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013226 }
13227 /* 2.2 */
13228 if (type->baseType == baseType) {
13229 /*
13230 * 2.2.1 D's ·base type definition· is B.
13231 */
13232 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013233 }
13234 /*
13235 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13236 * and is validly derived from B given the subset, as defined by this
13237 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013238 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013239 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013240 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013241 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013242 return (0);
13243 }
13244 /*
13245 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013246 * definition·.
13247 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013248 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013249 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013250 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013251 }
13252 /*
13253 * 2.2.4 B's {variety} is union and D is validly derived from a type
13254 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013255 * defined by this constraint.
13256 *
13257 * NOTE: This seems not to involve built-in types, since there is no
13258 * built-in Union Simple Type.
13259 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013260 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013261 xmlSchemaTypeLinkPtr cur;
13262
13263 cur = baseType->memberTypes;
13264 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013265 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013266 return (0);
13267 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013268 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013269 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013270
Daniel Veillard01fa6152004-06-29 17:04:39 +000013271 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13272}
13273
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013274/**
13275 * xmlSchemaCheckTypeDefCircularInternal:
13276 * @pctxt: the schema parser context
13277 * @ctxtType: the type definition
13278 * @ancestor: an ancestor of @ctxtType
13279 *
13280 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013281 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013282 *
13283 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13284 * circular, 0 otherwise.
13285 */
13286static int
13287xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13288 xmlSchemaTypePtr ctxtType,
13289 xmlSchemaTypePtr ancestor)
13290{
13291 int ret;
13292
13293 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13294 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013295
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013296 if (ctxtType == ancestor) {
13297 xmlSchemaPCustomErr(pctxt,
13298 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13299 NULL, ctxtType, GET_NODE(ctxtType),
13300 "The definition is circular", NULL);
13301 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13302 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013303 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13304 /*
13305 * Avoid inifinite recursion on circular types not yet checked.
13306 */
13307 return (0);
13308 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013309 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13310 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13311 ancestor->baseType);
13312 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13313 return (ret);
13314}
13315
13316/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013317 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013318 * @item: the complex/simple type definition
13319 * @ctxt: the parser context
13320 * @name: the name
13321 *
13322 * Checks for circular type definitions.
13323 */
13324static void
13325xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013326 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013327 const xmlChar * name ATTRIBUTE_UNUSED)
13328{
13329 if ((item == NULL) ||
13330 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13331 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13332 return;
13333 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13334
13335}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013336
13337/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013338 * xmlSchemaResolveTypeDefs:
13339 * @item: the complex/simple type definition
13340 * @ctxt: the parser context
13341 * @name: the name
13342 *
13343 * Checks for circular type definitions.
13344 */
13345static void
13346xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013347 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013348 const xmlChar * name ATTRIBUTE_UNUSED)
13349{
13350 if (typeDef == NULL)
13351 return;
13352
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013353 /*
13354 * Resolve the base type.
13355 */
13356 if (typeDef->baseType == NULL) {
13357 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13358 typeDef->base, typeDef->baseNs);
13359 if (typeDef->baseType == NULL) {
13360 xmlSchemaPResCompAttrErr(ctxt,
13361 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013362 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013363 "base", typeDef->base, typeDef->baseNs,
13364 XML_SCHEMA_TYPE_SIMPLE, NULL);
13365 return;
13366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013367 }
13368 if (IS_SIMPLE_TYPE(typeDef)) {
13369 if (VARIETY_UNION(typeDef)) {
13370 /*
13371 * Resolve the memberTypes.
13372 */
13373 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13374 return;
13375 } else if (VARIETY_LIST(typeDef)) {
13376 /*
13377 * Resolve the itemType.
13378 */
13379 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13380 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13381 typeDef->ref, typeDef->refNs);
13382 if ((typeDef->subtypes == NULL) ||
13383 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13384 typeDef->subtypes = NULL;
13385 xmlSchemaPResCompAttrErr(ctxt,
13386 XML_SCHEMAP_SRC_RESOLVE,
13387 typeDef, typeDef->node,
13388 "itemType", typeDef->ref, typeDef->refNs,
13389 XML_SCHEMA_TYPE_SIMPLE, NULL);
13390 }
13391 }
13392 return;
13393 }
13394 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013395}
13396
13397
13398
13399/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 * xmlSchemaCheckSTPropsCorrect:
13401 * @ctxt: the schema parser context
13402 * @type: the simple type definition
13403 *
13404 * Checks st-props-correct.
13405 *
13406 * Returns 0 if the properties are correct,
13407 * if not, a positive error code and -1 on internal
13408 * errors.
13409 */
13410static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013411xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013412 xmlSchemaTypePtr type)
13413{
13414 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13415 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013416 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417
Daniel Veillardc0826a72004-08-10 14:17:33 +000013418 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 /*
13420 * Schema Component Constraint: Simple Type Definition Properties Correct
13421 *
13422 * NOTE: This is somehow redundant, since we actually built a simple type
13423 * to have all the needed information; this acts as an self test.
13424 */
13425 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13426 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013427 /* Base type: If the datatype has been ·derived· by ·restriction·
13428 * then the Simple Type Definition component from which it is ·derived·,
13429 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013430 */
13431 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013432 /*
13433 * TODO: Think about: "modulo the impact of Missing
13434 * Sub-components (§5.3)."
13435 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013436 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013439 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013440 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013441
Daniel Veillard01fa6152004-06-29 17:04:39 +000013442 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013443 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013444 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013445 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446 NULL, type, NULL,
13447 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013448 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13451 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13453 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13454 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013455 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013456 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013457 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013458 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013459 "the simple ur-type definition as base type, not '%s'",
13460 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013461 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13463 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013464 /*
13465 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013467 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13468 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013469 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013470 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013471 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013472 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13474 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013477 /*
13478 * 3 The {final} of the {base type definition} must not contain restriction.
13479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013480 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013481 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13482 xmlSchemaPCustomErr(ctxt,
13483 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013485 "The 'final' of its base type '%s' must not contain "
13486 "'restriction'",
13487 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013489 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013491
13492 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493 * 2 All simple type definitions must be derived ultimately from the ·simple
13494 * ur-type definition (so· circular definitions are disallowed). That is, it
13495 * must be possible to reach a built-in primitive datatype or the ·simple
13496 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013497 *
13498 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013499 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013500 return (0);
13501}
13502
13503/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013504 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013505 * @ctxt: the schema parser context
13506 * @type: the simple type definition
13507 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013508 * Schema Component Constraint:
13509 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13510
13511 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013512 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013513 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013514 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 * a positive error code otherwise.
13516 */
13517static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013519 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013520{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013521 xmlChar *str = NULL;
13522
Daniel Veillard01fa6152004-06-29 17:04:39 +000013523 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13525 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013526 return (-1);
13527 }
13528
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013530 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013531 /*
13532 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 */
13535 if (! VARIETY_ATOMIC(type->baseType)) {
13536 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013538 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013539 "The base type '%s' is not an atomic simple type",
13540 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013541 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013542 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 * restriction.
13546 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013547 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013548 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013549 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013550 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013551 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013552 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013553 "The final of its base type '%s' must not contain 'restriction'",
13554 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013555 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13557 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013558
13559 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013560 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 * Primitive datatypes.
13563 */
13564 if (type->facets != NULL) {
13565 xmlSchemaFacetPtr facet;
13566 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 primitive = xmlSchemaGetPrimitiveType(type);
13569 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13571 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013572 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013573 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013574 facet = type->facets;
13575 do {
13576 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013577 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013579 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013580 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 }
13582 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013583 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013584 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013585 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 }
13587 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013588 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13589 * of the {base type definition} (call this BF),then the DF's {value}
13590 * must be a valid restriction of BF's {value} as defined in
13591 * [XML Schemas: Datatypes]."
13592 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013593 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013594 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013595 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013596 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013597 xmlSchemaTypePtr itemType = NULL;
13598
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013599 itemType = type->subtypes;
13600 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013601 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13602 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013603 return (-1);
13604 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013605 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013606 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013607 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013608 * 2.1 The {item type definition} must have a {variety} of atomic or
13609 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013610 * must be atomic).
13611 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612 if ((! VARIETY_ATOMIC(itemType)) &&
13613 (! VARIETY_UNION(itemType))) {
13614 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013615 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013616 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013617 "The item type '%s' does not have a variety of atomic or union",
13618 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013619 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013620 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013621 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013622 xmlSchemaTypeLinkPtr member;
13623
13624 member = itemType->memberTypes;
13625 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 if (! VARIETY_ATOMIC(member->type)) {
13627 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013628 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013630 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013631 "member type '%s' of this item type is not atomic",
13632 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013633 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013634 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13635 }
13636 member = member->next;
13637 }
13638 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013639
13640 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013641 xmlSchemaFacetPtr facet;
13642 /*
13643 * This is the case if we have: <simpleType><list ..
13644 */
13645 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646 * 2.3.1
13647 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013648 * contain list.
13649 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013650 if (xmlSchemaTypeFinalContains(itemType,
13651 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13652 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013653 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013654 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013655 "The final of its item type '%s' must not contain 'list'",
13656 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013657 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013658 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13659 }
13660 /*
13661 * 2.3.1.2 The {facets} must only contain the whiteSpace
13662 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663 * OPTIMIZE TODO: the S4S already disallows any facet
13664 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 */
13666 if (type->facets != NULL) {
13667 facet = type->facets;
13668 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013669 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013672 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13674 }
13675 facet = facet->next;
13676 } while (facet != NULL);
13677 }
13678 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679 * MAYBE TODO: (Hmm, not really) Datatypes states:
13680 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13681 * whose ·lexical space· allows space (such as string or anyURI)or
13682 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013683 * ·lexical space· allows space.
13684 */
13685 } else {
13686 /*
13687 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013688 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 */
13690 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013691 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013692 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13693 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013694 if (! VARIETY_LIST(type->baseType)) {
13695 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013696 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013698 "The base type '%s' must be a list type",
13699 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013701 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13702 }
13703 /*
13704 * 2.3.2.2 The {final} of the {base type definition} must not
13705 * contain restriction.
13706 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013707 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013708 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013709 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013710 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013712 "The 'final' of the base type '%s' must not contain 'restriction'",
13713 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13716 }
13717 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013718 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013719 * from the {base type definition}'s {item type definition} given
13720 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13721 */
13722 {
13723 xmlSchemaTypePtr baseItemType;
13724
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013725 baseItemType = type->baseType->subtypes;
13726 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13728 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013729 return (-1);
13730 }
13731 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013732 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13733 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013734 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013736 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013737 NULL, type, NULL,
13738 "The item type '%s' is not validly derived from "
13739 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013740 xmlSchemaGetComponentQName(&str, itemType),
13741 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13742 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013743
13744 FREE_AND_NULL(str)
13745 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013746 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013747 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13748 }
13749 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750
Daniel Veillard01fa6152004-06-29 17:04:39 +000013751 if (type->facets != NULL) {
13752 xmlSchemaFacetPtr facet;
13753 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 /*
13755 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013756 * and enumeration facet components are allowed among the {facets}.
13757 */
13758 facet = type->facets;
13759 do {
13760 switch (facet->type) {
13761 case XML_SCHEMA_FACET_LENGTH:
13762 case XML_SCHEMA_FACET_MINLENGTH:
13763 case XML_SCHEMA_FACET_MAXLENGTH:
13764 case XML_SCHEMA_FACET_WHITESPACE:
13765 /*
13766 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013767 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 */
13769 case XML_SCHEMA_FACET_PATTERN:
13770 case XML_SCHEMA_FACET_ENUMERATION:
13771 break;
13772 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013773 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013774 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013775 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013777 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013778 * invalid facets.
13779 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013781 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013782 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013783 facet = facet->next;
13784 } while (facet != NULL);
13785 if (ok == 0)
13786 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13787 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013788 * SPEC (2.3.2.5) (same as 1.3.2)
13789 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013791 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013793 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 * atomic or list.
13799 */
13800 xmlSchemaTypeLinkPtr member;
13801
13802 member = type->memberTypes;
13803 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013804 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013805 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013806
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 if ((! VARIETY_ATOMIC(member->type)) &&
13808 (! VARIETY_LIST(member->type))) {
13809 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013811 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013812 "The member type '%s' is neither an atomic, nor a list type",
13813 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013814 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013815 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13816 }
13817 member = member->next;
13818 }
13819 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013820 * 3.3.1 If the {base type definition} is the ·simple ur-type
13821 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013822 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013823 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013824 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013825 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013826 * {final} which does not contain union.
13827 */
13828 member = type->memberTypes;
13829 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013830 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013831 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013832 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013833 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013834 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013835 "The 'final' of member type '%s' contains 'union'",
13836 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013838 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13839 }
13840 member = member->next;
13841 }
13842 /*
13843 * 3.3.1.2 The {facets} must be empty.
13844 */
13845 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013846 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013847 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013849 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013850 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13851 }
13852 } else {
13853 /*
13854 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013855 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013856 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013857 if (! VARIETY_UNION(type->baseType)) {
13858 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013859 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013860 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013861 "The base type '%s' is not a union type",
13862 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13865 }
13866 /*
13867 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13868 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013869 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013871 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013872 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013873 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013874 "The 'final' of its base type '%s' must not contain 'restriction'",
13875 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013876 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013877 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13878 }
13879 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013880 * 3.3.2.3 The {member type definitions}, in order, must be validly
13881 * derived from the corresponding type definitions in the {base
13882 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013883 * as defined in Type Derivation OK (Simple) (§3.14.6).
13884 */
13885 {
13886 xmlSchemaTypeLinkPtr baseMember;
13887
13888 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013889 * OPTIMIZE: if the type is restricting, it has no local defined
13890 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013891 * thus a check for equality can be skipped.
13892 */
13893 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013894 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013895 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013896 * types of it's base type. This check seems not necessary with
13897 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013898 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013899 */
13900 if (type->memberTypes != NULL) {
13901 member = type->memberTypes;
13902 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013903 if ((member == NULL) && (baseMember != NULL)) {
13904 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13905 "different number of member types in base");
13906 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013907 while (member != NULL) {
13908 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13910 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013911 }
13912 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013913 (xmlSchemaCheckCOSSTDerivedOK(
13914 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013915 xmlChar *strBMT = NULL, *strBT = NULL;
13916
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013917 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13919 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920 "The member type %s is not validly "
13921 "derived from its corresponding member "
13922 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013923 xmlSchemaGetComponentQName(&str, member->type),
13924 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13925 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013926 FREE_AND_NULL(str)
13927 FREE_AND_NULL(strBMT)
13928 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013929 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013931 member = member->next;
13932 baseMember = baseMember->next;
13933 }
13934 }
13935 }
13936 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013937 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013938 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013939 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013940 if (type->facets != NULL) {
13941 xmlSchemaFacetPtr facet;
13942 int ok = 1;
13943
13944 facet = type->facets;
13945 do {
13946 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13947 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013948 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013949 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013950 NULL, type, facet);
13951 ok = 0;
13952 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013953 facet = facet->next;
13954 } while (facet != NULL);
13955 if (ok == 0)
13956 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013957
Daniel Veillard01fa6152004-06-29 17:04:39 +000013958 }
13959 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013960 * SPEC (3.3.2.5) (same as 1.3.2)
13961 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013962 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013963 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 */
13965 }
13966 }
13967
13968 return (0);
13969}
13970
13971/**
13972 * xmlSchemaCheckSRCSimpleType:
13973 * @ctxt: the schema parser context
13974 * @type: the simple type definition
13975 *
13976 * Checks crc-simple-type constraints.
13977 *
13978 * Returns 0 if the constraints are satisfied,
13979 * if not a positive error code and -1 on internal
13980 * errors.
13981 */
13982static int
13983xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13984 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013985{
13986 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013987 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013988 * must satisfy the conditions set out in Constraints on Simple Type
13989 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013990 */
13991 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13992 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13993 /*
13994 * TODO: Removed this, since it got annoying to get an
13995 * extra error report, if anything failed until now.
13996 * Enable this if needed.
13997 */
13998 /*
13999 xmlSchemaPErr(ctxt, type->node,
14000 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014001 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014002 "on simple type definitions.\n",
14003 type->name, NULL);
14004 */
14005 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14006 }
14007
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014008 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014009 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014010 * src-simple-type.2 If the <restriction> alternative is chosen,
14011 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000014012 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014013 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014014 /*
14015 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014016 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014017 */
14018 } else if (VARIETY_LIST(type)) {
14019 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14020 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000014021 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014022 *
14023 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014024 */
14025 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014026 xmlSchemaTypeLinkPtr member;
14027 xmlSchemaTypePtr ancestor, anySimpleType;
14028
14029 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14030
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014031 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14032 * the <union> alternative is chosen, there must not be any entries
14033 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014034 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014035 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014036 member = type->memberTypes;
14037 while (member != NULL) {
14038 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014039 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014040 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014042 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014043 NULL, type, NULL,
14044 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014045 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014046 }
14047 if (IS_NOT_TYPEFIXED(ancestor))
14048 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014049 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014050 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014051 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014052 * type as item type, which in turn has a list ST as member
14053 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014054 * was not yet performed.
14055 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014056 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014057
Daniel Veillard01fa6152004-06-29 17:04:39 +000014058 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014059 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014060 member = member->next;
14061 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014062 }
14063
14064 return (0);
14065}
14066
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014067static int
14068xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14069{
14070 if (ctxt->vctxt == NULL) {
14071 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14072 if (ctxt->vctxt == NULL) {
14073 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014074 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014075 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014076 "failed to create a temp. validation context.\n",
14077 NULL, NULL);
14078 return (-1);
14079 }
14080 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014081 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014082 }
14083 return (0);
14084}
14085
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014086static int
14087xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14088 xmlNodePtr node,
14089 xmlSchemaTypePtr type,
14090 const xmlChar *value,
14091 xmlSchemaValPtr *retVal,
14092 int fireErrors,
14093 int normalize,
14094 int isNormalized);
14095
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014096/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014097 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014098 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014099 * @type: the simple type definition
14100 * @value: the default value
14101 * @node: an optional node (the holder of the value)
14102 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014103 * Schema Component Constraint: Element Default Valid (Immediate)
14104 * (cos-valid-default)
14105 * This will be used by the parser only. For the validator there's
14106 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014107 *
14108 * Returns 0 if the constraints are satisfied,
14109 * if not, a positive error code and -1 on internal
14110 * errors.
14111 */
14112static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014113xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14114 xmlNodePtr node,
14115 xmlSchemaTypePtr type,
14116 const xmlChar *value,
14117 xmlSchemaValPtr *val)
14118{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014119 int ret = 0;
14120
14121 /*
14122 * cos-valid-default:
14123 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014124 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014125 * definition the appropriate case among the following must be true:
14126 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014127 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014128 /*
14129 * Complex type.
14130 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014131 * SPEC (2.1) "its {content type} must be a simple type definition
14132 * or mixed."
14133 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014134 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014135 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014136 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014137 if ((! HAS_SIMPLE_CONTENT(type)) &&
14138 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14139 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014140 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014141 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014142 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014143 "For a string to be a valid default, the type definition "
14144 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014145 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014146 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14147 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014148 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014149 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014150 * 1 If the type definition is a simple type definition, then the string
14151 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014152 * Valid (§3.14.4).
14153 *
14154 * AND
14155 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014156 * 2.2.1 If the {content type} is a simple type definition, then the
14157 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014158 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014159 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014160 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014161 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14162 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014163 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014164 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14165 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014166 else
14167 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014169 if (ret < 0) {
14170 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14171 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014172 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014173
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014174 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014175}
14176
14177/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014178 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014179 * @ctxt: the schema parser context
14180 * @type: the complex type definition
14181 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014182 *.(4.6) Constraints on Complex Type Definition Schema Components
14183 * Schema Component Constraint:
14184 * Complex Type Definition Properties Correct (ct-props-correct)
14185 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014186 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014187 * Returns 0 if the constraints are satisfied, a positive
14188 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014189 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014190static int
14191xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14192 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014193{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014194 /*
14195 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14196 *
14197 * SPEC (1) "The values of the properties of a complex type definition must
14198 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014199 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014200 * Sub-components (§5.3)."
14201 */
14202 if ((type->baseType != NULL) &&
14203 (IS_SIMPLE_TYPE(type->baseType)) &&
14204 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14205 /*
14206 * SPEC (2) "If the {base type definition} is a simple type definition,
14207 * the {derivation method} must be extension."
14208 */
14209 xmlSchemaPCustomErr(pctxt,
14210 XML_SCHEMAP_SRC_CT_1,
14211 NULL, type, NULL,
14212 "If the base type is a simple type, the derivation method must be "
14213 "'extension'", NULL);
14214 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014215 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014216 /*
14217 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14218 * definition·. That is, it must be possible to reach the ·ur-type
14219 * definition by repeatedly following the {base type definition}."
14220 *
14221 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14222 *
14223 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014224 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014225 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14226 * must not have {type definition}s which are or are derived from ID."
14227 *
14228 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14229 */
14230 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014231}
14232
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014233static int
14234xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14235 xmlSchemaTypePtr typeB)
14236{
14237 /*
14238 * TODO: This should implement component-identity
14239 * in the future.
14240 */
14241 if ((typeA == NULL) || (typeB == NULL))
14242 return (0);
14243 return (typeA == typeB);
14244}
14245
14246/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014247 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014248 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014249 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014250 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014251 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014252 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014253 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014254 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14255 *
14256 * STATUS: completed
14257 *
14258 * Returns 0 if the constraints are satisfied, or 1
14259 * if not.
14260 */
14261static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014262xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014263 xmlSchemaTypePtr baseType,
14264 int set)
14265{
14266 int equal = xmlSchemaAreEqualTypes(type, baseType);
14267 /* TODO: Error codes. */
14268 /*
14269 * SPEC "For a complex type definition (call it D, for derived)
14270 * to be validly derived from a type definition (call this
14271 * B, for base) given a subset of {extension, restriction}
14272 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014273 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014274 if (! equal) {
14275 /*
14276 * SPEC (1) "If B and D are not the same type definition, then the
14277 * {derivation method} of D must not be in the subset."
14278 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014279 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014280 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014281 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014282 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014283 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014284 } else {
14285 /*
14286 * SPEC (2.1) "B and D must be the same type definition."
14287 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014288 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014289 }
14290 /*
14291 * SPEC (2.2) "B must be D's {base type definition}."
14292 */
14293 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014294 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014295 /*
14296 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14297 * definition·."
14298 */
14299 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014300 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014301
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014302 if (IS_COMPLEX_TYPE(type->baseType)) {
14303 /*
14304 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14305 * must be validly derived from B given the subset as defined by this
14306 * constraint."
14307 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014308 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014309 baseType, set));
14310 } else {
14311 /*
14312 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14313 * must be validly derived from B given the subset as defined in Type
14314 * Derivation OK (Simple) (§3.14.6).
14315 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014316 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14317 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014318}
14319
14320/**
14321 * xmlSchemaCheckCOSDerivedOK:
14322 * @type: the derived simple type definition
14323 * @baseType: the base type definition
14324 *
14325 * Calls:
14326 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014327 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014328 * Checks wheter @type can be validly derived from @baseType.
14329 *
14330 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014331 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014332static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014333xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014334 xmlSchemaTypePtr baseType,
14335 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014336{
14337 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014338 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014339 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014340 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014341}
14342
William M. Brack2f2a6632004-08-20 23:09:47 +000014343/**
14344 * xmlSchemaCheckCOSCTExtends:
14345 * @ctxt: the schema parser context
14346 * @type: the complex type definition
14347 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014348 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014349 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014350 * Derivation Valid (Extension) (cos-ct-extends)
14351 *
14352 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014353 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014354 * (1.5)
14355 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014356 *
14357 * Returns 0 if the constraints are satisfied, a positive
14358 * error code if not and -1 if an internal error occured.
14359 */
14360static int
14361xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14362 xmlSchemaTypePtr type)
14363{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014364 xmlSchemaTypePtr base = type->baseType;
14365 /*
14366 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14367 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014368 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014369 /*
14370 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014371 * then all of the following must be true:"
14372 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014373 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14374 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014375 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014376 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014377 */
14378 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14379 xmlSchemaPCustomErr(ctxt,
14380 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14381 NULL, type, NULL,
14382 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014383 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014384 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14385 }
14386 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014387 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014388 * uses}
14389 * of the complex type definition itself, that is, for every attribute
14390 * use in the {attribute uses} of the {base type definition}, there
14391 * must be an attribute use in the {attribute uses} of the complex
14392 * type definition itself whose {attribute declaration} has the same
14393 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014394 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014395 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014396 * NOTE (1.2): This will be already satisfied by the way the attribute
14397 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14398 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014399 */
14400
14401 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014402 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14403 * definition must also have one, and the base type definition's
14404 * {attribute wildcard}'s {namespace constraint} must be a subset
14405 * of the complex type definition's {attribute wildcard}'s {namespace
14406 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014407 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014408 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014409 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014410 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014411 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014412 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014413 if ((type->contentTypeDef != NULL) &&
14414 (type->contentTypeDef == base->contentTypeDef)) {
14415 /*
14416 * SPEC (1.4.1) "The {content type} of the {base type definition}
14417 * and the {content type} of the complex type definition itself
14418 * must be the same simple type definition"
14419 * PASS
14420 */
14421 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14422 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14423 /*
14424 * SPEC (1.4.2) "The {content type} of both the {base type
14425 * definition} and the complex type definition itself must
14426 * be empty."
14427 * PASS
14428 */
14429 } else {
14430 /*
14431 * SPEC (1.4.3) "All of the following must be true:"
14432 */
14433 if (type->subtypes == NULL) {
14434 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014435 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014436 * definition itself must specify a particle.
14437 */
14438 xmlSchemaPCustomErr(ctxt,
14439 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14440 NULL, type, NULL,
14441 "The content type must specify a particle", NULL);
14442 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14443 }
14444 /*
14445 * SPEC (1.4.3.2) "One of the following must be true:"
14446 */
14447 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14448 /*
14449 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14450 * definition} must be empty.
14451 * PASS
14452 */
14453 } else {
14454 /*
14455 * SPEC (1.4.3.2.2) "All of the following must be true:"
14456 */
14457 if ((type->contentType != base->contentType) ||
14458 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14459 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14460 /*
14461 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14462 * or both must be element-only."
14463 */
14464 xmlSchemaPCustomErr(ctxt,
14465 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14466 NULL, type, NULL,
14467 "The content type of both, the type and its base "
14468 "type, must either 'mixed' or 'element-only'", NULL);
14469 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014470 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014471 /*
14472 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14473 * complex type definition must be a ·valid extension·
14474 * of the {base type definition}'s particle, as defined
14475 * in Particle Valid (Extension) (§3.9.6)."
14476 *
14477 * NOTE that we won't check "Particle Valid (Extension)",
14478 * since it is ensured by the derivation process in
14479 * xmlSchemaTypeFixup(). We need to implement this when heading
14480 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014481 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014482 }
14483 /*
14484 * TODO (1.5)
14485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014486 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014487 } else {
14488 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014489 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014490 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014491 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014492 if (type->contentTypeDef != base) {
14493 /*
14494 * SPEC (2.1) "The {content type} must be the same simple type
14495 * definition."
14496 */
14497 xmlSchemaPCustomErr(ctxt,
14498 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14499 NULL, type, NULL,
14500 "The content type must be the simple base type", NULL);
14501 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14502 }
14503 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14504 /*
14505 * SPEC (2.2) "The {final} of the {base type definition} must not
14506 * contain extension"
14507 * NOTE that this is the same as (1.1).
14508 */
14509 xmlSchemaPCustomErr(ctxt,
14510 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14511 NULL, type, NULL,
14512 "The 'final' of the base type definition "
14513 "contains 'extension'", NULL);
14514 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014515 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014516 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014517 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014518}
14519
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014520/**
14521 * xmlSchemaCheckDerivationOKRestriction:
14522 * @ctxt: the schema parser context
14523 * @type: the complex type definition
14524 *
14525 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014526 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014527 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14528 *
14529 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014530 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014531 * (5.4.2), (5.2.2.1)
14532 *
14533 * Returns 0 if the constraints are satisfied, a positive
14534 * error code if not and -1 if an internal error occured.
14535 */
14536static int
14537xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14538 xmlSchemaTypePtr type)
14539{
14540 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014541
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014542 /*
14543 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14544 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014545 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014546 base = type->baseType;
14547 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14548 /*
14549 * SPEC (1) "The {base type definition} must be a complex type
14550 * definition whose {final} does not contain restriction."
14551 */
14552 xmlSchemaPCustomErr(ctxt,
14553 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14554 NULL, type, NULL,
14555 "The 'final' of the base type definition "
14556 "contains 'restriction'", NULL);
14557 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14558 }
14559 /*
14560 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14561 *
14562 * SPEC (5) "One of the following must be true:"
14563 */
14564 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14565 /*
14566 * SPEC (5.1) "The {base type definition} must be the
14567 * ·ur-type definition·."
14568 * PASS
14569 */
14570 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14571 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14572 /*
14573 * SPEC (5.2.1) "The {content type} of the complex type definition
14574 * must be a simple type definition"
14575 *
14576 * SPEC (5.2.2) "One of the following must be true:"
14577 */
14578 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14579 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14580 /*
14581 * SPEC (5.2.2.1) "The {content type} of the {base type
14582 * definition} must be a simple type definition from which
14583 * the {content type} is validly derived given the empty
14584 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14585 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014586 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014587 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14588 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014589 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014590 /*
14591 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14592 * and have a particle which is ·emptiable· as defined in
14593 * Particle Emptiable (§3.9.6)."
14594 * PASS
14595 */
14596 } else {
14597 xmlSchemaPCustomErr(ctxt,
14598 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14599 NULL, type, NULL,
14600 "The content type of the base type must be either "
14601 "a simple type or 'mixed' and an emptiable particle", NULL);
14602 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14603 }
14604 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14605 /*
14606 * SPEC (5.3.1) "The {content type} of the complex type itself must
14607 * be empty"
14608 */
14609 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14610 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014611 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014612 * definition} must also be empty."
14613 * PASS
14614 */
14615 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14616 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14617 xmlSchemaIsParticleEmptiable(
14618 (xmlSchemaParticlePtr) base->subtypes)) {
14619 /*
14620 * SPEC (5.3.2.2) "The {content type} of the {base type
14621 * definition} must be elementOnly or mixed and have a particle
14622 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14623 * PASS
14624 */
14625 } else {
14626 xmlSchemaPCustomErr(ctxt,
14627 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14628 NULL, type, NULL,
14629 "The content type of the base type must be either "
14630 "empty or 'mixed' (or 'elements-only') and an emptiable "
14631 "particle", NULL);
14632 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14633 }
14634 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014635 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014636 /*
14637 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14638 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014639 */
14640 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14641 /*
14642 * SPEC (5.4.1.2) "The {content type} of the complex type
14643 * definition itself and of the {base type definition} must be
14644 * mixed"
14645 */
14646 xmlSchemaPCustomErr(ctxt,
14647 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14648 NULL, type, NULL,
14649 "If the content type is 'mixed', then the content type of the "
14650 "base type must also be 'mixed'", NULL);
14651 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14652 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014653 /*
14654 * SPEC (5.4.2) "The particle of the complex type definition itself
14655 * must be a ·valid restriction· of the particle of the {content
14656 * type} of the {base type definition} as defined in Particle Valid
14657 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014658 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014659 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014660 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014661 } else {
14662 xmlSchemaPCustomErr(ctxt,
14663 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14664 NULL, type, NULL,
14665 "The type is not a valid restriction of its base type", NULL);
14666 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14667 }
14668 return (0);
14669}
14670
14671/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014672 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014673 * @ctxt: the schema parser context
14674 * @type: the complex type definition
14675 *
14676 * (3.4.6) Constraints on Complex Type Definition Schema Components
14677 *
14678 * Returns 0 if the constraints are satisfied, a positive
14679 * error code if not and -1 if an internal error occured.
14680 */
14681static int
14682xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14683 xmlSchemaTypePtr type)
14684{
14685 int ret;
14686 /*
14687 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014688 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014689 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14690 if (ret != 0)
14691 return (ret);
14692 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14693 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14694 else
14695 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14696 return (ret);
14697}
14698
14699/**
14700 * xmlSchemaCheckSRCCT:
14701 * @ctxt: the schema parser context
14702 * @type: the complex type definition
14703 *
14704 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014705 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014706 * Complex Type Definition Representation OK (src-ct)
14707 *
14708 * Returns 0 if the constraints are satisfied, a positive
14709 * error code if not and -1 if an internal error occured.
14710 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014711static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014712xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014713 xmlSchemaTypePtr type)
14714{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014715 xmlSchemaTypePtr base;
14716 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014717
14718 /*
14719 * TODO: Adjust the error codes here, as I used
14720 * XML_SCHEMAP_SRC_CT_1 only yet.
14721 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014722 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014723 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014724 /*
14725 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014726 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014727 * must be a complex type definition;
14728 */
14729 if (! IS_COMPLEX_TYPE(base)) {
14730 xmlChar *str = NULL;
14731 xmlSchemaPCustomErr(ctxt,
14732 XML_SCHEMAP_SRC_CT_1,
14733 NULL, type, type->node,
14734 "If using <complexContent>, the base type is expected to be "
14735 "a complex type. The base type '%s' is a simple type",
14736 xmlSchemaFormatQName(&str, base->targetNamespace,
14737 base->name));
14738 FREE_AND_NULL(str)
14739 return (XML_SCHEMAP_SRC_CT_1);
14740 }
14741 } else {
14742 /*
14743 * SPEC
14744 * 2 If the <simpleContent> alternative is chosen, all of the
14745 * following must be true:
14746 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14747 * base [attribute] must be one of the following:
14748 */
14749 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014750 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014751 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14752 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014753 /*
14754 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014755 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014756 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014757 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014758 xmlSchemaPCustomErr(ctxt,
14759 XML_SCHEMAP_SRC_CT_1,
14760 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014761 "If using <simpleContent> and <restriction>, the base "
14762 "type must be a complex type. The base type '%s' is "
14763 "a simple type",
14764 xmlSchemaFormatQName(&str, base->targetNamespace,
14765 base->name));
14766 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014767 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014768 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014769 } else {
14770 /* Base type is a complex type. */
14771 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14772 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14773 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014774 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 * simple type definition;
14776 * PASS
14777 */
14778 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014779 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014780 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014782 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014783 type->name);
14784 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014785 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014786 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14787 (type->flags &
14788 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014789
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014790 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014791 * 2.1.2 only if the <restriction> alternative is also
14792 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014793 * is mixed and a particle emptiable.
14794 */
14795 if (! xmlSchemaIsParticleEmptiable(
14796 (xmlSchemaParticlePtr) base->subtypes)) {
14797 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014798 } else
14799 /*
14800 * Attention: at this point the <simpleType> child is in
14801 * ->contentTypeDef (put there during parsing).
14802 */
14803 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014804 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014805 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014806 * 2.2 If clause 2.1.2 above is satisfied, then there
14807 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014808 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014809 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014810 /* TODO: Change error code to ..._SRC_CT_2_2. */
14811 xmlSchemaPCustomErr(ctxt,
14812 XML_SCHEMAP_SRC_CT_1,
14813 NULL, type, NULL,
14814 "A <simpleType> is expected among the children "
14815 "of <restriction>, if <simpleContent> is used and "
14816 "the base type '%s' is a complex type",
14817 xmlSchemaFormatQName(&str, base->targetNamespace,
14818 base->name));
14819 FREE_AND_NULL(str)
14820 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014821 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014822 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014823 ret = XML_SCHEMAP_SRC_CT_1;
14824 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014825 }
14826 if (ret > 0) {
14827 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014828 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014829 xmlSchemaPCustomErr(ctxt,
14830 XML_SCHEMAP_SRC_CT_1,
14831 NULL, type, NULL,
14832 "If <simpleContent> and <restriction> is used, the "
14833 "base type must be a simple type or a complex type with "
14834 "mixed content and particle emptiable. The base type "
14835 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014836 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014837 base->name));
14838 } else {
14839 xmlSchemaPCustomErr(ctxt,
14840 XML_SCHEMAP_SRC_CT_1,
14841 NULL, type, NULL,
14842 "If <simpleContent> and <extension> is used, the "
14843 "base type must be a simple type. The base type '%s' "
14844 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014845 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014846 base->name));
14847 }
14848 FREE_AND_NULL(str)
14849 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014850 }
14851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014852 * SPEC (3) "The corresponding complex type definition component must
14853 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014854 * Definition Schema Components (§3.4.6);"
14855 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014856 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014857 /*
14858 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014859 * above for {attribute wildcard} is satisfied, the intensional
14860 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014861 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014862 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014863 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014864 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014865}
William M. Brack2f2a6632004-08-20 23:09:47 +000014866
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014867#ifdef ENABLE_PARTICLE_RESTRICTION
14868/**
14869 * xmlSchemaCheckParticleRangeOK:
14870 * @ctxt: the schema parser context
14871 * @type: the complex type definition
14872 *
14873 * (3.9.6) Constraints on Particle Schema Components
14874 * Schema Component Constraint:
14875 * Occurrence Range OK (range-ok)
14876 *
14877 * STATUS: complete
14878 *
14879 * Returns 0 if the constraints are satisfied, a positive
14880 * error code if not and -1 if an internal error occured.
14881 */
14882static int
14883xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14884 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014885{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014886 if (rmin < bmin)
14887 return (1);
14888 if ((bmax != UNBOUNDED) &&
14889 (rmax > bmax))
14890 return (1);
14891 return (0);
14892}
14893
14894/**
14895 * xmlSchemaCheckRCaseNameAndTypeOK:
14896 * @ctxt: the schema parser context
14897 * @r: the restricting element declaration particle
14898 * @b: the base element declaration particle
14899 *
14900 * (3.9.6) Constraints on Particle Schema Components
14901 * Schema Component Constraint:
14902 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14903 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014904 *
14905 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014906 * MISSING (3.2.3)
14907 * CLARIFY: (3.2.2)
14908 *
14909 * Returns 0 if the constraints are satisfied, a positive
14910 * error code if not and -1 if an internal error occured.
14911 */
14912static int
14913xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14914 xmlSchemaParticlePtr r,
14915 xmlSchemaParticlePtr b)
14916{
14917 xmlSchemaElementPtr elemR, elemB;
14918
14919 /* TODO: Error codes (rcase-NameAndTypeOK). */
14920 elemR = (xmlSchemaElementPtr) r->children;
14921 elemB = (xmlSchemaElementPtr) b->children;
14922 /*
14923 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14924 * the same."
14925 */
14926 if ((elemR != elemB) &&
14927 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14928 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14929 return (1);
14930 /*
14931 * SPEC (2) "R's occurrence range is a valid restriction of B's
14932 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14933 */
14934 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14935 b->minOccurs, b->maxOccurs) != 0)
14936 return (1);
14937 /*
14938 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14939 * {scope} are global."
14940 */
14941 if (elemR == elemB)
14942 return (0);
14943 /*
14944 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14945 */
14946 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14947 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14948 return (1);
14949 /*
14950 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14951 * or is not fixed, or R's declaration's {value constraint} is fixed
14952 * with the same value."
14953 */
14954 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14955 ((elemR->value == NULL) ||
14956 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14957 /* TODO: Equality of the initial value or normalized or canonical? */
14958 (! xmlStrEqual(elemR->value, elemB->value))))
14959 return (1);
14960 /*
14961 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14962 * definitions} is a subset of B's declaration's {identity-constraint
14963 * definitions}, if any."
14964 */
14965 if (elemB->idcs != NULL) {
14966 /* TODO */
14967 }
14968 /*
14969 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14970 * superset of B's declaration's {disallowed substitutions}."
14971 */
14972 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14973 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14974 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14975 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14976 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14977 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14978 return (1);
14979 /*
14980 * SPEC (3.2.5) "R's {type definition} is validly derived given
14981 * {extension, list, union} from B's {type definition}"
14982 *
14983 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14984 * set, if the corresponding constraints handle "restriction" and
14985 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014986 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014987 */
14988 {
14989 int set = 0;
14990
14991 set |= SUBSET_EXTENSION;
14992 set |= SUBSET_LIST;
14993 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014994 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014995 elemB->subtypes, set) != 0)
14996 return (1);
14997 }
14998 return (0);
14999}
15000
15001/**
15002 * xmlSchemaCheckRCaseNSCompat:
15003 * @ctxt: the schema parser context
15004 * @r: the restricting element declaration particle
15005 * @b: the base wildcard particle
15006 *
15007 * (3.9.6) Constraints on Particle Schema Components
15008 * Schema Component Constraint:
15009 * Particle Derivation OK (Elt:Any -- NSCompat)
15010 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015011 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015012 * STATUS: complete
15013 *
15014 * Returns 0 if the constraints are satisfied, a positive
15015 * error code if not and -1 if an internal error occured.
15016 */
15017static int
15018xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15019 xmlSchemaParticlePtr r,
15020 xmlSchemaParticlePtr b)
15021{
15022 /* TODO:Error codes (rcase-NSCompat). */
15023 /*
15024 * SPEC "For an element declaration particle to be a ·valid restriction·
15025 * of a wildcard particle all of the following must be true:"
15026 *
15027 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15028 * with respect to the wildcard's {namespace constraint} as defined by
15029 * Wildcard allows Namespace Name (§3.10.4)."
15030 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015031 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015032 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15033 return (1);
15034 /*
15035 * SPEC (2) "R's occurrence range is a valid restriction of B's
15036 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15037 */
15038 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15039 b->minOccurs, b->maxOccurs) != 0)
15040 return (1);
15041
15042 return (0);
15043}
15044
15045/**
15046 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15047 * @ctxt: the schema parser context
15048 * @r: the restricting element declaration particle
15049 * @b: the base model group particle
15050 *
15051 * (3.9.6) Constraints on Particle Schema Components
15052 * Schema Component Constraint:
15053 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15054 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015055 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015056 * STATUS: TODO
15057 *
15058 * Returns 0 if the constraints are satisfied, a positive
15059 * error code if not and -1 if an internal error occured.
15060 */
15061static int
15062xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15063 xmlSchemaParticlePtr r,
15064 xmlSchemaParticlePtr b)
15065{
15066 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15067 TODO
15068 return (0);
15069}
15070
15071/**
15072 * xmlSchemaCheckRCaseNSSubset:
15073 * @ctxt: the schema parser context
15074 * @r: the restricting wildcard particle
15075 * @b: the base wildcard particle
15076 *
15077 * (3.9.6) Constraints on Particle Schema Components
15078 * Schema Component Constraint:
15079 * Particle Derivation OK (Any:Any -- NSSubset)
15080 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015081 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015082 * STATUS: complete
15083 *
15084 * Returns 0 if the constraints are satisfied, a positive
15085 * error code if not and -1 if an internal error occured.
15086 */
15087static int
15088xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15089 xmlSchemaParticlePtr r,
15090 xmlSchemaParticlePtr b,
15091 int isAnyTypeBase)
15092{
15093 /* TODO: Error codes (rcase-NSSubset). */
15094 /*
15095 * SPEC (1) "R's occurrence range is a valid restriction of B's
15096 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15097 */
15098 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15099 b->minOccurs, b->maxOccurs))
15100 return (1);
15101 /*
15102 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15103 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15104 */
15105 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15106 (xmlSchemaWildcardPtr) b->children))
15107 return (1);
15108 /*
15109 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15110 * definition·, R's {process contents} must be identical to or stronger
15111 * than B's {process contents}, where strict is stronger than lax is
15112 * stronger than skip."
15113 */
15114 if (! isAnyTypeBase) {
15115 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15116 ((xmlSchemaWildcardPtr) b->children)->processContents)
15117 return (1);
15118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015119
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015120 return (0);
15121}
15122
15123/**
15124 * xmlSchemaCheckCOSParticleRestrict:
15125 * @ctxt: the schema parser context
15126 * @type: the complex type definition
15127 *
15128 * (3.9.6) Constraints on Particle Schema Components
15129 * Schema Component Constraint:
15130 * Particle Valid (Restriction) (cos-particle-restrict)
15131 *
15132 * STATUS: TODO
15133 *
15134 * Returns 0 if the constraints are satisfied, a positive
15135 * error code if not and -1 if an internal error occured.
15136 */
15137static int
15138xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15139 xmlSchemaParticlePtr r,
15140 xmlSchemaParticlePtr b)
15141{
15142 int ret = 0;
15143
15144 /*part = GET_PARTICLE(type);
15145 basePart = GET_PARTICLE(base);
15146 */
15147
15148 TODO
15149
15150 /*
15151 * SPEC (1) "They are the same particle."
15152 */
15153 if (r == b)
15154 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015155
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015156
15157 return (0);
15158}
15159
15160/**
15161 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15162 * @ctxt: the schema parser context
15163 * @r: the model group particle
15164 * @b: the base wildcard particle
15165 *
15166 * (3.9.6) Constraints on Particle Schema Components
15167 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015168 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015169 * NSRecurseCheckCardinality)
15170 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015171 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015172 * STATUS: TODO: subst-groups
15173 *
15174 * Returns 0 if the constraints are satisfied, a positive
15175 * error code if not and -1 if an internal error occured.
15176 */
15177static int
15178xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15179 xmlSchemaParticlePtr r,
15180 xmlSchemaParticlePtr b)
15181{
15182 xmlSchemaParticlePtr part;
15183 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15184 if ((r->children == NULL) || (r->children->children == NULL))
15185 return (-1);
15186 /*
15187 * SPEC "For a group particle to be a ·valid restriction· of a
15188 * wildcard particle..."
15189 *
15190 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015191 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015192 * Particle Valid (Restriction) (§3.9.6)."
15193 */
15194 part = (xmlSchemaParticlePtr) r->children->children;
15195 do {
15196 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15197 return (1);
15198 part = (xmlSchemaParticlePtr) part->next;
15199 } while (part != NULL);
15200 /*
15201 * SPEC (2) "The effective total range of the group [...] is a
15202 * valid restriction of B's occurrence range as defined by
15203 * Occurrence Range OK (§3.9.6)."
15204 */
15205 if (xmlSchemaCheckParticleRangeOK(
15206 xmlSchemaGetParticleTotalRangeMin(r),
15207 xmlSchemaGetParticleTotalRangeMax(r),
15208 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015209 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015210 return (0);
15211}
15212
15213/**
15214 * xmlSchemaCheckRCaseRecurse:
15215 * @ctxt: the schema parser context
15216 * @r: the <all> or <sequence> model group particle
15217 * @b: the base <all> or <sequence> model group particle
15218 *
15219 * (3.9.6) Constraints on Particle Schema Components
15220 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015221 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015222 Recurse)
15223 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015224 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015225 * STATUS: ?
15226 * TODO: subst-groups
15227 *
15228 * Returns 0 if the constraints are satisfied, a positive
15229 * error code if not and -1 if an internal error occured.
15230 */
15231static int
15232xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15233 xmlSchemaParticlePtr r,
15234 xmlSchemaParticlePtr b)
15235{
15236 /* xmlSchemaParticlePtr part; */
15237 /* TODO: Error codes (rcase-Recurse). */
15238 if ((r->children == NULL) || (b->children == NULL) ||
15239 (r->children->type != b->children->type))
15240 return (-1);
15241 /*
15242 * SPEC "For an all or sequence group particle to be a ·valid
15243 * restriction· of another group particle with the same {compositor}..."
15244 *
15245 * SPEC (1) "R's occurrence range is a valid restriction of B's
15246 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15247 */
15248 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15249 b->minOccurs, b->maxOccurs))
15250 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015251
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015252
15253 return (0);
15254}
15255
15256#endif
15257
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015258#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15259 xmlSchemaPCustomErrExt(pctxt, \
15260 XML_SCHEMAP_INVALID_FACET_VALUE, \
15261 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15262 "It is an error for both '%s' and '%s' to be specified on the "\
15263 "same type definition", \
15264 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15265 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15266
15267#define FACET_RESTR_ERR(fac1, msg) \
15268 xmlSchemaPCustomErr(pctxt, \
15269 XML_SCHEMAP_INVALID_FACET_VALUE, \
15270 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015271 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015272
15273#define FACET_RESTR_FIXED_ERR(fac) \
15274 xmlSchemaPCustomErr(pctxt, \
15275 XML_SCHEMAP_INVALID_FACET_VALUE, \
15276 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15277 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015278 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015279
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015280static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015281xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15282 xmlSchemaFacetPtr facet1,
15283 xmlSchemaFacetPtr facet2,
15284 int lessGreater,
15285 int orEqual,
15286 int ofBase)
15287{
15288 xmlChar *msg = NULL;
15289
15290 msg = xmlStrdup(BAD_CAST "'");
15291 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15292 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15293 if (lessGreater == 0)
15294 msg = xmlStrcat(msg, BAD_CAST " equal to");
15295 if (lessGreater == 1)
15296 msg = xmlStrcat(msg, BAD_CAST " greater than");
15297 else
15298 msg = xmlStrcat(msg, BAD_CAST " less than");
15299
15300 if (orEqual)
15301 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15302 msg = xmlStrcat(msg, BAD_CAST " '");
15303 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15304 if (ofBase)
15305 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15306 else
15307 msg = xmlStrcat(msg, BAD_CAST "'");
15308
15309 xmlSchemaPCustomErr(pctxt,
15310 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015311 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015312 (const char *) msg, NULL);
15313
15314 if (msg != NULL)
15315 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015316}
15317
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015318static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015319xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15320 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015321{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015322 xmlSchemaTypePtr base = type->baseType;
15323 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015324 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015325 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15326 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15327 fmininc = NULL, fmaxinc = NULL,
15328 fminexc = NULL, fmaxexc = NULL,
15329 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15330 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15331 bfmininc = NULL, bfmaxinc = NULL,
15332 bfminexc = NULL, bfmaxexc = NULL;
15333 int res, err = 0, fixedErr;
15334 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015335 * 3 The {facets} of R are the union of S and the {facets}
15336 * of B, eliminating duplicates. To eliminate duplicates,
15337 * when a facet of the same kind occurs in both S and the
15338 * {facets} of B, the one in the {facets} of B is not
15339 * included, with the exception of enumeration and pattern
15340 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015341 * are allowed.
15342 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015343
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015344 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15345 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015346
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015347 last = type->facetSet;
15348 if (last != NULL)
15349 while (last->next != NULL)
15350 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015351
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015352 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15353 facet = cur->facet;
15354 switch (facet->type) {
15355 case XML_SCHEMA_FACET_LENGTH:
15356 flength = facet; break;
15357 case XML_SCHEMA_FACET_MINLENGTH:
15358 fminlen = facet; break;
15359 case XML_SCHEMA_FACET_MININCLUSIVE:
15360 fmininc = facet; break;
15361 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15362 fminexc = facet; break;
15363 case XML_SCHEMA_FACET_MAXLENGTH:
15364 fmaxlen = facet; break;
15365 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15366 fmaxinc = facet; break;
15367 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15368 fmaxexc = facet; break;
15369 case XML_SCHEMA_FACET_TOTALDIGITS:
15370 ftotdig = facet; break;
15371 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15372 ffracdig = facet; break;
15373 default:
15374 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015375 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015376 }
15377 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15378 facet = cur->facet;
15379 switch (facet->type) {
15380 case XML_SCHEMA_FACET_LENGTH:
15381 bflength = facet; break;
15382 case XML_SCHEMA_FACET_MINLENGTH:
15383 bfminlen = facet; break;
15384 case XML_SCHEMA_FACET_MININCLUSIVE:
15385 bfmininc = facet; break;
15386 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15387 bfminexc = facet; break;
15388 case XML_SCHEMA_FACET_MAXLENGTH:
15389 bfmaxlen = facet; break;
15390 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15391 bfmaxinc = facet; break;
15392 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15393 bfmaxexc = facet; break;
15394 case XML_SCHEMA_FACET_TOTALDIGITS:
15395 bftotdig = facet; break;
15396 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15397 bffracdig = facet; break;
15398 default:
15399 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015400 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015401 }
15402 err = 0;
15403 /*
15404 * length and minLength or maxLength (2.2) + (3.2)
15405 */
15406 if (flength && (fminlen || fmaxlen)) {
15407 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15408 "either of 'minLength' or 'maxLength' to be specified on "
15409 "the same type definition")
15410 }
15411 /*
15412 * Mutual exclusions in the same derivation step.
15413 */
15414 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015415 /*
15416 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015417 */
15418 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15419 }
15420 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015421 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015422 * SCC "minInclusive and minExclusive"
15423 */
15424 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015425 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015426
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015427 if (flength && bflength) {
15428 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015430 * The values have to be equal.
15431 */
15432 res = xmlSchemaCompareValues(flength->val, bflength->val);
15433 if (res == -2)
15434 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015435 if (res != 0)
15436 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15437 if ((res != 0) && (bflength->fixed)) {
15438 FACET_RESTR_FIXED_ERR(flength)
15439 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015440
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015441 }
15442 if (fminlen && bfminlen) {
15443 /*
15444 * SCC "minLength valid restriction"
15445 * minLength >= BASE minLength
15446 */
15447 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15448 if (res == -2)
15449 goto internal_error;
15450 if (res == -1)
15451 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15452 if ((res != 0) && (bfminlen->fixed)) {
15453 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015454 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015455 }
15456 if (fmaxlen && bfmaxlen) {
15457 /*
15458 * SCC "maxLength valid restriction"
15459 * maxLength <= BASE minLength
15460 */
15461 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15462 if (res == -2)
15463 goto internal_error;
15464 if (res == 1)
15465 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15466 if ((res != 0) && (bfmaxlen->fixed)) {
15467 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015468 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015469 }
15470 /*
15471 * SCC "length and minLength or maxLength"
15472 */
15473 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015475 if (flength) {
15476 if (! fminlen)
15477 flength = bflength;
15478 if (fminlen) {
15479 /* (1.1) length >= minLength */
15480 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15481 if (res == -2)
15482 goto internal_error;
15483 if (res == -1)
15484 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15485 }
15486 if (! fmaxlen)
15487 fmaxlen = bfmaxlen;
15488 if (fmaxlen) {
15489 /* (2.1) length <= maxLength */
15490 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15491 if (res == -2)
15492 goto internal_error;
15493 if (res == 1)
15494 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15495 }
15496 }
15497 if (fmaxinc) {
15498 /*
15499 * "maxInclusive"
15500 */
15501 if (fmininc) {
15502 /* SCC "maxInclusive >= minInclusive" */
15503 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15504 if (res == -2)
15505 goto internal_error;
15506 if (res == -1) {
15507 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15508 }
15509 }
15510 /*
15511 * SCC "maxInclusive valid restriction"
15512 */
15513 if (bfmaxinc) {
15514 /* maxInclusive <= BASE maxInclusive */
15515 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15516 if (res == -2)
15517 goto internal_error;
15518 if (res == 1)
15519 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15520 if ((res != 0) && (bfmaxinc->fixed)) {
15521 FACET_RESTR_FIXED_ERR(fmaxinc)
15522 }
15523 }
15524 if (bfmaxexc) {
15525 /* maxInclusive < BASE maxExclusive */
15526 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15527 if (res == -2)
15528 goto internal_error;
15529 if (res != -1) {
15530 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15531 }
15532 }
15533 if (bfmininc) {
15534 /* maxInclusive >= BASE minInclusive */
15535 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15536 if (res == -2)
15537 goto internal_error;
15538 if (res == -1) {
15539 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15540 }
15541 }
15542 if (bfminexc) {
15543 /* maxInclusive > BASE minExclusive */
15544 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15545 if (res == -2)
15546 goto internal_error;
15547 if (res != 1) {
15548 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15549 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015550 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015551 }
15552 if (fmaxexc) {
15553 /*
15554 * "maxExclusive >= minExclusive"
15555 */
15556 if (fminexc) {
15557 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15558 if (res == -2)
15559 goto internal_error;
15560 if (res == -1) {
15561 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15562 }
15563 }
15564 /*
15565 * "maxExclusive valid restriction"
15566 */
15567 if (bfmaxexc) {
15568 /* maxExclusive <= BASE maxExclusive */
15569 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15570 if (res == -2)
15571 goto internal_error;
15572 if (res == 1) {
15573 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15574 }
15575 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015576 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015577 }
15578 }
15579 if (bfmaxinc) {
15580 /* maxExclusive <= BASE maxInclusive */
15581 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15582 if (res == -2)
15583 goto internal_error;
15584 if (res == 1) {
15585 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15586 }
15587 }
15588 if (bfmininc) {
15589 /* maxExclusive > BASE minInclusive */
15590 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15591 if (res == -2)
15592 goto internal_error;
15593 if (res != 1) {
15594 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15595 }
15596 }
15597 if (bfminexc) {
15598 /* maxExclusive > BASE minExclusive */
15599 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15600 if (res == -2)
15601 goto internal_error;
15602 if (res != 1) {
15603 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15604 }
15605 }
15606 }
15607 if (fminexc) {
15608 /*
15609 * "minExclusive < maxInclusive"
15610 */
15611 if (fmaxinc) {
15612 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15613 if (res == -2)
15614 goto internal_error;
15615 if (res != -1) {
15616 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15617 }
15618 }
15619 /*
15620 * "minExclusive valid restriction"
15621 */
15622 if (bfminexc) {
15623 /* minExclusive >= BASE minExclusive */
15624 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15625 if (res == -2)
15626 goto internal_error;
15627 if (res == -1) {
15628 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15629 }
15630 if ((res != 0) && (bfminexc->fixed)) {
15631 FACET_RESTR_FIXED_ERR(fminexc)
15632 }
15633 }
15634 if (bfmaxinc) {
15635 /* minExclusive <= BASE maxInclusive */
15636 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15637 if (res == -2)
15638 goto internal_error;
15639 if (res == 1) {
15640 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15641 }
15642 }
15643 if (bfmininc) {
15644 /* minExclusive >= BASE minInclusive */
15645 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15646 if (res == -2)
15647 goto internal_error;
15648 if (res == -1) {
15649 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15650 }
15651 }
15652 if (bfmaxexc) {
15653 /* minExclusive < BASE maxExclusive */
15654 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15655 if (res == -2)
15656 goto internal_error;
15657 if (res != -1) {
15658 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15659 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015661 }
15662 if (fmininc) {
15663 /*
15664 * "minInclusive < maxExclusive"
15665 */
15666 if (fmaxexc) {
15667 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15668 if (res == -2)
15669 goto internal_error;
15670 if (res != -1) {
15671 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15672 }
15673 }
15674 /*
15675 * "minExclusive valid restriction"
15676 */
15677 if (bfmininc) {
15678 /* minInclusive >= BASE minInclusive */
15679 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15680 if (res == -2)
15681 goto internal_error;
15682 if (res == -1) {
15683 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15684 }
15685 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015686 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015687 }
15688 }
15689 if (bfmaxinc) {
15690 /* minInclusive <= BASE maxInclusive */
15691 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15692 if (res == -2)
15693 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000015694 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015695 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15696 }
15697 }
15698 if (bfminexc) {
15699 /* minInclusive > BASE minExclusive */
15700 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15701 if (res == -2)
15702 goto internal_error;
15703 if (res != 1)
15704 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15705 }
15706 if (bfmaxexc) {
15707 /* minInclusive < BASE maxExclusive */
15708 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15709 if (res == -2)
15710 goto internal_error;
15711 if (res != -1)
15712 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15713 }
15714 }
15715 if (ftotdig && bftotdig) {
15716 /*
15717 * SCC " totalDigits valid restriction"
15718 * totalDigits <= BASE totalDigits
15719 */
15720 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15721 if (res == -2)
15722 goto internal_error;
15723 if (res == 1)
15724 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15725 -1, 1, 1);
15726 if ((res != 0) && (bftotdig->fixed)) {
15727 FACET_RESTR_FIXED_ERR(ftotdig)
15728 }
15729 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015730 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015731 /*
15732 * SCC "fractionDigits valid restriction"
15733 * fractionDigits <= BASE fractionDigits
15734 */
15735 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15736 if (res == -2)
15737 goto internal_error;
15738 if (res == 1)
15739 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15740 -1, 1, 1);
15741 if ((res != 0) && (bffracdig->fixed)) {
15742 FACET_RESTR_FIXED_ERR(ffracdig)
15743 }
15744 }
15745 /*
15746 * SCC "fractionDigits less than or equal to totalDigits"
15747 */
15748 if (! ftotdig)
15749 ftotdig = bftotdig;
15750 if (! ffracdig)
15751 ffracdig = bffracdig;
15752 if (ftotdig && ffracdig) {
15753 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15754 if (res == -2)
15755 goto internal_error;
15756 if (res == 1)
15757 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15758 -1, 1, 0);
15759 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015760 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015761 * *Enumerations* won' be added here, since only the first set
15762 * of enumerations in the ancestor-or-self axis is used
15763 * for validation, plus we need to use the base type of those
15764 * enumerations for whitespace.
15765 *
15766 * *Patterns*: won't be add here, since they are ORed at
15767 * type level and ANDed at ancestor level. This will
15768 * happed during validation by walking the base axis
15769 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015770 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015771 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15772 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015773 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015774 * Special handling of enumerations and patterns.
15775 * TODO: hmm, they should not appear in the set, so remove this.
15776 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015777 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015778 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015779 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015780 /*
15781 * Search for a duplicate facet in the current type.
15782 */
15783 link = type->facetSet;
15784 err = 0;
15785 fixedErr = 0;
15786 while (link != NULL) {
15787 facet = link->facet;
15788 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015790 case XML_SCHEMA_FACET_WHITESPACE:
15791 /*
15792 * The whitespace must be stronger.
15793 */
15794 if (facet->whitespace < bfacet->whitespace) {
15795 FACET_RESTR_ERR(flength,
15796 "The 'whitespace' value has to be equal to "
15797 "or stronger than the 'whitespace' value of "
15798 "the base type")
15799 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015800 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015801 (facet->whitespace != bfacet->whitespace)) {
15802 FACET_RESTR_FIXED_ERR(facet)
15803 }
15804 break;
15805 default:
15806 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015807 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015808 /* Duplicate found. */
15809 break;
15810 }
15811 link = link->next;
15812 }
15813 /*
15814 * If no duplicate was found: add the base types's facet
15815 * to the set.
15816 */
15817 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015818 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015819 xmlMalloc(sizeof(xmlSchemaFacetLink));
15820 if (link == NULL) {
15821 xmlSchemaPErrMemory(pctxt,
15822 "deriving facets, creating a facet link", NULL);
15823 return (-1);
15824 }
15825 link->facet = cur->facet;
15826 link->next = NULL;
15827 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015828 type->facetSet = link;
15829 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015830 last->next = link;
15831 last = link;
15832 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015833
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015834 }
15835
15836 return (0);
15837internal_error:
15838 xmlSchemaPCustomErr(pctxt,
15839 XML_SCHEMAP_INVALID_FACET_VALUE,
15840 NULL, type, NULL,
15841 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15842 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015843}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015844
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015845static int
15846xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15847 xmlSchemaTypePtr type)
15848{
15849 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15850 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015851 * The actual value is then formed by replacing any union type
15852 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015853 * {member type definitions}, in order.
15854 */
15855 link = type->memberTypes;
15856 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015857
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015858 if (IS_NOT_TYPEFIXED(link->type))
15859 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15860
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015861 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015862 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015863 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015864 link->type = subLink->type;
15865 if (subLink->next != NULL) {
15866 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015867 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015868 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869 while (subLink != NULL) {
15870 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015871 xmlMalloc(sizeof(xmlSchemaTypeLink));
15872 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015873 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015874 NULL);
15875 return (-1);
15876 }
15877 newLink->type = subLink->type;
15878 prevLink->next = newLink;
15879 prevLink = newLink;
15880 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015881
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015882 subLink = subLink->next;
15883 }
15884 }
15885 }
15886 }
15887 link = link->next;
15888 }
15889 return (0);
15890}
15891
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015892static void
15893xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15894{
15895 int has = 0, needVal = 0, normVal = 0;
15896
15897 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15898 if (has) {
15899 needVal = (type->baseType->flags &
15900 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15901 normVal = (type->baseType->flags &
15902 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15903 }
15904 if (type->facets != NULL) {
15905 xmlSchemaFacetPtr fac;
15906
15907 for (fac = type->facets; fac != NULL; fac = fac->next) {
15908 switch (fac->type) {
15909 case XML_SCHEMA_FACET_WHITESPACE:
15910 break;
15911 case XML_SCHEMA_FACET_PATTERN:
15912 normVal = 1;
15913 has = 1;
15914 break;
15915 case XML_SCHEMA_FACET_ENUMERATION:
15916 needVal = 1;
15917 normVal = 1;
15918 has = 1;
15919 break;
15920 default:
15921 has = 1;
15922 break;
15923 }
15924 }
15925 }
15926 if (normVal)
15927 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15928 if (needVal)
15929 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15930 if (has)
15931 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15932
15933 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15934 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15935 /*
15936 * OPTIMIZE VAL TODO: Some facets need a computed value.
15937 */
15938 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15939 (prim->builtInType != XML_SCHEMAS_STRING)) {
15940 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15941 }
15942 }
15943}
15944
15945static int
15946xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15947{
15948
15949
15950 /*
15951 * Evaluate the whitespace-facet value.
15952 */
15953 if (VARIETY_LIST(type)) {
15954 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15955 return (0);
15956 } else if (VARIETY_UNION(type))
15957 return (0);
15958
15959 if (type->facetSet != NULL) {
15960 xmlSchemaFacetLinkPtr lin;
15961
15962 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15963 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15964 switch (lin->facet->whitespace) {
15965 case XML_SCHEMAS_FACET_PRESERVE:
15966 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15967 break;
15968 case XML_SCHEMAS_FACET_REPLACE:
15969 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15970 break;
15971 case XML_SCHEMAS_FACET_COLLAPSE:
15972 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15973 break;
15974 default:
15975 return (-1);
15976 }
15977 return (0);
15978 }
15979 }
15980 }
15981 /*
15982 * For all ·atomic· datatypes other than string (and types ·derived·
15983 * by ·restriction· from it) the value of whiteSpace is fixed to
15984 * collapse
15985 */
15986 {
15987 xmlSchemaTypePtr anc;
15988
15989 for (anc = type->baseType; anc != NULL &&
15990 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15991 anc = anc->baseType) {
15992
15993 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15994 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15995 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15996
15997 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15998 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15999 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16000
16001 } else
16002 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16003 break;
16004 }
16005 }
16006 return (0);
16007 }
16008 return (0);
16009}
16010
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016011/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016012 * xmlSchemaTypeFixup:
16013 * @typeDecl: the schema type definition
16014 * @ctxt: the schema parser context
16015 *
16016 * Fixes the content model of the type.
16017 */
16018static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016019xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016020 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016021{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016022 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016023 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016024 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16025 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016026 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016027 if (! IS_NOT_TYPEFIXED(type))
16028 return;
16029 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016030 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016031 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016032
16033 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016034 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016035 XML_SCHEMAP_INTERNAL,
16036 NULL, type, NULL,
16037 "Internal error: xmlSchemaTypeFixup, "
16038 "baseType is missing on '%s'", type->name);
16039 return;
16040 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016041
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016042 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016043 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016044
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016045 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016046 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016047 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016048 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016049 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016050 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16051 /*
16052 * Skip fixup if the base type is invalid.
16053 * TODO: Generate a warning!
16054 */
16055 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016056 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016057 /*
16058 * This basically checks if the base type can be derived.
16059 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016060 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016061 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16062 return;
16063 }
16064 /*
16065 * Fixup the content type.
16066 */
16067 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16068 /*
16069 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016070 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016071 if ((IS_COMPLEX_TYPE(baseType)) &&
16072 (baseType->contentTypeDef != NULL) &&
16073 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016074 xmlSchemaTypePtr contentBase, content;
16075 char buf[30];
16076 const xmlChar *tmpname;
16077 /*
16078 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016079 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016080 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016081 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016082 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016083 * SPEC (1.1) "the simple type definition corresponding to the
16084 * <simpleType> among the [children] of <restriction> if there
16085 * is one;"
16086 * Note that this "<simpleType> among the [children]" was put
16087 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016088 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016089 contentBase = type->contentTypeDef;
16090 type->contentTypeDef = NULL;
16091 } else {
16092 /*
16093 * (1.2) "...otherwise (<restriction> has no <simpleType>
16094 * among its [children]), the simple type definition which
16095 * is the {content type} of the ... base type."
16096 */
16097 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016098 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016099 /*
16100 * SPEC
16101 * "... a simple type definition which restricts the simple
16102 * type definition identified in clause 1.1 or clause 1.2
16103 * with a set of facet components"
16104 *
16105 * Create the anonymous simple type, which will be the content
16106 * type of the complex type.
16107 */
16108 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16109 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16110 content = xmlSchemaAddType(pctxt,
16111 pctxt->schema, tmpname, tmpname, type->node);
16112 if (content == NULL)
16113 return;
16114 /*
16115 * We will use the same node as for the <complexType>
16116 * to have it somehow anchored in the schema doc.
16117 */
16118 content->node = type->node;
16119 content->type = XML_SCHEMA_TYPE_SIMPLE;
16120 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16121 content->baseType = contentBase;
16122 /*
16123 * Move the facets, previously anchored on the complexType.
16124 */
16125 content->facets = type->facets;
16126 type->facets = NULL;
16127 content->facetSet = type->facetSet;
16128 type->facetSet = NULL;
16129
16130 type->contentTypeDef = content;
16131 if (IS_NOT_TYPEFIXED(contentBase))
16132 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16133 xmlSchemaTypeFixup(content, pctxt, NULL);
16134
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016135 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16136 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16137 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16138 /*
16139 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16140 * an emptiable particle, then a simple type definition which
16141 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016143 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016144 (type->contentTypeDef->baseType == NULL)) {
16145 /*
16146 * TODO: Check if this ever happens.
16147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016148 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016149 XML_SCHEMAP_INTERNAL,
16150 NULL, type, NULL,
16151 "Internal error: xmlSchemaTypeFixup, "
16152 "complex type '%s': the <simpleContent><restriction> "
16153 "is missing a <simpleType> child, but was not catched "
16154 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016155 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016156 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16157 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16158 /*
16159 * SPEC (3) If <extension> + base is <complexType> with
16160 * <simpleType> content, "...then the {content type} of that
16161 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016162 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016163 if (baseType->contentTypeDef == NULL) {
16164 /*
16165 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16166 * should have catched this already.
16167 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016168 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016169 XML_SCHEMAP_INTERNAL,
16170 NULL, type, NULL,
16171 "Internal error: xmlSchemaTypeFixup, "
16172 "complex type '%s': the <extension>ed base type is "
16173 "a complex type with no simple content type",
16174 type->name);
16175 }
16176 type->contentTypeDef = baseType->contentTypeDef;
16177 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16178 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16179 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016180 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016181 * "... then that simple type definition"
16182 */
16183 type->contentTypeDef = baseType;
16184 } else {
16185 /*
16186 * TODO: Check if this ever happens.
16187 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016188 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016189 XML_SCHEMAP_INTERNAL,
16190 NULL, type, NULL,
16191 "Internal error: xmlSchemaTypeFixup, "
16192 "complex type '%s' with <simpleContent>: unhandled "
16193 "derivation case", type->name);
16194 }
16195 } else {
16196 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016197 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016198 (xmlSchemaParticlePtr) type->subtypes;
16199 /*
16200 * Corresponds to <complexType><complexContent>...
16201 *
16202 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016203 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016204 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016205 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016206 * Compute the "effective content":
16207 * (2.1.1) + (2.1.2) + (2.1.3)
16208 */
16209 if ((particle == NULL) ||
16210 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16211 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16212 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16213 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16214 (particle->minOccurs == 0))) &&
16215 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016216 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 /*
16218 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16219 * a particle whose properties are as follows:..."
16220 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016221 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016222 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16223 * NOTE that we sill assign it the <complexType> node to
16224 * somehow anchor it in the doc.
16225 */
16226 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016227 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016228 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016229 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016230 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016231 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016232 type->node, 1, 1);
16233 if (particle == NULL)
16234 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016235 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016236 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016237 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016238 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016239 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016240 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16241 if (particle->children == NULL)
16242 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016243
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016244 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016245 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016246 dummySequence = 1;
16247 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16248 } else {
16249 /*
16250 * SPEC (2.1.5) "otherwise empty"
16251 */
16252 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016253 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016254 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016255 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016256 * SPEC (2.2) "otherwise the particle corresponding to the
16257 * <all>, <choice>, <group> or <sequence> among the
16258 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016259 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16261 }
16262 /*
16263 * Compute the "content type".
16264 */
16265 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016266 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016267 * SPEC (3.1) "If <restriction>..."
16268 * (3.1.1) + (3.1.2) */
16269 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16270 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16271 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16272 }
16273 } else {
16274 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016275 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016276 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016277 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16278 /*
16279 * SPEC (3.2.1)
16280 */
16281 type->contentType = baseType->contentType;
16282 type->subtypes = baseType->subtypes;
16283 /*
16284 * NOTE that the effective mixed is ignored here.
16285 */
16286 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16287 /*
16288 * SPEC (3.2.2)
16289 */
16290 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16291 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16292 } else {
16293 /*
16294 * SPEC (3.2.3)
16295 */
16296 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16297 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16298 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016299 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016300 * {particles} are..."
16301 */
16302 if (! dummySequence) {
16303 xmlSchemaTreeItemPtr effectiveContent =
16304 (xmlSchemaTreeItemPtr) type->subtypes;
16305 /*
16306 * Create the particle.
16307 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016308 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 type->node, 1, 1);
16310 if (particle == NULL)
16311 return;
16312 /*
16313 * Create the "sequence" model group.
16314 */
16315 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016316 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016317 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16318 if (particle->children == NULL)
16319 return;
16320 type->subtypes = (xmlSchemaTypePtr) particle;
16321 /*
16322 * SPEC "the particle of the {content type} of
16323 * the ... base ..."
16324 * Create a duplicate of the base type's particle
16325 * and assign its "term" to it.
16326 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016327 particle->children->children =
16328 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16329 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016331 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016332 if (particle->children->children == NULL)
16333 return;
16334 particle = (xmlSchemaParticlePtr)
16335 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016336 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016337 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16338 /*
16339 * SPEC "followed by the ·effective content·."
16340 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016341 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016342 } else {
16343 /*
16344 * This is the case when there is already an empty
16345 * <sequence> with minOccurs==maxOccurs==1.
16346 * Just add the base types's content type.
16347 * NOTE that, although we miss to add an intermediate
16348 * <sequence>, this should produce no difference to
16349 * neither the regex compilation of the content model,
16350 * nor to the complex type contraints.
16351 */
16352 particle->children->children =
16353 (xmlSchemaTreeItemPtr) baseType->subtypes;
16354 }
16355 }
16356 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016357 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 /*
16359 * Apply the complex type component constraints; this will not
16360 * check attributes, since this is done in
16361 * xmlSchemaBuildAttributeValidation().
16362 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016363 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16364 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016365 /*
16366 * Inherit & check constraints for attributes.
16367 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016368 xmlSchemaBuildAttributeValidation(pctxt, type);
16369 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016370 /*
16371 * Simple Type Definition Schema Component
16372 */
16373 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016374 if (VARIETY_LIST(type)) {
16375 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016378 if (type->subtypes == NULL) {
16379 /*
16380 * This one is really needed, so get out.
16381 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016382 PERROR_INT("xmlSchemaTypeFixup",
16383 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 return;
16385 }
16386 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016387 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16388 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016389 /*
16390 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016391 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 if (type->memberTypes == NULL) {
16393 /*
16394 * This one is really needed, so get out.
16395 */
16396 return;
16397 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016398 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016399 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016400 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016401 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016402 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016403 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016404 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016405 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016406 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16407 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016408 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016409 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016410 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016411 */
16412 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016413 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016414 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016415 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16416 /*
16417 * Inherit the itemType.
16418 */
16419 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016420 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016421 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16422 /*
16423 * NOTE that we won't assign the memberTypes of the base,
16424 * since this will make trouble when freeing them; we will
16425 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016427 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016428 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016429 /*
16430 * Check constraints.
16431 *
16432 * TODO: Split this somehow, we need to know first if we can derive
16433 * from the base type at all!
16434 */
16435 if (type->baseType != NULL) {
16436 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016437 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016438 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016439 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016440 * applied beforehand.
16441 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016442 xmlSchemaCheckSRCSimpleType(pctxt, type);
16443 xmlSchemaCheckFacetValues(type, pctxt);
16444 if ((type->facetSet != NULL) ||
16445 (type->baseType->facetSet != NULL))
16446 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16447 /*
16448 * Whitespace value.
16449 */
16450 xmlSchemaTypeFixupWhitespace(type);
16451 xmlSchemaTypeFixupOptimFacets(type);
16452 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016453 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016454
Daniel Veillard8651f532002-04-17 09:06:27 +000016455#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016456 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016457 xmlGenericError(xmlGenericErrorContext,
16458 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016459 type->node->doc->URL,
16460 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016461 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016462 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016463 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016464 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16465 switch (type->contentType) {
16466 case XML_SCHEMA_CONTENT_SIMPLE:
16467 xmlGenericError(xmlGenericErrorContext, "simple\n");
16468 break;
16469 case XML_SCHEMA_CONTENT_ELEMENTS:
16470 xmlGenericError(xmlGenericErrorContext, "elements\n");
16471 break;
16472 case XML_SCHEMA_CONTENT_UNKNOWN:
16473 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16474 break;
16475 case XML_SCHEMA_CONTENT_EMPTY:
16476 xmlGenericError(xmlGenericErrorContext, "empty\n");
16477 break;
16478 case XML_SCHEMA_CONTENT_MIXED:
16479 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016480 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016481 xmlGenericError(xmlGenericErrorContext,
16482 "mixed as emptiable particle\n");
16483 else
16484 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16485 break;
16486 /* Removed, since not used. */
16487 /*
16488 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16489 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16490 break;
16491 */
16492 case XML_SCHEMA_CONTENT_BASIC:
16493 xmlGenericError(xmlGenericErrorContext, "basic\n");
16494 break;
16495 default:
16496 xmlGenericError(xmlGenericErrorContext,
16497 "not registered !!!\n");
16498 break;
16499 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016500 }
16501#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016502}
16503
16504/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016505 * xmlSchemaCheckFacet:
16506 * @facet: the facet
16507 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016508 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016509 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016510 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016511 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016512 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016513 * Returns 0 if valid, a positive error code if not valid and
16514 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016515 */
16516int
16517xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016518 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016519 xmlSchemaParserCtxtPtr pctxt,
16520 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016521{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016523
Daniel Veillardce682bc2004-11-05 17:22:25 +000016524 if ((facet == NULL) || (typeDecl == NULL))
16525 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016527 * TODO: will the parser context be given if used from
16528 * the relaxNG module?
16529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016530 if (pctxt == NULL)
16531 ctxtGiven = 0;
16532 else
16533 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016534
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016535 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016536 case XML_SCHEMA_FACET_MININCLUSIVE:
16537 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16538 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016539 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16540 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016541 /*
16542 * Okay we need to validate the value
16543 * at that point.
16544 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016545 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016546
16547 /* 4.3.5.5 Constraints on enumeration Schema Components
16548 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016549 * It is an ·error· if any member of {value} is not in the
16550 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016551 *
16552 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016553 * The value ·must· be in the
16554 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016555 */
16556 /*
16557 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016558 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016559 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016560 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016561 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016562 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016563 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016564 */
16565 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16566 base = typeDecl->baseType;
16567 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016568 PERROR_INT("xmlSchemaCheckFacet",
16569 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016570 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016571 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016572 } else
16573 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016574
16575 if (! ctxtGiven) {
16576 /*
16577 * A context is needed if called from RelaxNG.
16578 */
16579 pctxt = xmlSchemaNewParserCtxt("*");
16580 if (pctxt == NULL)
16581 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016582 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016583 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016584 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016585 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016586 * facet->node is just the node holding the facet
16587 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016588 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016589 */
16590 ret = xmlSchemaVCheckCVCSimpleType(
16591 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16592 facet->value, &(facet->val), 1, 1, 0);
16593 if (ret != 0) {
16594 if (ret < 0) {
16595 /* No error message for RelaxNG. */
16596 if (ctxtGiven) {
16597 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16598 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16599 "Internal error: xmlSchemaCheckFacet, "
16600 "failed to validate the value '%s' of the "
16601 "facet '%s' against the base type",
16602 facet->value, xmlSchemaFacetTypeToString(facet->type));
16603 }
16604 goto internal_error;
16605 }
16606 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16607 /* No error message for RelaxNG. */
16608 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016609 xmlChar *str = NULL;
16610
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016611 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16612 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016613 "The value '%s' of the facet does not validate "
16614 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016615 facet->value,
16616 xmlSchemaFormatQName(&str,
16617 base->targetNamespace, base->name));
16618 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016619 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016620 goto exit;
16621 } else if (facet->val == NULL) {
16622 if (ctxtGiven) {
16623 PERROR_INT("xmlSchemaCheckFacet",
16624 "value was not computed");
16625 }
16626 TODO
16627 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016628 break;
16629 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016630 case XML_SCHEMA_FACET_PATTERN:
16631 facet->regexp = xmlRegexpCompile(facet->value);
16632 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016633 ret = XML_SCHEMAP_REGEXP_INVALID;
16634 /* No error message for RelaxNG. */
16635 if (ctxtGiven) {
16636 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16637 ret, facet->node, typeDecl,
16638 "The value '%s' of the facet 'pattern' is not a "
16639 "valid regular expression",
16640 facet->value, NULL);
16641 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016642 }
16643 break;
16644 case XML_SCHEMA_FACET_TOTALDIGITS:
16645 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16646 case XML_SCHEMA_FACET_LENGTH:
16647 case XML_SCHEMA_FACET_MAXLENGTH:
16648 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016649 ret = xmlSchemaValidatePredefinedType(
16650 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16651 facet->value, &(facet->val));
16652 if (ret != 0) {
16653 if (ret < 0) {
16654 /* No error message for RelaxNG. */
16655 if (ctxtGiven) {
16656 PERROR_INT("xmlSchemaCheckFacet",
16657 "validating facet value");
16658 }
16659 goto internal_error;
16660 }
16661 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16662 /* No error message for RelaxNG. */
16663 if (ctxtGiven) {
16664 /* error code */
16665 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16666 ret, facet->node, typeDecl,
16667 "The value '%s' of the facet '%s' is not a valid "
16668 "'nonNegativeInteger'",
16669 facet->value,
16670 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016671 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016672 }
16673 break;
16674 }
16675 case XML_SCHEMA_FACET_WHITESPACE:{
16676 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16677 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16678 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16679 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16680 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16681 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16682 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016683 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16684 /* No error message for RelaxNG. */
16685 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016686 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016687 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16688 ret, facet->node, typeDecl,
16689 "The value '%s' of the facet 'whitespace' is not "
16690 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016691 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016692 }
16693 }
16694 default:
16695 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016697exit:
16698 if ((! ctxtGiven) && (pctxt != NULL))
16699 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016700 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016701internal_error:
16702 if ((! ctxtGiven) && (pctxt != NULL))
16703 xmlSchemaFreeParserCtxt(pctxt);
16704 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016705}
16706
16707/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016708 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016709 * @typeDecl: the schema type definition
16710 * @ctxt: the schema parser context
16711 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016712 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016713 */
16714static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016715xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16716 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016717{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016718 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016719 /*
16720 * NOTE: It is intended to use the facets list, instead
16721 * of facetSet.
16722 */
16723 if (typeDecl->facets != NULL) {
16724 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016725
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016726 /*
16727 * Temporarily assign the "schema" to the validation context
16728 * of the parser context. This is needed for NOTATION validation.
16729 */
16730 if (ctxt->vctxt == NULL) {
16731 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16732 return;
16733 }
16734 ctxt->vctxt->schema = ctxt->schema;
16735
Daniel Veillard01fa6152004-06-29 17:04:39 +000016736 while (facet != NULL) {
16737 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16738 facet = facet->next;
16739 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016740
16741 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016742 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016743}
16744
16745/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016746 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016747 * @ctxtMGroup: the searched model group
16748 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016749 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016750 *
16751 * This one is intended to be used by
16752 * xmlSchemaCheckGroupDefCircular only.
16753 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016754 * Returns the particle with the circular model group definition reference,
16755 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016756 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016757static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016758xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016759 xmlSchemaTreeItemPtr particle)
16760{
16761 xmlSchemaTreeItemPtr circ = NULL;
16762 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016763 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016764
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016765 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016766 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016767 if (term == NULL)
16768 continue;
16769 switch (term->type) {
16770 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016771 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016772 if (gdef == groupDef)
16773 return (particle);
16774 /*
16775 * Mark this model group definition to avoid infinite
16776 * recursion on circular references not yet examined.
16777 */
16778 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16779 continue;
16780 if (gdef->children != NULL) {
16781 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16782 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16783 gdef->children->children);
16784 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16785 if (circ != NULL)
16786 return (circ);
16787 }
16788 break;
16789 case XML_SCHEMA_TYPE_SEQUENCE:
16790 case XML_SCHEMA_TYPE_CHOICE:
16791 case XML_SCHEMA_TYPE_ALL:
16792 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16793 if (circ != NULL)
16794 return (circ);
16795 break;
16796 default:
16797 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016798 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016799 }
16800 return (NULL);
16801}
16802
16803/**
16804 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016805 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016806 * @ctxt: the parser context
16807 * @name: the name
16808 *
16809 * Checks for circular references to model group definitions.
16810 */
16811static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016812xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016813 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016814 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016815{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016816 /*
16817 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016818 * 2 Circular groups are disallowed. That is, within the {particles}
16819 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016820 * is the group itself.
16821 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016822 if ((item == NULL) ||
16823 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16824 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016825 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016826 {
16827 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016828
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016829 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016830 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016831 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016832 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016833 * TODO: The error report is not adequate: this constraint
16834 * is defined for model groups but not definitions, but since
16835 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016836 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016837 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016838 */
16839 xmlSchemaPCustomErr(ctxt,
16840 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016841 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016842 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016843 "defined", xmlSchemaFormatQName(&str,
16844 item->targetNamespace, item->name));
16845 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016846 /*
16847 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016848 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016849 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016850 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016851 }
16852 }
16853}
16854
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016855/**
16856 * xmlSchemaGroupDefTermFixup:
16857 * @item: the particle with a model group definition as term
16858 * @ctxt: the parser context
16859 * @name: the name
16860 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016861 * Checks cos-all-limited.
16862 *
16863 * Assigns the model group of model group definitions to the "term"
16864 * of the referencing particle.
16865 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16866 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016867 */
16868static void
16869xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016870 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016871 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016872{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016873 if ((item == NULL) ||
16874 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16875 (item->children == NULL) ||
16876 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16877 (item->children->children == NULL))
16878 return;
16879 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880 /*
16881 * TODO: Not nice, but we will anchor cos-all-limited here.
16882 */
16883 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16884 (item->maxOccurs != 1)) {
16885 /*
16886 * SPEC (1.2) "the {term} property of a particle with
16887 * {max occurs}=1which is part of a pair which constitutes the
16888 * {content type} of a complex type definition."
16889 */
16890 xmlSchemaPCustomErr(ctxt,
16891 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16892 NULL, (xmlSchemaTypePtr) item, item->node,
16893 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16894 "group is its term", NULL);
16895 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016896}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016897
16898/**
16899 * xmlSchemaGetCircAttrGrRef:
16900 * @ctxtGr: the searched attribute group
16901 * @attr: the current attribute list to be processed
16902 *
16903 * This one is intended to be used by
16904 * xmlSchemaCheckSRCAttributeGroupCircular only.
16905 *
16906 * Returns the circular attribute grou reference, otherwise NULL.
16907 */
16908static xmlSchemaAttributeGroupPtr
16909xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16910 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016911{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016912 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16913 int marked;
16914 /*
16915 * We will search for an attribute group reference which
16916 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016917 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016918 while (attr != NULL) {
16919 marked = 0;
16920 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16921 gr = (xmlSchemaAttributeGroupPtr) attr;
16922 if (gr->refItem != NULL) {
16923 if (gr->refItem == ctxtGr)
16924 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016925 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016926 XML_SCHEMAS_ATTRGROUP_MARKED) {
16927 attr = attr->next;
16928 continue;
16929 } else {
16930 /*
16931 * Mark as visited to avoid infinite recursion on
16932 * circular references not yet examined.
16933 */
16934 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16935 marked = 1;
16936 }
16937 }
16938 if (gr->attributes != NULL)
16939 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16940 /*
16941 * Unmark the visited group's attributes.
16942 */
16943 if (marked)
16944 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16945 if (circ != NULL)
16946 return (circ);
16947 }
16948 attr = attr->next;
16949 }
16950 return (NULL);
16951}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016952
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016953/**
16954 * xmlSchemaCheckSRCAttributeGroupCircular:
16955 * attrGr: the attribute group definition
16956 * @ctxt: the parser context
16957 * @name: the name
16958 *
16959 * Checks for circular references of attribute groups.
16960 */
16961static void
16962xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016963 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016964 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016965{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016966 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016967 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016968 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016969 * 3 Circular group reference is disallowed outside <redefine>.
16970 * That is, unless this element information item's parent is
16971 * <redefine>, then among the [children], if any, there must
16972 * not be an <attributeGroup> with ref [attribute] which resolves
16973 * to the component corresponding to this <attributeGroup>. Indirect
16974 * circularity is also ruled out. That is, when QName resolution
16975 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16976 * any <attributeGroup>s with a ref [attribute] among the [children],
16977 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016978 * which resolves to the component corresponding to this <attributeGroup>.
16979 */
16980 /*
16981 * Only global components can be referenced.
16982 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016983 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016984 (attrGr->attributes == NULL))
16985 return;
16986 else {
16987 xmlSchemaAttributeGroupPtr circ;
16988
16989 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16990 if (circ != NULL) {
16991 /*
16992 * TODO: Report the referenced attr group as QName.
16993 */
16994 xmlSchemaPCustomErr(ctxt,
16995 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16996 NULL, NULL, circ->node,
16997 "Circular reference to the attribute group '%s' "
16998 "defined", attrGr->name);
16999 /*
17000 * NOTE: We will cut the reference to avoid further
17001 * confusion of the processor.
17002 * BADSPEC: The spec should define how to process in this case.
17003 */
17004 circ->attributes = NULL;
17005 circ->refItem = NULL;
17006 }
17007 }
17008}
17009
17010/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017011 * xmlSchemaAttrGrpFixup:
17012 * @attrgrpDecl: the schema attribute definition
17013 * @ctxt: the schema parser context
17014 * @name: the attribute name
17015 *
17016 * Fixes finish doing the computations on the attributes definitions
17017 */
17018static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017019xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017020 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017021{
17022 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017023 name = attrgrp->name;
17024 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017025 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017026 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017027 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017028
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017029 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017030 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017031 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017032 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017033 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017034 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17035 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017036 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017037 return;
17038 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017039 attrgrp->refItem = ref;
17040 /*
17041 * Check for self reference!
17042 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017043 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017044 attrgrp->attributes = ref->attributes;
17045 attrgrp->attributeWildcard = ref->attributeWildcard;
17046 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017047}
17048
17049/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017050 * xmlSchemaAttrCheckValConstr:
17051 * @item: an schema attribute declaration/use
17052 * @ctxt: a schema parser context
17053 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017054 *
17055 *
17056 * Schema Component Constraint: Attribute Declaration Properties Correct
17057 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017058 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017059 *
17060 * Fixes finish doing the computations on the attributes definitions
17061 */
17062static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017063xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017064 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017065 const xmlChar * name ATTRIBUTE_UNUSED)
17066{
17067
17068 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017069 * 2 if there is a {value constraint}, the canonical lexical
17070 * representation of its value must be ·valid· with respect
17071 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017072 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017073 if (item->defValue != NULL) {
17074 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017075
17076 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017077 PERROR_INT("xmlSchemaCheckAttrValConstr",
17078 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017079 return;
17080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017081 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17082 item->node, item->subtypes, item->defValue, &(item->defVal),
17083 1, 1, 0);
17084 if (ret != 0) {
17085 if (ret < 0) {
17086 PERROR_INT("xmlSchemaAttrCheckValConstr",
17087 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017088 return;
17089 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017090 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17091 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17092 ret, item->node, (xmlSchemaTypePtr) item,
17093 "The value of the value constraint is not valid", NULL, NULL);
17094 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017095 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017096 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017097}
17098
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017099static xmlSchemaElementPtr
17100xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17101 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017102{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017103 xmlSchemaElementPtr ret;
17104
17105 if (SUBST_GROUP_AFF(ancestor) == NULL)
17106 return (NULL);
17107 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17108 return (ancestor);
17109
17110 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17111 return (NULL);
17112 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17113 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17114 SUBST_GROUP_AFF(ancestor));
17115 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17116
17117 return (ret);
17118}
17119
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017120/**
17121 * xmlSchemaCheckElemPropsCorrect:
17122 * @ctxt: a schema parser context
17123 * @decl: the element declaration
17124 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017125 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017126 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017127 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017128 *
17129 * STATUS:
17130 * missing: (6)
17131 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017132static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017133xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17134 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017135{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017136 int ret = 0;
17137 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017138 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017139 * SPEC (1) "The values of the properties of an element declaration
17140 * must be as described in the property tableau in The Element
17141 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17142 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017143 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017144 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017145 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017146
17147 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017148 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017149 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017150 * affiliation}, then {scope} must be global."
17151 */
17152 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17153 xmlSchemaPCustomErr(pctxt,
17154 XML_SCHEMAP_E_PROPS_CORRECT_3,
17155 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17156 "Only global element declarations can have a "
17157 "substitution group affiliation", NULL);
17158 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017159 }
17160 /*
17161 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17162 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017164 * property."
17165 */
17166 if (head == elemDecl)
17167 circ = head;
17168 else if (SUBST_GROUP_AFF(head) != NULL)
17169 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17170 else
17171 circ = NULL;
17172 if (circ != NULL) {
17173 xmlChar *strA = NULL, *strB = NULL;
17174
17175 xmlSchemaPCustomErrExt(pctxt,
17176 XML_SCHEMAP_E_PROPS_CORRECT_6,
17177 NULL, (xmlSchemaTypePtr) circ, circ->node,
17178 "The element declaration '%s' defines a circular "
17179 "substitution group to element declaration '%s'",
17180 xmlSchemaGetComponentQName(&strA, circ),
17181 xmlSchemaGetComponentQName(&strB, head),
17182 NULL);
17183 FREE_AND_NULL(strA)
17184 FREE_AND_NULL(strB)
17185 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17186 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017187 /*
17188 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017189 * the {type definition}
17190 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017191 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017192 * of the {substitution group exclusions} of the {substitution group
17193 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17194 * (if the {type definition} is complex) or as defined in
17195 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017196 * simple)."
17197 *
17198 * NOTE: {substitution group exclusions} means the values of the
17199 * attribute "final".
17200 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017201
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017202 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017203 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017204
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017205 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17206 set |= SUBSET_EXTENSION;
17207 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17208 set |= SUBSET_RESTRICTION;
17209
17210 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17211 ELEM_TYPE(head), set) != 0) {
17212 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17213
17214 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017215 xmlSchemaPCustomErrExt(pctxt,
17216 XML_SCHEMAP_E_PROPS_CORRECT_4,
17217 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017218 "The type definition '%s' was "
17219 "either rejected by the substitution group "
17220 "affiliation '%s', or not validly derived from its type "
17221 "definition '%s'",
17222 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017223 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017224 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017225 FREE_AND_NULL(strA)
17226 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017227 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017228 }
17229 }
17230 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017231 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017232 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017233 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017234 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017235 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017236 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017237 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017238 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017239 ((IS_SIMPLE_TYPE(typeDef) &&
17240 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017241 (IS_COMPLEX_TYPE(typeDef) &&
17242 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017243 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17244 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017245
17246 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17247 xmlSchemaPCustomErr(pctxt,
17248 XML_SCHEMAP_E_PROPS_CORRECT_5,
17249 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17250 "The type definition (or type definition's content type) is or "
17251 "is derived from ID; value constraints are not allowed in "
17252 "conjunction with such a type definition", NULL);
17253 } else if (elemDecl->value != NULL) {
17254 int vcret;
17255 xmlNodePtr node = NULL;
17256
17257 /*
17258 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17259 * representation of its value must be ·valid· with respect to the
17260 * {type definition} as defined in Element Default Valid (Immediate)
17261 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017262 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017263 if (typeDef == NULL) {
17264 xmlSchemaPErr(pctxt, elemDecl->node,
17265 XML_SCHEMAP_INTERNAL,
17266 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17267 "type is missing... skipping validation of "
17268 "the value constraint", NULL, NULL);
17269 return (-1);
17270 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017271 if (elemDecl->node != NULL) {
17272 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17273 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17274 BAD_CAST "fixed");
17275 else
17276 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17277 BAD_CAST "default");
17278 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017279 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17280 typeDef, elemDecl->value, &(elemDecl->defVal));
17281 if (vcret != 0) {
17282 if (vcret < 0) {
17283 PERROR_INT("xmlSchemaElemCheckValConstr",
17284 "failed to validate the value constraint of an "
17285 "element declaration");
17286 return (-1);
17287 }
17288 return (vcret);
17289 }
17290 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017291
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017292 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017293}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017294
17295/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017296 * xmlSchemaCheckElemSubstGroup:
17297 * @ctxt: a schema parser context
17298 * @decl: the element declaration
17299 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017300 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017301 * Schema Component Constraint:
17302 * Substitution Group (cos-equiv-class)
17303 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017304 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017305 * a list will be built for each subst. group head, holding all direct
17306 * referents to this head.
17307 * NOTE that this function needs:
17308 * 1. circular subst. groups to be checked beforehand
17309 * 2. the declaration's type to be derived from the head's type
17310 *
17311 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017312 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017313 */
17314static void
17315xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17316 xmlSchemaElementPtr elemDecl)
17317{
17318 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17319 /* SPEC (1) "Its {abstract} is false." */
17320 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17321 return;
17322 {
17323 xmlSchemaElementPtr head;
17324 xmlSchemaTypePtr headType, type;
17325 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017326 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017327 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17328 * {disallowed substitutions} as the blocking constraint, as defined in
17329 * Substitution Group OK (Transitive) (§3.3.6)."
17330 */
17331 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17332 head = SUBST_GROUP_AFF(head)) {
17333 set = 0;
17334 methSet = 0;
17335 /*
17336 * The blocking constraints.
17337 */
17338 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17339 continue;
17340 headType = head->subtypes;
17341 type = elemDecl->subtypes;
17342 if (headType == type)
17343 goto add_member;
17344 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17345 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17346 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17347 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17348 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017349 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017350 * "The set of all {derivation method}s involved in the
17351 * derivation of D's {type definition} from C's {type definition}
17352 * does not intersect with the union of the blocking constraint,
17353 * C's {prohibited substitutions} (if C is complex, otherwise the
17354 * empty set) and the {prohibited substitutions} (respectively the
17355 * empty set) of any intermediate {type definition}s in the
17356 * derivation of D's {type definition} from C's {type definition}."
17357 */
17358 /*
17359 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17360 * subst.head axis, the methSet does not need to be computed for
17361 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017362 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017363 /*
17364 * The set of all {derivation method}s involved in the derivation
17365 */
17366 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017367 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017368 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17369 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17370 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017371
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017372 if ((type->flags &
17373 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17374 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17375 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17376
17377 type = type->baseType;
17378 }
17379 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017380 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017381 * the head's type.
17382 */
17383 type = elemDecl->subtypes->baseType;
17384 while (type != NULL) {
17385 if (IS_COMPLEX_TYPE(type)) {
17386 if ((type->flags &
17387 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17388 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17389 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17390 if ((type->flags &
17391 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17392 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17393 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17394 } else
17395 break;
17396 if (type == headType)
17397 break;
17398 type = type->baseType;
17399 }
17400 if ((set != 0) &&
17401 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17402 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17403 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17404 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17405 continue;
17406 }
17407add_member:
17408 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17409 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17410 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17411 }
17412 }
17413}
17414
17415/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017416 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017417 * @item: an schema element declaration/particle
17418 * @ctxt: a schema parser context
17419 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017420 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017421 * Validates the value constraints of an element declaration.
17422 *
17423 * Fixes finish doing the computations on the element declarations.
17424 */
17425static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017426xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017427 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017428 const xmlChar * name ATTRIBUTE_UNUSED)
17429{
17430 if (elemDecl == NULL)
17431 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017432 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17433 return;
17434 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017435 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17436 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017437}
17438
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017439/**
17440 * xmlSchemaMiscRefFixup:
17441 * @item: an schema component
17442 * @ctxt: a schema parser context
17443 * @name: the internal name of the component
17444 *
17445 * Resolves references of misc. schema components.
17446 */
17447static void
17448xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017449 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017450 const xmlChar * name ATTRIBUTE_UNUSED)
17451{
17452 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017453 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017454 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17455 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17456 xmlSchemaTreeItemPtr refItem;
17457 /*
17458 * Resolve the reference.
17459 */
17460 item->children = NULL;
17461 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17462 ref->itemType, ref->name, ref->targetNamespace);
17463 if (refItem == NULL) {
17464 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017465 NULL, GET_NODE(item), "ref", ref->name,
17466 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017467 } else {
17468 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17469 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017470 * NOTE that we will assign the model group definition
17471 * itself to the "term" of the particle. This will ease
17472 * the check for circular model group definitions. After
17473 * that the "term" will be assigned the model group of the
17474 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017475 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017476 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017477 } else
17478 item->children = refItem;
17479 }
17480 }
17481 }
17482}
17483
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017484static int
17485xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17486 xmlSchemaValPtr y)
17487{
17488 xmlSchemaTypePtr tx, ty, ptx, pty;
17489 int ret;
17490
17491 while (x != NULL) {
17492 /* Same types. */
17493 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17494 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17495 ptx = xmlSchemaGetPrimitiveType(tx);
17496 pty = xmlSchemaGetPrimitiveType(ty);
17497 /*
17498 * (1) if a datatype T' is ·derived· by ·restriction· from an
17499 * atomic datatype T then the ·value space· of T' is a subset of
17500 * the ·value space· of T. */
17501 /*
17502 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17503 * from a common atomic ancestor T then the ·value space·s of T'
17504 * and T'' may overlap.
17505 */
17506 if (ptx != pty)
17507 return(0);
17508 /*
17509 * We assume computed values to be normalized, so do a fast
17510 * string comparison for string based types.
17511 */
17512 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17513 IS_ANY_SIMPLE_TYPE(ptx)) {
17514 if (! xmlStrEqual(
17515 xmlSchemaValueGetAsString(x),
17516 xmlSchemaValueGetAsString(y)))
17517 return (0);
17518 } else {
17519 ret = xmlSchemaCompareValuesWhtsp(
17520 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17521 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17522 if (ret == -2)
17523 return(-1);
17524 if (ret != 0)
17525 return(0);
17526 }
17527 /*
17528 * Lists.
17529 */
17530 x = xmlSchemaValueGetNext(x);
17531 if (x != NULL) {
17532 y = xmlSchemaValueGetNext(y);
17533 if (y == NULL)
17534 return (0);
17535 } else if (xmlSchemaValueGetNext(y) != NULL)
17536 return (0);
17537 else
17538 return (1);
17539 }
17540 return (0);
17541}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017542
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017543/**
17544 * xmlSchemaAttrFixup:
17545 * @item: an schema attribute declaration/use.
17546 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017547 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017548 *
17549 * Fixes finish doing the computations on attribute declarations/uses.
17550 */
17551static void
17552xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017553 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017554 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017555{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017556 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017557 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017558 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017559 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017560 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017561 * The simple type definition corresponding to the <simpleType> element
17562 * information item in the [children], if present, otherwise the simple
17563 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017564 * [attribute], if present, otherwise the ·simple ur-type definition·.
17565 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017566 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017567 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017568 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17569 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017570 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017571 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017572 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017573
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017574 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17575 item->typeNs);
17576 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017577 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017578 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579 (xmlSchemaTypePtr) item, item->node,
17580 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017581 XML_SCHEMA_TYPE_SIMPLE, NULL);
17582 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017583 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017584
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017585 } else if (item->ref != NULL) {
17586 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017587
Daniel Veillardc0826a72004-08-10 14:17:33 +000017588 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017590 * attribute declaration.
17591 */
17592 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017593 * TODO: Evaluate, what errors could occur if the declaration is not
17594 * found. It might be possible that the "typefixup" might crash if
17595 * no ref declaration was found.
17596 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017597 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017598 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017599 xmlSchemaPResCompAttrErr(ctxt,
17600 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017601 (xmlSchemaTypePtr) item, item->node,
17602 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017603 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017604 return;
17605 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017606 item->refDecl = decl;
17607 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017608 item->subtypes = decl->subtypes;
17609 /*
17610 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017611 * au-props-correct.2: If the {attribute declaration} has a fixed
17612 * {value constraint}, then if the attribute use itself has a
17613 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017614 * that of the {attribute declaration}'s {value constraint}.
17615 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017616 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017617 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017618 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017619 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017620 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17621 NULL, NULL, item->node,
17622 "The attribute declaration has a 'fixed' value constraint "
17623 ", thus it must be 'fixed' in attribute use as well",
17624 NULL);
17625 } else {
17626 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17627 xmlSchemaPCustomErr(ctxt,
17628 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17629 NULL, NULL, item->node,
17630 "The 'fixed' value constraint of the attribute use "
17631 "must match the attribute declaration's value "
17632 "constraint '%s'",
17633 decl->defValue);
17634 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017635 }
17636 /*
17637 * FUTURE: One should change the values of the attr. use
17638 * if ever validation should be attempted even if the
17639 * schema itself was not fully valid.
17640 */
17641 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017642 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017643 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17644 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017645}
17646
17647/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017648 * xmlSchemaResolveIDCKeyRef:
17649 * @idc: the identity-constraint definition
17650 * @ctxt: the schema parser context
17651 * @name: the attribute name
17652 *
17653 * Resolve keyRef references to key/unique IDCs.
17654 */
17655static void
17656xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017657 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017658 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017659{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017660 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17661 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017662 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017663 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017664 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017665 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017666 idc->ref->targetNamespace);
17667 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017668 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017669 * TODO: It is actually not an error to fail to resolve.
17670 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017671 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017672 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017673 (xmlSchemaTypePtr) idc, idc->node,
17674 "refer", idc->ref->name,
17675 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017676 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17677 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017678 } else {
17679 if (idc->nbFields !=
17680 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17681 xmlChar *str = NULL;
17682 xmlSchemaIDCPtr refer;
17683
17684 refer = (xmlSchemaIDCPtr) idc->ref->item;
17685 /*
17686 * SPEC c-props-correct(2)
17687 * "If the {identity-constraint category} is keyref,
17688 * the cardinality of the {fields} must equal that of
17689 * the {fields} of the {referenced key}.
17690 */
17691 xmlSchemaPCustomErr(pctxt,
17692 XML_SCHEMAP_C_PROPS_CORRECT,
17693 NULL, (xmlSchemaTypePtr) idc, idc->node,
17694 "The cardinality of the keyref differs from the "
17695 "cardinality of the referenced key '%s'",
17696 xmlSchemaFormatQName(&str, refer->targetNamespace,
17697 refer->name)
17698 );
17699 FREE_AND_NULL(str)
17700 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017701 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017702 }
17703}
17704
17705/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017706 * xmlSchemaParse:
17707 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017708 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017709 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017710 * XML Shema struture which can be used to validate instances.
17711 * *WARNING* this interface is highly subject to change
17712 *
17713 * Returns the internal XML Schema structure built from the resource or
17714 * NULL in case of error
17715 */
17716xmlSchemaPtr
17717xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17718{
17719 xmlSchemaPtr ret = NULL;
17720 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017721 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017722 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017723
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017724 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017725 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017726 * the API; i.e. not automatically by the validated instance document.
17727 */
17728
Daniel Veillard4255d502002-04-16 15:50:10 +000017729 xmlSchemaInitTypes();
17730
Daniel Veillard6045c902002-10-09 21:13:59 +000017731 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017732 return (NULL);
17733
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017734 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017735 ctxt->counter = 0;
17736 ctxt->container = NULL;
17737
17738 /*
17739 * First step is to parse the input document into an DOM/Infoset
17740 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017741 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017742 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017743 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017744 if (doc == NULL) {
17745 xmlSchemaPErr(ctxt, NULL,
17746 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017747 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017748 ctxt->URL, NULL);
17749 return (NULL);
17750 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017751 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017752 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17753 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017754 if (doc == NULL) {
17755 xmlSchemaPErr(ctxt, NULL,
17756 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017757 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017758 NULL, NULL);
17759 return (NULL);
17760 }
17761 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017762 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017763 } else if (ctxt->doc != NULL) {
17764 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017765 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017766 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017767 xmlSchemaPErr(ctxt, NULL,
17768 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017769 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017770 NULL, NULL);
17771 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017772 }
17773
17774 /*
17775 * Then extract the root and Schema parse it
17776 */
17777 root = xmlDocGetRootElement(doc);
17778 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017779 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17780 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017781 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017782 if (!preserve) {
17783 xmlFreeDoc(doc);
17784 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017785 return (NULL);
17786 }
17787
17788 /*
17789 * Remove all the blank text nodes
17790 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017791 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017792
17793 /*
17794 * Then do the parsing for good
17795 */
17796 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017797 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017798 if (!preserve) {
17799 xmlFreeDoc(doc);
17800 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017801 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017802 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017803 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017804 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017805 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017806 ctxt->ctxtType = NULL;
17807 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017808
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017809 /*
17810 * Resolve base types of simple/complex types.
17811 */
17812 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017813
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017814 if (ctxt->nberrors != 0)
17815 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017816
17817 if (ret->volatiles != NULL) {
17818 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17819 int i;
17820 xmlSchemaTreeItemPtr item;
17821
17822 for (i = 0; i < list->nbItems; i++) {
17823 item = (xmlSchemaTreeItemPtr) list->items[i];
17824 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17825 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017826 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017827 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017828 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017829 * Then fixup all attributes declarations
17830 */
17831 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017832 /*
17833 * Then fixup all attributes group declarations
17834 */
17835 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17836 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017837 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017838 * Resolve identity-constraint keyRefs.
17839 */
17840 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017841 /*
17842 * Check type defnitions for circular references.
17843 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017844 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017845 xmlSchemaCheckTypeDefCircular, ctxt);
17846 /*
17847 * Check model groups defnitions for circular references.
17848 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017849 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017850 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017851 /*
17852 * Set the "term" of particles pointing to model group definitions
17853 * to the contained model group.
17854 */
17855 if (ret->volatiles != NULL) {
17856 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17857 int i;
17858 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017859
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017860 for (i = 0; i < list->nbItems; i++) {
17861 item = (xmlSchemaParticlePtr) list->items[i];
17862 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17863 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17864 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017865 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017866 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017867 * Check attribute groups for circular references.
17868 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017869 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17870 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017871 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017872 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017873 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017874 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017875 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017876 /*
17877 * We will stop here if the schema was not valid to avoid internal errors
17878 * on missing sub-components. This is not conforming to the spec, since it
17879 * allows missing components, but it might make further processing crash.
17880 * So see it as a very strict handling, which might be made more lax in the
17881 * future.
17882 */
17883 if (ctxt->nberrors != 0)
17884 goto exit;
17885 /*
17886 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017887 */
17888 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017889 /*
17890 * Validate the value constraint of attribute declarations/uses.
17891 */
17892 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017893 /*
17894 * Validate the value constraint of element declarations.
17895 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017896 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017897
17898 if (ctxt->nberrors != 0)
17899 goto exit;
17900
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017901 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017902 * TODO: cos-element-consistent, cos-all-limited
17903 *
17904 * Then build the content model for all complex types
17905 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017906 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017907 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017908
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017909exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017910 if (ctxt->nberrors != 0) {
17911 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017912 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017913 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017914 return (ret);
17915}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017916
Daniel Veillard4255d502002-04-16 15:50:10 +000017917/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017918 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017919 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017920 * @err: the error callback
17921 * @warn: the warning callback
17922 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017923 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017924 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017925 */
17926void
17927xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017928 xmlSchemaValidityErrorFunc err,
17929 xmlSchemaValidityWarningFunc warn, void *ctx)
17930{
Daniel Veillard4255d502002-04-16 15:50:10 +000017931 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017932 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017933 ctxt->error = err;
17934 ctxt->warning = warn;
17935 ctxt->userData = ctx;
17936}
17937
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017938/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017939 * xmlSchemaGetParserErrors:
17940 * @ctxt: a XMl-Schema parser context
17941 * @err: the error callback result
17942 * @warn: the warning callback result
17943 * @ctx: contextual data for the callbacks result
17944 *
17945 * Get the callback information used to handle errors for a parser context
17946 *
17947 * Returns -1 in case of failure, 0 otherwise
17948 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017949int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017950xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17951 xmlSchemaValidityErrorFunc * err,
17952 xmlSchemaValidityWarningFunc * warn, void **ctx)
17953{
17954 if (ctxt == NULL)
17955 return(-1);
17956 if (err != NULL)
17957 *err = ctxt->error;
17958 if (warn != NULL)
17959 *warn = ctxt->warning;
17960 if (ctx != NULL)
17961 *ctx = ctxt->userData;
17962 return(0);
17963}
17964
17965/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017966 * xmlSchemaFacetTypeToString:
17967 * @type: the facet type
17968 *
17969 * Convert the xmlSchemaTypeType to a char string.
17970 *
17971 * Returns the char string representation of the facet type if the
17972 * type is a facet and an "Internal Error" string otherwise.
17973 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017974static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017975xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17976{
17977 switch (type) {
17978 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017979 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017980 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017981 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017982 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017983 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017984 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017985 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017986 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017987 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017988 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017989 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017990 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017991 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017992 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017993 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017994 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017995 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017996 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017997 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017998 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017999 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018000 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018001 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018002 default:
18003 break;
18004 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018005 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018006}
18007
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018008static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000018009xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
18010{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018011 /*
18012 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000018013 * from xsd:string.
18014 */
18015 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018016 /*
18017 * Note that we assume a whitespace of preserve for anySimpleType.
18018 */
18019 if ((type->builtInType == XML_SCHEMAS_STRING) ||
18020 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18021 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000018022 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018023 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018024 else {
18025 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018026 * For all ·atomic· datatypes other than string (and types ·derived·
18027 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018028 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018029 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018030 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018031 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018032 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018033 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018034 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018035 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018037 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18038 } else if (VARIETY_UNION(type)) {
18039 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18040 } else if (VARIETY_ATOMIC(type)) {
18041 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18042 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18043 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18044 return (XML_SCHEMA_WHITESPACE_REPLACE);
18045 else
18046 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018047 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018048 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018049}
18050
Daniel Veillard4255d502002-04-16 15:50:10 +000018051/************************************************************************
18052 * *
18053 * Simple type validation *
18054 * *
18055 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018056
Daniel Veillard4255d502002-04-16 15:50:10 +000018057
18058/************************************************************************
18059 * *
18060 * DOM Validation code *
18061 * *
18062 ************************************************************************/
18063
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018064static void
18065xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18066{
18067 int i, nbItems;
18068 xmlSchemaTypePtr item, *items;
18069
18070
18071 /*
18072 * During the Assemble of the schema ctxt->curItems has
18073 * been filled with the relevant new items. Fix those up.
18074 */
18075 nbItems = ctxt->assemble->nbItems;
18076 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018077
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018078 for (i = 0; i < nbItems; i++) {
18079 item = items[i];
18080 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018081 case XML_SCHEMA_TYPE_COMPLEX:
18082 case XML_SCHEMA_TYPE_SIMPLE:
18083 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18084 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018085 case XML_SCHEMA_TYPE_ATTRIBUTE:
18086 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18087 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018088 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018089 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018090 ctxt, NULL);
18091 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018092 case XML_SCHEMA_TYPE_PARTICLE:
18093 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018094 break;
18095 case XML_SCHEMA_TYPE_IDC_KEY:
18096 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18097 case XML_SCHEMA_TYPE_IDC_KEYREF:
18098 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18099 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018100 default:
18101 break;
18102 }
18103 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018104 if (ctxt->nberrors != 0)
18105 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018106 /*
18107 * Circularity checks.
18108 */
18109 for (i = 0; i < nbItems; i++) {
18110 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018111 switch (item->type) {
18112 case XML_SCHEMA_TYPE_COMPLEX:
18113 case XML_SCHEMA_TYPE_SIMPLE:
18114 xmlSchemaCheckTypeDefCircular(
18115 (xmlSchemaTypePtr) item, ctxt, NULL);
18116 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018117 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018118 xmlSchemaCheckGroupDefCircular(
18119 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018120 break;
18121 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18122 xmlSchemaCheckAttributeGroupCircular(
18123 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18124 break;
18125 default:
18126 break;
18127 }
18128 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018129 if (ctxt->nberrors != 0)
18130 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018131 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018132 * Set the "term" of particles pointing to model group definitions
18133 * to the contained model group.
18134 */
18135 for (i = 0; i < nbItems; i++) {
18136 item = items[i];
18137 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18138 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018139 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018140 XML_SCHEMA_TYPE_GROUP)) {
18141 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18142 ctxt, NULL);
18143 }
18144 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018145 if (ctxt->nberrors != 0)
18146 return;
18147 for (i = 0; i < nbItems; i++) {
18148 item = items[i];
18149 switch (item->type) {
18150 case XML_SCHEMA_TYPE_ELEMENT:
18151 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18152 NULL, NULL, NULL);
18153 break;
18154 default:
18155 break;
18156 }
18157 }
18158 if (ctxt->nberrors != 0)
18159 return;
18160
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018161 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018162 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018163 */
18164 for (i = 0; i < nbItems; i++) {
18165 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018166 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018167 case XML_SCHEMA_TYPE_SIMPLE:
18168 case XML_SCHEMA_TYPE_COMPLEX:
18169 xmlSchemaTypeFixup(item, ctxt, NULL);
18170 break;
18171 default:
18172 break;
18173 }
18174 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018175 if (ctxt->nberrors != 0)
18176 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018177 /*
18178 * Validate value contraint values.
18179 */
18180 for (i = 0; i < nbItems; i++) {
18181 item = items[i];
18182 switch (item->type) {
18183 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018184 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18185 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018186 break;
18187 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018188 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018189 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018190 break;
18191 default:
18192 break;
18193 }
18194 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018195 if (ctxt->nberrors != 0)
18196 return;
18197 /*
18198 * Build the content model for complex types.
18199 */
18200 for (i = 0; i < nbItems; i++) {
18201 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018202 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018203 case XML_SCHEMA_TYPE_COMPLEX:
18204 xmlSchemaBuildContentModel(item, ctxt, NULL);
18205 break;
18206 default:
18207 break;
18208 }
18209 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018210}
18211
18212/**
18213 * xmlSchemaAssembleByLocation:
18214 * @pctxt: a schema parser context
18215 * @vctxt: a schema validation context
18216 * @schema: the existing schema
18217 * @node: the node that fired the assembling
18218 * @nsName: the namespace name of the new schema
18219 * @location: the location of the schema
18220 *
18221 * Expands an existing schema by an additional schema.
18222 *
18223 * Returns 0 if the new schema is correct, a positive error code
18224 * number otherwise and -1 in case of an internal or API error.
18225 */
18226static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018227xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018228 xmlSchemaPtr schema,
18229 xmlNodePtr node,
18230 const xmlChar *nsName,
18231 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018233 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018234 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018235 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018236 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018237 xmlSchemaParserCtxtPtr pctxt;
18238
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018239 /*
18240 * This should be used:
18241 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018242 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018243 * 3. if requested via the API
18244 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018245 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018246 return (-1);
18247 /*
18248 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018250 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018251 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18252 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018253 pctxt = vctxt->pctxt;
18254 /*
18255 * Set the counter to produce unique names for anonymous items.
18256 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018257 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018258 /*
18259 * Acquire the schema document.
18260 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018261 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18262 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018263 if (ret != 0) {
18264 if (doc != NULL)
18265 xmlFreeDoc(doc);
18266 } else if (doc != NULL) {
18267 docElem = xmlDocGetRootElement(doc);
18268 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018269 * Create new assemble info.
18270 */
18271 if (pctxt->assemble == NULL) {
18272 pctxt->assemble = xmlSchemaNewAssemble();
18273 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018274 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018275 "Memory error: xmlSchemaAssembleByLocation, "
18276 "allocating assemble info", NULL);
18277 xmlFreeDoc(doc);
18278 return (-1);
18279 }
18280 }
18281 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018282 * Save and reset the context & schema.
18283 */
18284 oldflags = schema->flags;
18285 oldtns = schema->targetNamespace;
18286 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018287 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018288
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018289 xmlSchemaClearSchemaDefaults(schema);
18290 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018291 if ((targetNs != NULL) &&
18292 xmlStrEqual(targetNs, xmlSchemaNs)) {
18293 /*
18294 * We are parsing the schema for schema!
18295 */
18296 vctxt->pctxt->isS4S = 1;
18297 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018298 /* schema->nbCurItems = 0; */
18299 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018300 pctxt->ctxtType = NULL;
18301 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018302
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018303 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18304 if (pctxt->nberrors != 0) {
18305 vctxt->nberrors += pctxt->nberrors;
18306 goto finally;
18307 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018308 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018309 if (pctxt->nberrors != 0) {
18310 vctxt->nberrors += pctxt->nberrors;
18311 goto finally;
18312 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018313 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018314 if (pctxt->nberrors != 0)
18315 vctxt->nberrors += pctxt->nberrors;
18316finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018317 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018318 * Set the counter of items.
18319 */
18320 schema->counter = pctxt->counter;
18321 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018322 * Free the list of assembled components.
18323 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018324 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018325 /*
18326 * Restore the context & schema.
18327 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018328 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018329 schema->flags = oldflags;
18330 schema->targetNamespace = oldtns;
18331 schema->doc = olddoc;
18332 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018333 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018334 return (ret);
18335}
18336
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018337static xmlSchemaAttrInfoPtr
18338xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18339 int metaType)
18340{
18341 if (vctxt->nbAttrInfos == 0)
18342 return (NULL);
18343 {
18344 int i;
18345 xmlSchemaAttrInfoPtr iattr;
18346
18347 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18348 iattr = vctxt->attrInfos[i];
18349 if (iattr->metaType == metaType)
18350 return (iattr);
18351 }
18352
18353 }
18354 return (NULL);
18355}
18356
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018357/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018358 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018359 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018360 *
18361 * Expands an existing schema by an additional schema using
18362 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18363 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18364 * must be set to 1.
18365 *
18366 * Returns 0 if the new schema is correct, a positive error code
18367 * number otherwise and -1 in case of an internal or API error.
18368 */
18369static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018370xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018371{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018372 const xmlChar *cur, *end;
18373 const xmlChar *nsname = NULL, *location;
18374 int count = 0;
18375 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018376 xmlSchemaAttrInfoPtr iattr;
18377
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018378 /*
18379 * Parse the value; we will assume an even number of values
18380 * to be given (this is how Xerces and XSV work).
18381 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018382 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18383 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18384 if (iattr == NULL)
18385 xmlSchemaGetMetaAttrInfo(vctxt,
18386 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18387 if (iattr == NULL)
18388 return (0);
18389 cur = iattr->value;
18390 do {
18391 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392 /*
18393 * Get the namespace name.
18394 */
18395 while (IS_BLANK_CH(*cur))
18396 cur++;
18397 end = cur;
18398 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18399 end++;
18400 if (end == cur)
18401 break;
18402 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018403 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018404 cur = end;
18405 }
18406 /*
18407 * Get the URI.
18408 */
18409 while (IS_BLANK_CH(*cur))
18410 cur++;
18411 end = cur;
18412 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18413 end++;
18414 if (end == cur)
18415 break;
18416 count++;
18417 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018418 cur = end;
18419 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18420 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018421 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018422 VERROR_INT("xmlSchemaAssembleByXSI",
18423 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018424 return (-1);
18425 }
18426 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018427 return (ret);
18428}
18429
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018430#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018431
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018432static const xmlChar *
18433xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18434 const xmlChar *prefix)
18435{
18436 if (vctxt->sax != NULL) {
18437 int i, j;
18438 xmlSchemaNodeInfoPtr inode;
18439
18440 for (i = vctxt->depth; i >= 0; i--) {
18441 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18442 inode = vctxt->elemInfos[i];
18443 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18444 if (((prefix == NULL) &&
18445 (inode->nsBindings[j] == NULL)) ||
18446 ((prefix != NULL) && xmlStrEqual(prefix,
18447 inode->nsBindings[j]))) {
18448
18449 /*
18450 * Note that the namespace bindings are already
18451 * in a string dict.
18452 */
18453 return (inode->nsBindings[j+1]);
18454 }
18455 }
18456 }
18457 }
18458 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018459#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018460 } else if (vctxt->reader != NULL) {
18461 xmlChar *nsName;
18462
18463 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18464 if (nsName != NULL) {
18465 const xmlChar *ret;
18466
18467 VAL_CREATE_DICT;
18468 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18469 xmlFree(nsName);
18470 return (ret);
18471 } else
18472 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018473#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474 } else {
18475 xmlNsPtr ns;
18476
18477 if ((vctxt->inode->node == NULL) ||
18478 (vctxt->inode->node->doc == NULL)) {
18479 VERROR_INT("xmlSchemaLookupNamespace",
18480 "no node or node's doc avaliable");
18481 return (NULL);
18482 }
18483 ns = xmlSearchNs(vctxt->inode->node->doc,
18484 vctxt->inode->node, prefix);
18485 if (ns != NULL)
18486 return (ns->href);
18487 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018488 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018489}
18490
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018491/*
18492* This one works on the schema of the validation context.
18493*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018494static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018495xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18496 xmlSchemaPtr schema,
18497 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018498 const xmlChar *value,
18499 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018500 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018501{
18502 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018503
18504 if (vctxt && (vctxt->schema == NULL)) {
18505 VERROR_INT("xmlSchemaValidateNotation",
18506 "a schema is needed on the validation context");
18507 return (-1);
18508 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018509 ret = xmlValidateQName(value, 1);
18510 if (ret != 0)
18511 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018512 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018513 xmlChar *localName = NULL;
18514 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018515
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018516 localName = xmlSplitQName2(value, &prefix);
18517 if (prefix != NULL) {
18518 const xmlChar *nsName = NULL;
18519
18520 if (vctxt != NULL)
18521 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18522 else if (node != NULL) {
18523 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18524 if (ns != NULL)
18525 nsName = ns->href;
18526 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018527 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018528 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018529 return (1);
18530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018531 if (nsName == NULL) {
18532 xmlFree(prefix);
18533 xmlFree(localName);
18534 return (1);
18535 }
18536 if (xmlHashLookup2(schema->notaDecl, localName,
18537 nsName) != NULL) {
18538 if (valNeeded && (val != NULL)) {
18539 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18540 BAD_CAST xmlStrdup(nsName));
18541 if (*val == NULL)
18542 ret = -1;
18543 }
18544 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018545 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018546 xmlFree(prefix);
18547 xmlFree(localName);
18548 } else {
18549 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18550 if (valNeeded && (val != NULL)) {
18551 (*val) = xmlSchemaNewNOTATIONValue(
18552 BAD_CAST xmlStrdup(value), NULL);
18553 if (*val == NULL)
18554 ret = -1;
18555 }
18556 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018557 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018558 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018559 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018560 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018561}
18562
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018563/************************************************************************
18564 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018565 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018566 * *
18567 ************************************************************************/
18568
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018569/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018570 * xmlSchemaAugmentIDC:
18571 * @idcDef: the IDC definition
18572 *
18573 * Creates an augmented IDC definition item.
18574 *
18575 * Returns the item, or NULL on internal errors.
18576 */
18577static void
18578xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18579 xmlSchemaValidCtxtPtr vctxt)
18580{
18581 xmlSchemaIDCAugPtr aidc;
18582
18583 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18584 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018585 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018586 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18587 NULL);
18588 return;
18589 }
18590 aidc->bubbleDepth = -1;
18591 aidc->def = idcDef;
18592 aidc->next = NULL;
18593 if (vctxt->aidcs == NULL)
18594 vctxt->aidcs = aidc;
18595 else {
18596 aidc->next = vctxt->aidcs;
18597 vctxt->aidcs = aidc;
18598 }
18599}
18600
18601/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018602 * xmlSchemaIDCNewBinding:
18603 * @idcDef: the IDC definition of this binding
18604 *
18605 * Creates a new IDC binding.
18606 *
18607 * Returns the new binding in case of succeeded, NULL on internal errors.
18608 */
18609static xmlSchemaPSVIIDCBindingPtr
18610xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18611{
18612 xmlSchemaPSVIIDCBindingPtr ret;
18613
18614 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18615 sizeof(xmlSchemaPSVIIDCBinding));
18616 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018617 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018618 "allocating a PSVI IDC binding item", NULL);
18619 return (NULL);
18620 }
18621 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18622 ret->definition = idcDef;
18623 return (ret);
18624}
18625
18626/**
18627 * xmlSchemaIDCStoreNodeTableItem:
18628 * @vctxt: the WXS validation context
18629 * @item: the IDC node table item
18630 *
18631 * The validation context is used to store an IDC node table items.
18632 * They are stored to avoid copying them if IDC node-tables are merged
18633 * with corresponding parent IDC node-tables (bubbling).
18634 *
18635 * Returns 0 if succeeded, -1 on internal errors.
18636 */
18637static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018638xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018639 xmlSchemaPSVIIDCNodePtr item)
18640{
18641 /*
18642 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018643 */
18644 if (vctxt->idcNodes == NULL) {
18645 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018646 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18647 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018648 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018649 "allocating the IDC node table item list", NULL);
18650 return (-1);
18651 }
18652 vctxt->sizeIdcNodes = 20;
18653 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18654 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018655 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18656 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018657 sizeof(xmlSchemaPSVIIDCNodePtr));
18658 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018659 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018660 "re-allocating the IDC node table item list", NULL);
18661 return (-1);
18662 }
18663 }
18664 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018665
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018666 return (0);
18667}
18668
18669/**
18670 * xmlSchemaIDCStoreKey:
18671 * @vctxt: the WXS validation context
18672 * @item: the IDC key
18673 *
18674 * The validation context is used to store an IDC key.
18675 *
18676 * Returns 0 if succeeded, -1 on internal errors.
18677 */
18678static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018679xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018680 xmlSchemaPSVIIDCKeyPtr key)
18681{
18682 /*
18683 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018684 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018685 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018686 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018687 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18688 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018689 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018690 "allocating the IDC key storage list", NULL);
18691 return (-1);
18692 }
18693 vctxt->sizeIdcKeys = 40;
18694 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18695 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018696 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18697 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018698 sizeof(xmlSchemaPSVIIDCKeyPtr));
18699 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018700 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018701 "re-allocating the IDC key storage list", NULL);
18702 return (-1);
18703 }
18704 }
18705 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018706
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018707 return (0);
18708}
18709
18710/**
18711 * xmlSchemaIDCAppendNodeTableItem:
18712 * @bind: the IDC binding
18713 * @ntItem: the node-table item
18714 *
18715 * Appends the IDC node-table item to the binding.
18716 *
18717 * Returns 0 on success and -1 on internal errors.
18718 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018719static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018720xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18721 xmlSchemaPSVIIDCNodePtr ntItem)
18722{
18723 if (bind->nodeTable == NULL) {
18724 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018725 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018726 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18727 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018728 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018729 "allocating an array of IDC node-table items", NULL);
18730 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018731 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018732 } else if (bind->sizeNodes <= bind->nbNodes) {
18733 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018734 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18735 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018736 sizeof(xmlSchemaPSVIIDCNodePtr));
18737 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018738 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018739 "re-allocating an array of IDC node-table items", NULL);
18740 return(-1);
18741 }
18742 }
18743 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018744 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018745}
18746
18747/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018748 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018749 * @vctxt: the WXS validation context
18750 * @matcher: the IDC matcher
18751 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018752 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018753 * of the given matcher. If none found, a new one is created
18754 * and added to the IDC table.
18755 *
18756 * Returns an IDC binding or NULL on internal errors.
18757 */
18758static xmlSchemaPSVIIDCBindingPtr
18759xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18760 xmlSchemaIDCMatcherPtr matcher)
18761{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018762 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018763
18764 info = vctxt->elemInfos[matcher->depth];
18765
18766 if (info->idcTable == NULL) {
18767 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18768 if (info->idcTable == NULL)
18769 return (NULL);
18770 return(info->idcTable);
18771 } else {
18772 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018773
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018774 bind = info->idcTable;
18775 do {
18776 if (bind->definition == matcher->aidc->def)
18777 return(bind);
18778 if (bind->next == NULL) {
18779 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18780 if (bind->next == NULL)
18781 return (NULL);
18782 return(bind->next);
18783 }
18784 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018785 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018786 }
18787 return (NULL);
18788}
18789
18790/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018791 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018792 * @key: the IDC key
18793 *
18794 * Frees an IDC key together with its compiled value.
18795 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018796static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018797xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18798{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018799 if (key->val != NULL)
18800 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018801 xmlFree(key);
18802}
18803
18804/**
18805 * xmlSchemaIDCFreeBinding:
18806 *
18807 * Frees an IDC binding. Note that the node table-items
18808 * are not freed.
18809 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018810static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018811xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18812{
18813 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018814 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18815 int i;
18816 /*
18817 * Node-table items for keyrefs are not stored globally
18818 * to the validation context, since they are not bubbled.
18819 * We need to free them here.
18820 */
18821 for (i = 0; i < bind->nbNodes; i++) {
18822 xmlFree(bind->nodeTable[i]->keys);
18823 xmlFree(bind->nodeTable[i]);
18824 }
18825 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018826 xmlFree(bind->nodeTable);
18827 }
18828 xmlFree(bind);
18829}
18830
18831/**
18832 * xmlSchemaIDCFreeIDCTable:
18833 * @bind: the first IDC binding in the list
18834 *
18835 * Frees an IDC table, i.e. all the IDC bindings in the list.
18836 */
18837static void
18838xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18839{
18840 xmlSchemaPSVIIDCBindingPtr prev;
18841
18842 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018843 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018844 bind = bind->next;
18845 xmlSchemaIDCFreeBinding(prev);
18846 }
18847}
18848
18849/**
18850 * xmlSchemaIDCFreeMatcherList:
18851 * @matcher: the first IDC matcher in the list
18852 *
18853 * Frees a list of IDC matchers.
18854 */
18855static void
18856xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18857{
18858 xmlSchemaIDCMatcherPtr next;
18859
18860 while (matcher != NULL) {
18861 next = matcher->next;
18862 if (matcher->keySeqs != NULL) {
18863 int i;
18864 for (i = 0; i < matcher->sizeKeySeqs; i++)
18865 if (matcher->keySeqs[i] != NULL)
18866 xmlFree(matcher->keySeqs[i]);
18867 xmlFree(matcher->keySeqs);
18868 }
18869 xmlFree(matcher);
18870 matcher = next;
18871 }
18872}
18873
18874/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018875 * xmlSchemaIDCAddStateObject:
18876 * @vctxt: the WXS validation context
18877 * @matcher: the IDC matcher
18878 * @sel: the XPath information
18879 * @parent: the parent "selector" state object if any
18880 * @type: "selector" or "field"
18881 *
18882 * Creates/reuses and activates state objects for the given
18883 * XPath information; if the XPath expression consists of unions,
18884 * multiple state objects are created for every unioned expression.
18885 *
18886 * Returns 0 on success and -1 on internal errors.
18887 */
18888static int
18889xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18890 xmlSchemaIDCMatcherPtr matcher,
18891 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018892 int type)
18893{
18894 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018895
18896 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018897 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018898 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018899 if (vctxt->xpathStatePool != NULL) {
18900 sto = vctxt->xpathStatePool;
18901 vctxt->xpathStatePool = sto->next;
18902 sto->next = NULL;
18903 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018904 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018905 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018906 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018907 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18908 if (sto == NULL) {
18909 xmlSchemaVErrMemory(NULL,
18910 "allocating an IDC state object", NULL);
18911 return (-1);
18912 }
18913 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18914 }
18915 /*
18916 * Add to global list.
18917 */
18918 if (vctxt->xpathStates != NULL)
18919 sto->next = vctxt->xpathStates;
18920 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018921
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018922 /*
18923 * Free the old xpath validation context.
18924 */
18925 if (sto->xpathCtxt != NULL)
18926 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18927
18928 /*
18929 * Create a new XPath (pattern) validation context.
18930 */
18931 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18932 (xmlPatternPtr) sel->xpathComp);
18933 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018934 VERROR_INT("xmlSchemaIDCAddStateObject",
18935 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018936 return (-1);
18937 }
18938 sto->type = type;
18939 sto->depth = vctxt->depth;
18940 sto->matcher = matcher;
18941 sto->sel = sel;
18942 sto->nbHistory = 0;
18943
18944#if DEBUG_IDC
18945 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18946 sto->sel->xpath);
18947#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018948 return (0);
18949}
18950
18951/**
18952 * xmlSchemaXPathEvaluate:
18953 * @vctxt: the WXS validation context
18954 * @nodeType: the nodeType of the current node
18955 *
18956 * Evaluates all active XPath state objects.
18957 *
18958 * Returns the number of IC "field" state objects which resolved to
18959 * this node, 0 if none resolved and -1 on internal errors.
18960 */
18961static int
18962xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018963 xmlElementType nodeType)
18964{
18965 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018966 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018967
18968 if (vctxt->xpathStates == NULL)
18969 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018970
18971 if (nodeType == XML_ATTRIBUTE_NODE)
18972 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018973#if DEBUG_IDC
18974 {
18975 xmlChar *str = NULL;
18976 xmlGenericError(xmlGenericErrorContext,
18977 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018978 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18979 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018980 FREE_AND_NULL(str)
18981 }
18982#endif
18983 /*
18984 * Process all active XPath state objects.
18985 */
18986 first = vctxt->xpathStates;
18987 sto = first;
18988 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018989#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018990 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018991 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18992 sto->matcher->aidc->def->name, sto->sel->xpath);
18993 else
18994 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18995 sto->matcher->aidc->def->name, sto->sel->xpath);
18996#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018997 if (nodeType == XML_ELEMENT_NODE)
18998 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018999 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019000 else
19001 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019002 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019003
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019004 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019005 VERROR_INT("xmlSchemaXPathEvaluate",
19006 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019007 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019008 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019009 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019010 goto next_sto;
19011 /*
19012 * Full match.
19013 */
19014#if DEBUG_IDC
19015 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019016 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019017#endif
19018 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019019 * Register a match in the state object history.
19020 */
19021 if (sto->history == NULL) {
19022 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19023 if (sto->history == NULL) {
19024 xmlSchemaVErrMemory(NULL,
19025 "allocating the state object history", NULL);
19026 return(-1);
19027 }
19028 sto->sizeHistory = 10;
19029 } else if (sto->sizeHistory <= sto->nbHistory) {
19030 sto->sizeHistory *= 2;
19031 sto->history = (int *) xmlRealloc(sto->history,
19032 sto->sizeHistory * sizeof(int));
19033 if (sto->history == NULL) {
19034 xmlSchemaVErrMemory(NULL,
19035 "re-allocating the state object history", NULL);
19036 return(-1);
19037 }
19038 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019039 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019040
19041#ifdef DEBUG_IDC
19042 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19043 vctxt->depth);
19044#endif
19045
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019046 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19047 xmlSchemaIDCSelectPtr sel;
19048 /*
19049 * Activate state objects for the IDC fields of
19050 * the IDC selector.
19051 */
19052#if DEBUG_IDC
19053 xmlGenericError(xmlGenericErrorContext, "IDC: "
19054 "activating field states\n");
19055#endif
19056 sel = sto->matcher->aidc->def->fields;
19057 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019058 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19059 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19060 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019061 sel = sel->next;
19062 }
19063 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19064 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019065 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019066 */
19067#if DEBUG_IDC
19068 xmlGenericError(xmlGenericErrorContext,
19069 "IDC: key found\n");
19070#endif
19071 /*
19072 * Notify that the character value of this node is
19073 * needed.
19074 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019075 if (resolved == 0) {
19076 if ((vctxt->inode->flags &
19077 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19078 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19079 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019080 resolved++;
19081 }
19082next_sto:
19083 if (sto->next == NULL) {
19084 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019085 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019086 */
19087 head = first;
19088 sto = vctxt->xpathStates;
19089 } else
19090 sto = sto->next;
19091 }
19092 return (resolved);
19093}
19094
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019095static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019096xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019097 xmlChar **buf,
19098 xmlSchemaPSVIIDCKeyPtr *seq,
19099 int count)
19100{
19101 int i, res;
19102 const xmlChar *value = NULL;
19103
19104 *buf = xmlStrdup(BAD_CAST "[");
19105 for (i = 0; i < count; i++) {
19106 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019107 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19108 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019109 if (res == 0)
19110 *buf = xmlStrcat(*buf, value);
19111 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019112 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19113 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019114 *buf = xmlStrcat(*buf, BAD_CAST "???");
19115 }
19116 if (i < count -1)
19117 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19118 else
19119 *buf = xmlStrcat(*buf, BAD_CAST "'");
19120 if (value != NULL) {
19121 xmlFree((xmlChar *) value);
19122 value = NULL;
19123 }
19124 }
19125 *buf = xmlStrcat(*buf, BAD_CAST "]");
19126
19127 return (BAD_CAST *buf);
19128}
19129
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019130/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019131 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019132 * @vctxt: the WXS validation context
19133 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019134 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019135 *
19136 * Processes and pops the history items of the IDC state objects.
19137 * IDC key-sequences are validated/created on IDC bindings.
19138 *
19139 * Returns 0 on success and -1 on internal errors.
19140 */
19141static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019142xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019143 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019144{
19145 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019146 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019147 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019148 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019149
19150 if (vctxt->xpathStates == NULL)
19151 return (0);
19152 sto = vctxt->xpathStates;
19153
19154#if DEBUG_IDC
19155 {
19156 xmlChar *str = NULL;
19157 xmlGenericError(xmlGenericErrorContext,
19158 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019159 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19160 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019161 FREE_AND_NULL(str)
19162 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019163#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019164 /*
19165 * Evaluate the state objects.
19166 */
19167 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019168 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19169 if (res == -1) {
19170 VERROR_INT("xmlSchemaXPathProcessHistory",
19171 "calling xmlStreamPop()");
19172 return (-1);
19173 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019174#if DEBUG_IDC
19175 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19176 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019177#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019178 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019179 goto deregister_check;
19180
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019181 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019182
19183 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019184 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019185 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019186 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019187 sto = sto->next;
19188 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019189 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019190 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19191 if (! IS_SIMPLE_TYPE(type)) {
19192 /*
19193 * Not qualified if the field resolves to a node of non
19194 * simple type.
19195 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019196 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19197 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019198 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19199 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019200 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019201
19202 sto->nbHistory--;
19203 goto deregister_check;
19204 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019205 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019206 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019207 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019208 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019209 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019210 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019211 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19212 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019213 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019214 sto->nbHistory--;
19215 goto deregister_check;
19216 } else {
19217 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19218 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019219 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019220
19221 /*
19222 * The key will be anchored on the matcher's list of
19223 * key-sequences. The position in this list is determined
19224 * by the target node's depth relative to the matcher's
19225 * depth of creation (i.e. the depth of the scope element).
19226 */
19227 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019228 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019229
19230 /*
19231 * Create/grow the array of key-sequences.
19232 */
19233 if (matcher->keySeqs == NULL) {
19234 if (pos > 9)
19235 matcher->sizeKeySeqs = pos * 2;
19236 else
19237 matcher->sizeKeySeqs = 10;
19238 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19239 xmlMalloc(matcher->sizeKeySeqs *
19240 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19241 if (matcher->keySeqs == NULL) {
19242 xmlSchemaVErrMemory(NULL,
19243 "allocating an array of key-sequences",
19244 NULL);
19245 return(-1);
19246 }
19247 memset(matcher->keySeqs, 0,
19248 matcher->sizeKeySeqs *
19249 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19250 } else if (pos >= matcher->sizeKeySeqs) {
19251 int i = matcher->sizeKeySeqs;
19252
19253 matcher->sizeKeySeqs *= 2;
19254 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19255 xmlRealloc(matcher->keySeqs,
19256 matcher->sizeKeySeqs *
19257 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019258 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019259 xmlSchemaVErrMemory(NULL,
19260 "reallocating an array of key-sequences",
19261 NULL);
19262 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019263 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019264 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019265 * The array needs to be NULLed.
19266 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019267 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019268 for (; i < matcher->sizeKeySeqs; i++)
19269 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019270 }
19271
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019272 /*
19273 * Get/create the key-sequence.
19274 */
19275 keySeq = matcher->keySeqs[pos];
19276 if (keySeq == NULL) {
19277 goto create_sequence;
19278 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019279 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019280 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019281 * cvc-identity-constraint:
19282 * 3 For each node in the ·target node set· all
19283 * of the {fields}, with that node as the context
19284 * node, evaluate to either an empty node-set or
19285 * a node-set with exactly one member, which must
19286 * have a simple type.
19287 *
19288 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019290 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19291 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019292 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019293 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019294 "with more than one member",
19295 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019296 sto->nbHistory--;
19297 goto deregister_check;
19298 } else {
19299 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019300 }
19301 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019302
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019303create_sequence:
19304 /*
19305 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019306 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019307 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19308 matcher->aidc->def->nbFields *
19309 sizeof(xmlSchemaPSVIIDCKeyPtr));
19310 if (keySeq == NULL) {
19311 xmlSchemaVErrMemory(NULL,
19312 "allocating an IDC key-sequence", NULL);
19313 return(-1);
19314 }
19315 memset(keySeq, 0, matcher->aidc->def->nbFields *
19316 sizeof(xmlSchemaPSVIIDCKeyPtr));
19317 matcher->keySeqs[pos] = keySeq;
19318create_key:
19319 /*
19320 * Created a key once per node only.
19321 */
19322 if (key == NULL) {
19323 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19324 sizeof(xmlSchemaPSVIIDCKey));
19325 if (key == NULL) {
19326 xmlSchemaVErrMemory(NULL,
19327 "allocating a IDC key", NULL);
19328 xmlFree(keySeq);
19329 matcher->keySeqs[pos] = NULL;
19330 return(-1);
19331 }
19332 /*
19333 * Consume the compiled value.
19334 */
19335 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019336 key->val = vctxt->inode->val;
19337 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019338 /*
19339 * Store the key in a global list.
19340 */
19341 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19342 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019343 return (-1);
19344 }
19345 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019346 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019347 }
19348 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019349
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019350 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19351 xmlSchemaPSVIIDCBindingPtr bind;
19352 xmlSchemaPSVIIDCNodePtr ntItem;
19353 xmlSchemaIDCMatcherPtr matcher;
19354 xmlSchemaIDCPtr idc;
19355 int pos, i, j, nbKeys;
19356 /*
19357 * Here we have the following scenario:
19358 * An IDC 'selector' state object resolved to a target node,
19359 * during the time this target node was in the
19360 * ancestor-or-self axis, the 'field' state object(s) looked
19361 * out for matching nodes to create a key-sequence for this
19362 * target node. Now we are back to this target node and need
19363 * to put the key-sequence, together with the target node
19364 * itself, into the node-table of the corresponding IDC
19365 * binding.
19366 */
19367 matcher = sto->matcher;
19368 idc = matcher->aidc->def;
19369 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019370 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019371 /*
19372 * Check if the matcher has any key-sequences at all, plus
19373 * if it has a key-sequence for the current target node.
19374 */
19375 if ((matcher->keySeqs == NULL) ||
19376 (matcher->sizeKeySeqs <= pos)) {
19377 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19378 goto selector_key_error;
19379 else
19380 goto selector_leave;
19381 }
19382
19383 keySeq = &(matcher->keySeqs[pos]);
19384 if (*keySeq == NULL) {
19385 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19386 goto selector_key_error;
19387 else
19388 goto selector_leave;
19389 }
19390
19391 for (i = 0; i < nbKeys; i++) {
19392 if ((*keySeq)[i] == NULL) {
19393 /*
19394 * Not qualified, if not all fields did resolve.
19395 */
19396 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19397 /*
19398 * All fields of a "key" IDC must resolve.
19399 */
19400 goto selector_key_error;
19401 }
19402 goto selector_leave;
19403 }
19404 }
19405 /*
19406 * All fields did resolve.
19407 */
19408
19409 /*
19410 * 4.1 If the {identity-constraint category} is unique(/key),
19411 * then no two members of the ·qualified node set· have
19412 * ·key-sequences· whose members are pairwise equal, as
19413 * defined by Equal in [XML Schemas: Datatypes].
19414 *
19415 * Get the IDC binding from the matcher and check for
19416 * duplicate key-sequences.
19417 */
19418 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19419 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19420 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019421 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019422
19423 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019424 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019425 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019426 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019427 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019428 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019429 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019430 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019431 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019432 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019433 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019434 if (res == -1) {
19435 return (-1);
19436 } else if (res == 0)
19437 break;
19438 }
19439 if (res == 1) {
19440 /*
19441 * Duplicate found.
19442 */
19443 break;
19444 }
19445 i++;
19446 } while (i < bind->nbNodes);
19447 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019448 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019449 /*
19450 * TODO: Try to report the key-sequence.
19451 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019452 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19453 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019454 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019455 "Duplicate key-sequence %s",
19456 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19457 (*keySeq), nbKeys), NULL);
19458 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019459 goto selector_leave;
19460 }
19461 }
19462 /*
19463 * Add a node-table item to the IDC binding.
19464 */
19465 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19466 sizeof(xmlSchemaPSVIIDCNode));
19467 if (ntItem == NULL) {
19468 xmlSchemaVErrMemory(NULL,
19469 "allocating an IDC node-table item", NULL);
19470 xmlFree(*keySeq);
19471 *keySeq = NULL;
19472 return(-1);
19473 }
19474 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19475
19476 /*
19477 * Store the node-table item on global list.
19478 */
19479 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19480 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19481 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019482 xmlFree(*keySeq);
19483 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019484 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019485 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019486 }
19487 /*
19488 * Init the node-table item. Consume the key-sequence.
19489 */
19490 ntItem->node = vctxt->node;
19491 ntItem->keys = *keySeq;
19492 *keySeq = NULL;
19493 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19494 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19495 /*
19496 * Free the item, since keyref items won't be
19497 * put on a global list.
19498 */
19499 xmlFree(ntItem->keys);
19500 xmlFree(ntItem);
19501 }
19502 return (-1);
19503 }
19504
19505 goto selector_leave;
19506selector_key_error:
19507 /*
19508 * 4.2.1 (KEY) The ·target node set· and the
19509 * ·qualified node set· are equal, that is, every
19510 * member of the ·target node set· is also a member
19511 * of the ·qualified node set· and vice versa.
19512 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019513 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19514 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019515selector_leave:
19516 /*
19517 * Free the key-sequence if not added to the IDC table.
19518 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019519 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019520 xmlFree(*keySeq);
19521 *keySeq = NULL;
19522 }
19523 } /* if selector */
19524
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019525 sto->nbHistory--;
19526
19527deregister_check:
19528 /*
19529 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019530 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019531 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019532#if DEBUG_IDC
19533 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19534 sto->sel->xpath);
19535#endif
19536 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019537 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019538 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019539 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019540 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019541 nextsto = sto->next;
19542 /*
19543 * Unlink from the list of active XPath state objects.
19544 */
19545 vctxt->xpathStates = sto->next;
19546 sto->next = vctxt->xpathStatePool;
19547 /*
19548 * Link it to the pool of reusable state objects.
19549 */
19550 vctxt->xpathStatePool = sto;
19551 sto = nextsto;
19552 } else
19553 sto = sto->next;
19554 } /* while (sto != NULL) */
19555 return (0);
19556}
19557
19558/**
19559 * xmlSchemaIDCRegisterMatchers:
19560 * @vctxt: the WXS validation context
19561 * @elemDecl: the element declaration
19562 *
19563 * Creates helper objects to evaluate IDC selectors/fields
19564 * successively.
19565 *
19566 * Returns 0 if OK and -1 on internal errors.
19567 */
19568static int
19569xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19570 xmlSchemaElementPtr elemDecl)
19571{
19572 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19573 xmlSchemaIDCPtr idc, refIdc;
19574 xmlSchemaIDCAugPtr aidc;
19575
19576 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19577 if (idc == NULL)
19578 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019579
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019580#if DEBUG_IDC
19581 {
19582 xmlChar *str = NULL;
19583 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019584 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019585 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19586 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019587 FREE_AND_NULL(str)
19588 }
19589#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019590 if (vctxt->inode->idcMatchers != NULL) {
19591 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19592 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019593 return (-1);
19594 }
19595 do {
19596 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19597 /*
19598 * Since IDCs bubbles are expensive we need to know the
19599 * depth at which the bubbles should stop; this will be
19600 * the depth of the top-most keyref IDC. If no keyref
19601 * references a key/unique IDC, the bubbleDepth will
19602 * be -1, indicating that no bubbles are needed.
19603 */
19604 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19605 if (refIdc != NULL) {
19606 /*
19607 * Lookup the augmented IDC.
19608 */
19609 aidc = vctxt->aidcs;
19610 while (aidc != NULL) {
19611 if (aidc->def == refIdc)
19612 break;
19613 aidc = aidc->next;
19614 }
19615 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019616 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019617 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019618 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019619 return (-1);
19620 }
19621 if ((aidc->bubbleDepth == -1) ||
19622 (vctxt->depth < aidc->bubbleDepth))
19623 aidc->bubbleDepth = vctxt->depth;
19624 }
19625 }
19626 /*
19627 * Lookup the augmented IDC item for the IDC definition.
19628 */
19629 aidc = vctxt->aidcs;
19630 while (aidc != NULL) {
19631 if (aidc->def == idc)
19632 break;
19633 aidc = aidc->next;
19634 }
19635 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019636 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19637 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019638 return (-1);
19639 }
19640 /*
19641 * Create an IDC matcher for every IDC definition.
19642 */
19643 matcher = (xmlSchemaIDCMatcherPtr)
19644 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19645 if (matcher == NULL) {
19646 xmlSchemaVErrMemory(vctxt,
19647 "allocating an IDC matcher", NULL);
19648 return (-1);
19649 }
19650 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19651 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019652 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019653 else
19654 last->next = matcher;
19655 last = matcher;
19656
19657 matcher->type = IDC_MATCHER;
19658 matcher->depth = vctxt->depth;
19659 matcher->aidc = aidc;
19660#if DEBUG_IDC
19661 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19662#endif
19663 /*
19664 * Init the automaton state object.
19665 */
19666 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019667 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019668 return (-1);
19669
19670 idc = idc->next;
19671 } while (idc != NULL);
19672 return (0);
19673}
19674
19675/**
19676 * xmlSchemaBubbleIDCNodeTables:
19677 * @depth: the current tree depth
19678 *
19679 * Merges IDC bindings of an element at @depth into the corresponding IDC
19680 * bindings of its parent element. If a duplicate note-table entry is found,
19681 * both, the parent node-table entry and child entry are discarded from the
19682 * node-table of the parent.
19683 *
19684 * Returns 0 if OK and -1 on internal errors.
19685 */
19686static int
19687xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19688{
19689 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019690 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19691 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019692 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19693 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019694 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019695 int duplTop;
19696
19697 /*
19698 * The node table has the following sections:
19699 *
19700 * O --> old node-table entries (first)
19701 * O
19702 * + --> new node-table entries
19703 * +
19704 * % --> new duplicate node-table entries
19705 * %
19706 * # --> old duplicate node-table entries
19707 * # (last)
19708 *
19709 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019710 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019711 if (bind == NULL) {
19712 /* Fine, no table, no bubbles. */
19713 return (0);
19714 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019715
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019716 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19717 /*
19718 * Walk all bindings; create new or add to existing bindings.
19719 * Remove duplicate key-sequences.
19720 */
19721start_binding:
19722 while (bind != NULL) {
19723 /*
19724 * Skip keyref IDCs.
19725 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019726 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19727 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019728 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019729 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019730 /*
19731 * Check if the key/unique IDC table needs to be bubbled.
19732 */
19733 aidc = vctxt->aidcs;
19734 do {
19735 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019736 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019737 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019738 bind = bind->next;
19739 goto start_binding;
19740 }
19741 break;
19742 }
19743 aidc = aidc->next;
19744 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019745
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019746 if (parTable != NULL)
19747 parBind = *parTable;
19748 while (parBind != NULL) {
19749 /*
19750 * Search a matching parent binding for the
19751 * IDC definition.
19752 */
19753 if (parBind->definition == bind->definition) {
19754
19755 /*
19756 * Compare every node-table entry of the child node,
19757 * i.e. the key-sequence within, ...
19758 */
19759 oldNum = parBind->nbNodes; /* Skip newly added items. */
19760 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019761 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019762
19763 for (i = 0; i < bind->nbNodes; i++) {
19764 node = bind->nodeTable[i];
19765 if (node == NULL)
19766 continue;
19767 /*
19768 * ...with every key-sequence of the parent node, already
19769 * evaluated to be a duplicate key-sequence.
19770 */
19771 if (parBind->nbDupls != 0) {
19772 j = bind->nbNodes + newDupls;
19773 while (j < duplTop) {
19774 parNode = parBind->nodeTable[j];
19775 for (k = 0; k < bind->definition->nbFields; k++) {
19776 key = node->keys[k];
19777 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019778 ret = xmlSchemaAreValuesEqual(key->val,
19779 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019780 if (ret == -1) {
19781 /* TODO: Internal error */
19782 return(-1);
19783 } else if (ret == 0)
19784 break;
19785
19786 }
19787 if (ret == 1)
19788 /* Duplicate found. */
19789 break;
19790 j++;
19791 }
19792 if (j != duplTop) {
19793 /* Duplicate found. */
19794 continue;
19795 }
19796 }
19797 /*
19798 * ... and with every key-sequence of the parent node.
19799 */
19800 j = 0;
19801 while (j < oldNum) {
19802 parNode = parBind->nodeTable[j];
19803 /*
19804 * Compare key by key.
19805 */
19806 for (k = 0; k < parBind->definition->nbFields; k++) {
19807 key = node->keys[k];
19808 parKey = parNode->keys[k];
19809
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019810 ret = xmlSchemaAreValuesEqual(key->val,
19811 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019812 if (ret == -1) {
19813 /* TODO: Internal error */
19814 } else if (ret == 0)
19815 break;
19816
19817 }
19818 if (ret == 1)
19819 /*
19820 * The key-sequences are equal.
19821 */
19822 break;
19823 j++;
19824 }
19825 if (j != oldNum) {
19826 /*
19827 * Handle duplicates.
19828 */
19829 newDupls++;
19830 oldNum--;
19831 parBind->nbNodes--;
19832 /*
19833 * Move last old item to pos of duplicate.
19834 */
19835 parBind->nodeTable[j] =
19836 parBind->nodeTable[oldNum];
19837
19838 if (parBind->nbNodes != oldNum) {
19839 /*
19840 * If new items exist, move last new item to
19841 * last of old items.
19842 */
19843 parBind->nodeTable[oldNum] =
19844 parBind->nodeTable[parBind->nbNodes];
19845 }
19846 /*
19847 * Move duplicate to last pos of new/old items.
19848 */
19849 parBind->nodeTable[parBind->nbNodes] = parNode;
19850
19851 } else {
19852 /*
19853 * Add the node-table entry (node and key-sequence) of
19854 * the child node to the node table of the parent node.
19855 */
19856 if (parBind->nodeTable == NULL) {
19857 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019858 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019859 if (parBind->nodeTable == NULL) {
19860 xmlSchemaVErrMemory(NULL,
19861 "allocating IDC list of node-table items", NULL);
19862 return(-1);
19863 }
19864 parBind->sizeNodes = 1;
19865 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019866 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019867 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19868 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19869 sizeof(xmlSchemaPSVIIDCNodePtr));
19870 if (parBind->nodeTable == NULL) {
19871 xmlSchemaVErrMemory(NULL,
19872 "re-allocating IDC list of node-table items", NULL);
19873 return(-1);
19874 }
19875 }
19876
19877 /*
19878 * Move first old duplicate to last position
19879 * of old duplicates +1.
19880 */
19881 if (parBind->nbDupls != 0) {
19882 parBind->nodeTable[duplTop] =
19883 parBind->nodeTable[parBind->nbNodes + newDupls];
19884 }
19885 /*
19886 * Move first new duplicate to last position of
19887 * new duplicates +1.
19888 */
19889 if (newDupls != 0) {
19890 parBind->nodeTable[parBind->nbNodes + newDupls] =
19891 parBind->nodeTable[parBind->nbNodes];
19892 }
19893 /*
19894 * Append the new node-table entry to the 'new node-table
19895 * entries' section.
19896 */
19897 parBind->nodeTable[parBind->nbNodes] = node;
19898 parBind->nbNodes++;
19899 duplTop++;
19900 }
19901 }
19902 parBind->nbDupls += newDupls;
19903 break;
19904 }
19905 if (parBind->next == NULL)
19906 lastParBind = parBind;
19907 parBind = parBind->next;
19908 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019909 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019910 /*
19911 * No binding for the IDC was found: create a new one and
19912 * copy all node-tables.
19913 */
19914 parBind = xmlSchemaIDCNewBinding(bind->definition);
19915 if (parBind == NULL)
19916 return(-1);
19917
19918 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19919 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19920 if (parBind->nodeTable == NULL) {
19921 xmlSchemaVErrMemory(NULL,
19922 "allocating an array of IDC node-table items", NULL);
19923 xmlSchemaIDCFreeBinding(parBind);
19924 return(-1);
19925 }
19926 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019927 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019928 memcpy(parBind->nodeTable, bind->nodeTable,
19929 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019930 if (*parTable == NULL)
19931 *parTable = parBind;
19932 else
19933 lastParBind->next = parBind;
19934 }
19935 bind = bind->next;
19936 }
19937 return (0);
19938}
19939
19940/**
19941 * xmlSchemaCheckCVCIDCKeyRef:
19942 * @vctxt: the WXS validation context
19943 * @elemDecl: the element declaration
19944 *
19945 * Check the cvc-idc-keyref constraints.
19946 */
19947static int
19948xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19949{
19950 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19951
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019952 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019953 /*
19954 * Find a keyref.
19955 */
19956 while (refbind != NULL) {
19957 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19958 int i, j, k, res;
19959 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19960 xmlSchemaPSVIIDCKeyPtr refKey, key;
19961
19962 /*
19963 * Find the referred key/unique.
19964 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019965 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019966 do {
19967 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19968 bind->definition)
19969 break;
19970 bind = bind->next;
19971 } while (bind != NULL);
19972
19973 /*
19974 * Search for a matching key-sequences.
19975 */
19976 for (i = 0; i < refbind->nbNodes; i++) {
19977 res = 0;
19978 if (bind != NULL) {
19979 refKeys = refbind->nodeTable[i]->keys;
19980 for (j = 0; j < bind->nbNodes; j++) {
19981 keys = bind->nodeTable[j]->keys;
19982 for (k = 0; k < bind->definition->nbFields; k++) {
19983 refKey = refKeys[k];
19984 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019985 res = xmlSchemaAreValuesEqual(key->val,
19986 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019987 if (res == 0)
19988 break;
19989 else if (res == -1) {
19990 return (-1);
19991 }
19992 }
19993 if (res == 1) {
19994 /*
19995 * Match found.
19996 */
19997 break;
19998 }
19999 }
20000 }
20001 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020002 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020003 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020004 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20005 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020006 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020007 "No match found for key-sequence %s of key "
20008 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020009 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020010 refbind->nodeTable[i]->keys,
20011 refbind->definition->nbFields),
20012 xmlSchemaFormatQName(&strB,
20013 refbind->definition->targetNamespace,
20014 refbind->definition->name));
20015 FREE_AND_NULL(str);
20016 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020017 }
20018 }
20019 }
20020 refbind = refbind->next;
20021 }
20022 return (0);
20023}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020024
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020025/************************************************************************
20026 * *
20027 * XML Reader validation code *
20028 * *
20029 ************************************************************************/
20030
20031static xmlSchemaAttrInfoPtr
20032xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020033{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020034 xmlSchemaAttrInfoPtr iattr;
20035 /*
20036 * Grow/create list of attribute infos.
20037 */
20038 if (vctxt->attrInfos == NULL) {
20039 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20040 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20041 vctxt->sizeAttrInfos = 1;
20042 if (vctxt->attrInfos == NULL) {
20043 xmlSchemaVErrMemory(vctxt,
20044 "allocating attribute info list", NULL);
20045 return (NULL);
20046 }
20047 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20048 vctxt->sizeAttrInfos++;
20049 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20050 xmlRealloc(vctxt->attrInfos,
20051 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20052 if (vctxt->attrInfos == NULL) {
20053 xmlSchemaVErrMemory(vctxt,
20054 "re-allocating attribute info list", NULL);
20055 return (NULL);
20056 }
20057 } else {
20058 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20059 if (iattr->localName != NULL) {
20060 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20061 "attr info not cleared");
20062 return (NULL);
20063 }
20064 iattr->nodeType = XML_ATTRIBUTE_NODE;
20065 return (iattr);
20066 }
20067 /*
20068 * Create an attribute info.
20069 */
20070 iattr = (xmlSchemaAttrInfoPtr)
20071 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20072 if (iattr == NULL) {
20073 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20074 return (NULL);
20075 }
20076 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20077 iattr->nodeType = XML_ATTRIBUTE_NODE;
20078 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20079
20080 return (iattr);
20081}
20082
20083static int
20084xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20085 xmlNodePtr attrNode,
20086 const xmlChar *localName,
20087 const xmlChar *nsName,
20088 int ownedNames,
20089 xmlChar *value,
20090 int ownedValue)
20091{
20092 xmlSchemaAttrInfoPtr attr;
20093
20094 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20095 if (attr == NULL) {
20096 VERROR_INT("xmlSchemaPushAttribute",
20097 "calling xmlSchemaGetFreshAttrInfo()");
20098 return (-1);
20099 }
20100 attr->node = attrNode;
20101 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20102 attr->localName = localName;
20103 attr->nsName = nsName;
20104 if (ownedNames)
20105 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20106 /*
20107 * Evaluate if it's an XSI attribute.
20108 */
20109 if (nsName != NULL) {
20110 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20111 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20112 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20113 }
20114 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20115 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20116 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20117 }
20118 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20119 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20120 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20121 }
20122 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20123 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20124 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20125 }
20126 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20127 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20128 }
20129 }
20130 attr->value = value;
20131 if (ownedValue)
20132 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20133 if (attr->metaType != 0)
20134 attr->state = XML_SCHEMAS_ATTR_META;
20135 return (0);
20136}
20137
20138static void
20139xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20140{
20141 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20142 FREE_AND_NULL(ielem->localName);
20143 FREE_AND_NULL(ielem->nsName);
20144 } else {
20145 ielem->localName = NULL;
20146 ielem->nsName = NULL;
20147 }
20148 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20149 FREE_AND_NULL(ielem->value);
20150 } else {
20151 ielem->value = NULL;
20152 }
20153 if (ielem->val != NULL) {
20154 xmlSchemaFreeValue(ielem->val);
20155 ielem->val = NULL;
20156 }
20157 if (ielem->idcMatchers != NULL) {
20158 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20159 ielem->idcMatchers = NULL;
20160 }
20161 if (ielem->idcTable != NULL) {
20162 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20163 ielem->idcTable = NULL;
20164 }
20165 if (ielem->regexCtxt != NULL) {
20166 xmlRegFreeExecCtxt(ielem->regexCtxt);
20167 ielem->regexCtxt = NULL;
20168 }
20169 if (ielem->nsBindings != NULL) {
20170 xmlFree((xmlChar **)ielem->nsBindings);
20171 ielem->nsBindings = NULL;
20172 ielem->nbNsBindings = 0;
20173 ielem->sizeNsBindings = 0;
20174 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020175}
20176
20177/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020178 * xmlSchemaGetFreshElemInfo:
20179 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020180 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020181 * Creates/reuses and initializes the element info item for
20182 * the currect tree depth.
20183 *
20184 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020185 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020186static xmlSchemaNodeInfoPtr
20187xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020188{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020189 xmlSchemaNodeInfoPtr info = NULL;
20190
20191 if (vctxt->depth > vctxt->sizeElemInfos) {
20192 VERROR_INT("xmlSchemaGetFreshElemInfo",
20193 "inconsistent depth encountered");
20194 return (NULL);
20195 }
20196 if (vctxt->elemInfos == NULL) {
20197 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20198 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20199 if (vctxt->elemInfos == NULL) {
20200 xmlSchemaVErrMemory(vctxt,
20201 "allocating the element info array", NULL);
20202 return (NULL);
20203 }
20204 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20205 vctxt->sizeElemInfos = 10;
20206 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20207 int i = vctxt->sizeElemInfos;
20208
20209 vctxt->sizeElemInfos *= 2;
20210 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20211 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20212 sizeof(xmlSchemaNodeInfoPtr));
20213 if (vctxt->elemInfos == NULL) {
20214 xmlSchemaVErrMemory(vctxt,
20215 "re-allocating the element info array", NULL);
20216 return (NULL);
20217 }
20218 /*
20219 * We need the new memory to be NULLed.
20220 * TODO: Use memset instead?
20221 */
20222 for (; i < vctxt->sizeElemInfos; i++)
20223 vctxt->elemInfos[i] = NULL;
20224 } else
20225 info = vctxt->elemInfos[vctxt->depth];
20226
20227 if (info == NULL) {
20228 info = (xmlSchemaNodeInfoPtr)
20229 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20230 if (info == NULL) {
20231 xmlSchemaVErrMemory(vctxt,
20232 "allocating an element info", NULL);
20233 return (NULL);
20234 }
20235 vctxt->elemInfos[vctxt->depth] = info;
20236 } else {
20237 if (info->localName != NULL) {
20238 VERROR_INT("xmlSchemaGetFreshElemInfo",
20239 "elem info has not been cleared");
20240 return (NULL);
20241 }
20242 }
20243 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20244 info->nodeType = XML_ELEMENT_NODE;
20245 info->depth = vctxt->depth;
20246
20247 return (info);
20248}
20249
20250#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20251#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20252#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20253
20254static int
20255xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20256 xmlNodePtr node,
20257 xmlSchemaTypePtr type,
20258 xmlSchemaValType valType,
20259 const xmlChar * value,
20260 xmlSchemaValPtr val,
20261 unsigned long length,
20262 int fireErrors)
20263{
20264 int ret, error = 0;
20265
20266 xmlSchemaTypePtr tmpType;
20267 xmlSchemaFacetLinkPtr facetLink;
20268 xmlSchemaFacetPtr facet;
20269 unsigned long len = 0;
20270 xmlSchemaWhitespaceValueType ws;
20271
20272 /*
20273 * In Libxml2, derived built-in types have currently no explicit facets.
20274 */
20275 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020276 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020277
20278 /*
20279 * NOTE: Do not jump away, if the facetSet of the given type is
20280 * empty: until now, "pattern" and "enumeration" facets of the
20281 * *base types* need to be checked as well.
20282 */
20283 if (type->facetSet == NULL)
20284 goto pattern_and_enum;
20285
20286 if (! VARIETY_ATOMIC(type)) {
20287 if (VARIETY_LIST(type))
20288 goto variety_list;
20289 else
20290 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020291 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020292 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020293 * Whitespace handling is only of importance for string-based
20294 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020295 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020296 tmpType = xmlSchemaGetPrimitiveType(type);
20297 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20298 IS_ANY_SIMPLE_TYPE(tmpType)) {
20299 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20300 } else
20301 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20302 /*
20303 * If the value was not computed (for string or
20304 * anySimpleType based types), then use the provided
20305 * type.
20306 */
20307 if (val == NULL)
20308 valType = valType;
20309 else
20310 valType = xmlSchemaGetValType(val);
20311
20312 ret = 0;
20313 for (facetLink = type->facetSet; facetLink != NULL;
20314 facetLink = facetLink->next) {
20315 /*
20316 * Skip the pattern "whiteSpace": it is used to
20317 * format the character content beforehand.
20318 */
20319 switch (facetLink->facet->type) {
20320 case XML_SCHEMA_FACET_WHITESPACE:
20321 case XML_SCHEMA_FACET_PATTERN:
20322 case XML_SCHEMA_FACET_ENUMERATION:
20323 continue;
20324 case XML_SCHEMA_FACET_LENGTH:
20325 case XML_SCHEMA_FACET_MINLENGTH:
20326 case XML_SCHEMA_FACET_MAXLENGTH:
20327 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20328 valType, value, val, &len, ws);
20329 break;
20330 default:
20331 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20332 valType, value, val, ws);
20333 break;
20334 }
20335 if (ret < 0) {
20336 AERROR_INT("xmlSchemaValidateFacets",
20337 "validating against a atomic type facet");
20338 return (-1);
20339 } else if (ret > 0) {
20340 if (fireErrors)
20341 xmlSchemaFacetErr(actxt, ret, node,
20342 value, len, type, facetLink->facet, NULL, NULL, NULL);
20343 else
20344 return (ret);
20345 if (error == 0)
20346 error = ret;
20347 }
20348 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020349 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020350
20351variety_list:
20352 if (! VARIETY_LIST(type))
20353 goto pattern_and_enum;
20354 /*
20355 * "length", "minLength" and "maxLength" of list types.
20356 */
20357 ret = 0;
20358 for (facetLink = type->facetSet; facetLink != NULL;
20359 facetLink = facetLink->next) {
20360
20361 switch (facetLink->facet->type) {
20362 case XML_SCHEMA_FACET_LENGTH:
20363 case XML_SCHEMA_FACET_MINLENGTH:
20364 case XML_SCHEMA_FACET_MAXLENGTH:
20365 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20366 value, length, NULL);
20367 break;
20368 default:
20369 continue;
20370 }
20371 if (ret < 0) {
20372 AERROR_INT("xmlSchemaValidateFacets",
20373 "validating against a list type facet");
20374 return (-1);
20375 } else if (ret > 0) {
20376 if (fireErrors)
20377 xmlSchemaFacetErr(actxt, ret, node,
20378 value, length, type, facetLink->facet, NULL, NULL, NULL);
20379 else
20380 return (ret);
20381 if (error == 0)
20382 error = ret;
20383 }
20384 ret = 0;
20385 }
20386
20387pattern_and_enum:
20388 if (error >= 0) {
20389 int found = 0;
20390 /*
20391 * Process enumerations. Facet values are in the value space
20392 * of the defining type's base type. This seems to be a bug in the
20393 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20394 * Only the first set of enumerations in the ancestor-or-self axis
20395 * is used for validation.
20396 */
20397 ret = 0;
20398 tmpType = type;
20399 do {
20400 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20401 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20402 continue;
20403 found = 1;
20404 ret = xmlSchemaAreValuesEqual(facet->val, val);
20405 if (ret == 1)
20406 break;
20407 else if (ret < 0) {
20408 AERROR_INT("xmlSchemaValidateFacets",
20409 "validating against an enumeration facet");
20410 return (-1);
20411 }
20412 }
20413 if (ret != 0)
20414 break;
20415 tmpType = tmpType->baseType;
20416 } while ((tmpType != NULL) &&
20417 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20418 if (found && (ret == 0)) {
20419 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20420 if (fireErrors) {
20421 xmlSchemaFacetErr(actxt, ret, node,
20422 value, 0, type, NULL, NULL, NULL, NULL);
20423 } else
20424 return (ret);
20425 if (error == 0)
20426 error = ret;
20427 }
20428 }
20429
20430 if (error >= 0) {
20431 int found;
20432 /*
20433 * Process patters. Pattern facets are ORed at type level
20434 * and ANDed if derived. Walk the base type axis.
20435 */
20436 tmpType = type;
20437 facet = NULL;
20438 do {
20439 found = 0;
20440 for (facetLink = tmpType->facetSet; facetLink != NULL;
20441 facetLink = facetLink->next) {
20442 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20443 continue;
20444 found = 1;
20445 /*
20446 * NOTE that for patterns, @value needs to be the
20447 * normalized vaule.
20448 */
20449 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20450 if (ret == 1)
20451 break;
20452 else if (ret < 0) {
20453 AERROR_INT("xmlSchemaValidateFacets",
20454 "validating against a pattern facet");
20455 return (-1);
20456 } else {
20457 /*
20458 * Save the last non-validating facet.
20459 */
20460 facet = facetLink->facet;
20461 }
20462 }
20463 if (found && (ret != 1)) {
20464 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20465 if (fireErrors) {
20466 xmlSchemaFacetErr(actxt, ret, node,
20467 value, 0, type, facet, NULL, NULL, NULL);
20468 } else
20469 return (ret);
20470 if (error == 0)
20471 error = ret;
20472 break;
20473 }
20474 tmpType = tmpType->baseType;
20475 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20476 }
20477
20478 return (error);
20479}
20480
20481static xmlChar *
20482xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20483 const xmlChar *value)
20484{
20485 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20486 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20487 return (xmlSchemaCollapseString(value));
20488 case XML_SCHEMA_WHITESPACE_REPLACE:
20489 return (xmlSchemaWhiteSpaceReplace(value));
20490 default:
20491 return (NULL);
20492 }
20493}
20494
20495static int
20496xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20497 const xmlChar *value,
20498 xmlSchemaValPtr *val,
20499 int valNeeded)
20500{
20501 int ret;
20502 const xmlChar *nsName;
20503 xmlChar *local, *prefix = NULL;
20504
20505 ret = xmlValidateQName(value, 1);
20506 if (ret != 0) {
20507 if (ret == -1) {
20508 VERROR_INT("xmlSchemaValidateQName",
20509 "calling xmlValidateQName()");
20510 return (-1);
20511 }
20512 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20513 }
20514 /*
20515 * NOTE: xmlSplitQName2 will always return a duplicated
20516 * strings.
20517 */
20518 local = xmlSplitQName2(value, &prefix);
20519 if (local == NULL)
20520 local = xmlStrdup(value);
20521 /*
20522 * OPTIMIZE TODO: Use flags for:
20523 * - is there any namespace binding?
20524 * - is there a default namespace?
20525 */
20526 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20527
20528 if (prefix != NULL) {
20529 xmlFree(prefix);
20530 /*
20531 * A namespace must be found if the prefix is
20532 * NOT NULL.
20533 */
20534 if (nsName == NULL) {
20535 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20536 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20537 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20538 "The QName value '%s' has no "
20539 "corresponding namespace declaration in "
20540 "scope", value, NULL);
20541 if (local != NULL)
20542 xmlFree(local);
20543 return (ret);
20544 }
20545 }
20546 if (valNeeded && val) {
20547 if (nsName != NULL)
20548 *val = xmlSchemaNewQNameValue(
20549 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20550 else
20551 *val = xmlSchemaNewQNameValue(NULL,
20552 BAD_CAST local);
20553 } else
20554 xmlFree(local);
20555 return (0);
20556}
20557
20558/*
20559* cvc-simple-type
20560*/
20561static int
20562xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20563 xmlNodePtr node,
20564 xmlSchemaTypePtr type,
20565 const xmlChar *value,
20566 xmlSchemaValPtr *retVal,
20567 int fireErrors,
20568 int normalize,
20569 int isNormalized)
20570{
20571 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20572 xmlSchemaValPtr val = NULL;
20573 xmlSchemaWhitespaceValueType ws;
20574 xmlChar *normValue = NULL;
20575
20576#define NORMALIZE(atype) \
20577 if ((! isNormalized) && \
20578 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20579 normValue = xmlSchemaNormalizeValue(atype, value); \
20580 if (normValue != NULL) \
20581 value = normValue; \
20582 isNormalized = 1; \
20583 }
20584
20585 if ((retVal != NULL) && (*retVal != NULL)) {
20586 xmlSchemaFreeValue(*retVal);
20587 *retVal = NULL;
20588 }
20589 /*
20590 * 3.14.4 Simple Type Definition Validation Rules
20591 * Validation Rule: String Valid
20592 */
20593 /*
20594 * 1 It is schema-valid with respect to that definition as defined
20595 * by Datatype Valid in [XML Schemas: Datatypes].
20596 */
20597 /*
20598 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20599 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20600 * the string must be a ·declared entity name·.
20601 */
20602 /*
20603 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20604 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20605 * then every whitespace-delimited substring of the string must be a ·declared
20606 * entity name·.
20607 */
20608 /*
20609 * 2.3 otherwise no further condition applies.
20610 */
20611 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20612 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020613 if (value == NULL)
20614 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020615 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20616 xmlSchemaTypePtr biType; /* The built-in type. */
20617 /*
20618 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20619 * a literal in the ·lexical space· of {base type definition}"
20620 */
20621 /*
20622 * Whitespace-normalize.
20623 */
20624 NORMALIZE(type);
20625 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20626 /*
20627 * Get the built-in type.
20628 */
20629 biType = type->baseType;
20630 while ((biType != NULL) &&
20631 (biType->type != XML_SCHEMA_TYPE_BASIC))
20632 biType = biType->baseType;
20633
20634 if (biType == NULL) {
20635 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20636 "could not get the built-in type");
20637 goto internal_error;
20638 }
20639 } else
20640 biType = type;
20641 /*
20642 * NOTATIONs need to be processed here, since they need
20643 * to lookup in the hashtable of NOTATION declarations of the schema.
20644 */
20645 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20646 switch (biType->builtInType) {
20647 case XML_SCHEMAS_NOTATION:
20648 ret = xmlSchemaValidateNotation(
20649 (xmlSchemaValidCtxtPtr) actxt,
20650 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20651 NULL, value, &val, valNeeded);
20652 break;
20653 case XML_SCHEMAS_QNAME:
20654 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20655 value, &val, valNeeded);
20656 break;
20657 default:
20658 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20659 if (valNeeded)
20660 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20661 value, &val, NULL);
20662 else
20663 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20664 value, NULL, NULL);
20665 break;
20666 }
20667 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20668 switch (biType->builtInType) {
20669 case XML_SCHEMAS_NOTATION:
20670 ret = xmlSchemaValidateNotation(NULL,
20671 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20672 value, &val, valNeeded);
20673 break;
20674 default:
20675 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20676 if (valNeeded)
20677 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20678 value, &val, node);
20679 else
20680 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20681 value, NULL, node);
20682 break;
20683 }
20684 } else {
20685 /*
20686 * Validation via a public API is not implemented yet.
20687 */
20688 TODO
20689 goto internal_error;
20690 }
20691 if (ret != 0) {
20692 if (ret < 0) {
20693 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20694 "validating against a built-in type");
20695 goto internal_error;
20696 }
20697 if (VARIETY_LIST(type))
20698 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20699 else
20700 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20701 }
20702 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20703 /*
20704 * Check facets.
20705 */
20706 ret = xmlSchemaValidateFacets(actxt, node, type,
20707 (xmlSchemaValType) biType->builtInType, value, val,
20708 0, fireErrors);
20709 if (ret != 0) {
20710 if (ret < 0) {
20711 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20712 "validating facets of atomic simple type");
20713 goto internal_error;
20714 }
20715 if (VARIETY_LIST(type))
20716 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20717 else
20718 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20719 }
20720 }
20721 if (fireErrors && (ret > 0))
20722 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20723 } else if (VARIETY_LIST(type)) {
20724
20725 xmlSchemaTypePtr itemType;
20726 const xmlChar *cur, *end;
20727 xmlChar *tmpValue = NULL;
20728 unsigned long len = 0;
20729 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20730 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20731 * of white space separated tokens, each of which ·match·es a literal
20732 * in the ·lexical space· of {item type definition}
20733 */
20734 /*
20735 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20736 * the list type has an enum or pattern facet.
20737 */
20738 NORMALIZE(type);
20739 /*
20740 * VAL TODO: Optimize validation of empty values.
20741 * VAL TODO: We do not have computed values for lists.
20742 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020743 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020744 cur = value;
20745 do {
20746 while (IS_BLANK_CH(*cur))
20747 cur++;
20748 end = cur;
20749 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20750 end++;
20751 if (end == cur)
20752 break;
20753 tmpValue = xmlStrndup(cur, end - cur);
20754 len++;
20755
20756 if (valNeeded)
20757 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20758 tmpValue, &curVal, fireErrors, 0, 1);
20759 else
20760 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20761 tmpValue, NULL, fireErrors, 0, 1);
20762 FREE_AND_NULL(tmpValue);
20763 if (curVal != NULL) {
20764 /*
20765 * Add to list of computed values.
20766 */
20767 if (val == NULL)
20768 val = curVal;
20769 else
20770 xmlSchemaValueAppend(prevVal, curVal);
20771 prevVal = curVal;
20772 curVal = NULL;
20773 }
20774 if (ret != 0) {
20775 if (ret < 0) {
20776 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20777 "validating an item of list simple type");
20778 goto internal_error;
20779 }
20780 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20781 break;
20782 }
20783 cur = end;
20784 } while (*cur != 0);
20785 FREE_AND_NULL(tmpValue);
20786 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20787 /*
20788 * Apply facets (pattern, enumeration).
20789 */
20790 ret = xmlSchemaValidateFacets(actxt, node, type,
20791 XML_SCHEMAS_UNKNOWN, value, val,
20792 len, fireErrors);
20793 if (ret != 0) {
20794 if (ret < 0) {
20795 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20796 "validating facets of list simple type");
20797 goto internal_error;
20798 }
20799 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20800 }
20801 }
20802 if (fireErrors && (ret > 0)) {
20803 /*
20804 * Report the normalized value.
20805 */
20806 normalize = 1;
20807 NORMALIZE(type);
20808 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20809 }
20810 } else if (VARIETY_UNION(type)) {
20811 xmlSchemaTypeLinkPtr memberLink;
20812 /*
20813 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20814 * not apply directly; however, the normalization behavior of ·union·
20815 * types is controlled by the value of whiteSpace on that one of the
20816 * ·memberTypes· against which the ·union· is successfully validated.
20817 *
20818 * This means that the value is normalized by the first validating
20819 * member type, then the facets of the union type are applied. This
20820 * needs changing of the value!
20821 */
20822
20823 /*
20824 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20825 * literal in the ·lexical space· of at least one member of
20826 * {member type definitions}
20827 */
20828 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20829 if (memberLink == NULL) {
20830 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20831 "union simple type has no member types");
20832 goto internal_error;
20833 }
20834 /*
20835 * Always normalize union type values, since we currently
20836 * cannot store the whitespace information with the value
20837 * itself; otherwise a later value-comparison would be
20838 * not possible.
20839 */
20840 while (memberLink != NULL) {
20841 if (valNeeded)
20842 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20843 memberLink->type, value, &val, 0, 1, 0);
20844 else
20845 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20846 memberLink->type, value, NULL, 0, 1, 0);
20847 if (ret <= 0)
20848 break;
20849 memberLink = memberLink->next;
20850 }
20851 if (ret != 0) {
20852 if (ret < 0) {
20853 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20854 "validating members of union simple type");
20855 goto internal_error;
20856 }
20857 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20858 }
20859 /*
20860 * Apply facets (pattern, enumeration).
20861 */
20862 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20863 /*
20864 * The normalization behavior of ·union· types is controlled by
20865 * the value of whiteSpace on that one of the ·memberTypes·
20866 * against which the ·union· is successfully validated.
20867 */
20868 NORMALIZE(memberLink->type);
20869 ret = xmlSchemaValidateFacets(actxt, node, type,
20870 XML_SCHEMAS_UNKNOWN, value, val,
20871 0, fireErrors);
20872 if (ret != 0) {
20873 if (ret < 0) {
20874 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20875 "validating facets of union simple type");
20876 goto internal_error;
20877 }
20878 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20879 }
20880 }
20881 if (fireErrors && (ret > 0))
20882 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20883 }
20884
20885 if (normValue != NULL)
20886 xmlFree(normValue);
20887 if (ret == 0) {
20888 if (retVal != NULL)
20889 *retVal = val;
20890 else if (val != NULL)
20891 xmlSchemaFreeValue(val);
20892 } else if (val != NULL)
20893 xmlSchemaFreeValue(val);
20894 return (ret);
20895internal_error:
20896 if (normValue != NULL)
20897 xmlFree(normValue);
20898 if (val != NULL)
20899 xmlSchemaFreeValue(val);
20900 return (-1);
20901}
20902
20903static int
20904xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20905 const xmlChar *value,
20906 const xmlChar **nsName,
20907 const xmlChar **localName)
20908{
20909 int ret = 0;
20910
20911 if ((nsName == NULL) || (localName == NULL))
20912 return (-1);
20913 *nsName = NULL;
20914 *localName = NULL;
20915
20916 ret = xmlValidateQName(value, 1);
20917 if (ret == -1)
20918 return (-1);
20919 if (ret > 0) {
20920 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20921 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20922 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20923 return (1);
20924 }
20925 {
20926 xmlChar *local = NULL;
20927 xmlChar *prefix;
20928
20929 /*
20930 * NOTE: xmlSplitQName2 will return a duplicated
20931 * string.
20932 */
20933 local = xmlSplitQName2(value, &prefix);
20934 VAL_CREATE_DICT;
20935 if (local == NULL)
20936 *localName = xmlDictLookup(vctxt->dict, value, -1);
20937 else {
20938 *localName = xmlDictLookup(vctxt->dict, local, -1);
20939 xmlFree(local);
20940 }
20941
20942 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20943
20944 if (prefix != NULL) {
20945 xmlFree(prefix);
20946 /*
20947 * A namespace must be found if the prefix is NOT NULL.
20948 */
20949 if (*nsName == NULL) {
20950 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20951 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20952 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20953 "The QName value '%s' has no "
20954 "corresponding namespace declaration in scope",
20955 value, NULL);
20956 return (2);
20957 }
20958 }
20959 }
20960 return (0);
20961}
20962
20963static int
20964xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20965 xmlSchemaAttrInfoPtr iattr,
20966 xmlSchemaTypePtr *localType,
20967 xmlSchemaElementPtr elemDecl)
20968{
20969 int ret = 0;
20970 /*
20971 * cvc-elt (3.3.4) : (4)
20972 * AND
20973 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20974 * (1.2.1.2.1) - (1.2.1.2.4)
20975 * Handle 'xsi:type'.
20976 */
20977 if (localType == NULL)
20978 return (-1);
20979 *localType = NULL;
20980 if (iattr == NULL)
20981 return (0);
20982 else {
20983 const xmlChar *nsName = NULL, *local = NULL;
20984 /*
20985 * TODO: We should report a *warning* that the type was overriden
20986 * by the instance.
20987 */
20988 ACTIVATE_ATTRIBUTE(iattr);
20989 /*
20990 * (cvc-elt) (3.3.4) : (4.1)
20991 * (cvc-assess-elt) (1.2.1.2.2)
20992 */
20993 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20994 &nsName, &local);
20995 if (ret != 0) {
20996 if (ret < 0) {
20997 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20998 "calling xmlSchemaQNameExpand() to validate the "
20999 "attribute 'xsi:type'");
21000 goto internal_error;
21001 }
21002 goto exit;
21003 }
21004 /*
21005 * (cvc-elt) (3.3.4) : (4.2)
21006 * (cvc-assess-elt) (1.2.1.2.3)
21007 */
21008 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
21009 if (*localType == NULL) {
21010 xmlChar *str = NULL;
21011
21012 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21013 XML_SCHEMAV_CVC_ELT_4_2, NULL,
21014 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21015 "The QName value '%s' of the xsi:type attribute does not "
21016 "resolve to a type definition",
21017 xmlSchemaFormatQName(&str, nsName, local), NULL);
21018 FREE_AND_NULL(str);
21019 ret = vctxt->err;
21020 goto exit;
21021 }
21022 if (elemDecl != NULL) {
21023 int set = 0;
21024
21025 /*
21026 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21027 * "The ·local type definition· must be validly
21028 * derived from the {type definition} given the union of
21029 * the {disallowed substitutions} and the {type definition}'s
21030 * {prohibited substitutions}, as defined in
21031 * Type Derivation OK (Complex) (§3.4.6)
21032 * (if it is a complex type definition),
21033 * or given {disallowed substitutions} as defined in Type
21034 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21035 * definition)."
21036 *
21037 * {disallowed substitutions}: the "block" on the element decl.
21038 * {prohibited substitutions}: the "block" on the type def.
21039 */
21040 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21041 (elemDecl->subtypes->flags &
21042 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21043 set |= SUBSET_EXTENSION;
21044
21045 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21046 (elemDecl->subtypes->flags &
21047 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21048 set |= SUBSET_RESTRICTION;
21049
21050 if (xmlSchemaCheckCOSDerivedOK(*localType,
21051 elemDecl->subtypes, set) != 0) {
21052 xmlChar *str = NULL;
21053
21054 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21055 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21056 "The type definition '%s', specified by xsi:type, is "
21057 "blocked or not validly derived from the type definition "
21058 "of the element declaration",
21059 xmlSchemaFormatQName(&str,
21060 (*localType)->targetNamespace,
21061 (*localType)->name),
21062 NULL);
21063 FREE_AND_NULL(str);
21064 ret = vctxt->err;
21065 *localType = NULL;
21066 }
21067 }
21068 }
21069exit:
21070 ACTIVATE_ELEM;
21071 return (ret);
21072internal_error:
21073 ACTIVATE_ELEM;
21074 return (-1);
21075}
21076
21077static int
21078xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21079{
21080 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21081 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21082
21083 /*
21084 * cvc-elt (3.3.4) : 1
21085 */
21086 if (elemDecl == NULL) {
21087 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21088 "No matching declaration available");
21089 return (vctxt->err);
21090 }
21091 /*
21092 * cvc-elt (3.3.4) : 2
21093 */
21094 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21095 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21096 "The element declaration is abstract");
21097 return (vctxt->err);
21098 }
21099 if (actualType == NULL) {
21100 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21101 "The type definition is absent");
21102 return (XML_SCHEMAV_CVC_TYPE_1);
21103 }
21104 if (vctxt->nbAttrInfos != 0) {
21105 int ret;
21106 xmlSchemaAttrInfoPtr iattr;
21107 /*
21108 * cvc-elt (3.3.4) : 3
21109 * Handle 'xsi:nil'.
21110 */
21111 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21112 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21113 if (iattr) {
21114 ACTIVATE_ATTRIBUTE(iattr);
21115 /*
21116 * Validate the value.
21117 */
21118 ret = xmlSchemaVCheckCVCSimpleType(
21119 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21120 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21121 iattr->value, &(iattr->val), 1, 0, 0);
21122 ACTIVATE_ELEM;
21123 if (ret < 0) {
21124 VERROR_INT("xmlSchemaValidateElemDecl",
21125 "calling xmlSchemaVCheckCVCSimpleType() to "
21126 "validate the attribute 'xsi:nil'");
21127 return (-1);
21128 }
21129 if (ret == 0) {
21130 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21131 /*
21132 * cvc-elt (3.3.4) : 3.1
21133 */
21134 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21135 "The element is not 'nillable'");
21136 /* Does not return an error on purpose. */
21137 } else {
21138 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21139 /*
21140 * cvc-elt (3.3.4) : 3.2.2
21141 */
21142 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21143 (elemDecl->value != NULL)) {
21144 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21145 "The element cannot be 'nilled' because "
21146 "there is a fixed value constraint defined "
21147 "for it");
21148 /* Does not return an error on purpose. */
21149 } else
21150 vctxt->inode->flags |=
21151 XML_SCHEMA_ELEM_INFO_NILLED;
21152 }
21153 }
21154 }
21155 }
21156 /*
21157 * cvc-elt (3.3.4) : 4
21158 * Handle 'xsi:type'.
21159 */
21160 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21161 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21162 if (iattr) {
21163 xmlSchemaTypePtr localType = NULL;
21164
21165 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21166 elemDecl);
21167 if (ret != 0) {
21168 if (ret == -1) {
21169 VERROR_INT("xmlSchemaValidateElemDecl",
21170 "calling xmlSchemaProcessXSIType() to "
21171 "process the attribute 'xsi:type'");
21172 return (-1);
21173 }
21174 /* Does not return an error on purpose. */
21175 }
21176 if (localType != NULL) {
21177 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21178 actualType = localType;
21179 }
21180 }
21181 }
21182 /*
21183 * IDC: Register identity-constraint XPath matchers.
21184 */
21185 if ((elemDecl->idcs != NULL) &&
21186 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21187 return (-1);
21188 /*
21189 * No actual type definition.
21190 */
21191 if (actualType == NULL) {
21192 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21193 "The type definition is absent");
21194 return (XML_SCHEMAV_CVC_TYPE_1);
21195 }
21196 /*
21197 * Remember the actual type definition.
21198 */
21199 vctxt->inode->typeDef = actualType;
21200
21201 return (0);
21202}
21203
21204static int
21205xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21206{
21207 xmlSchemaAttrInfoPtr iattr;
21208 int ret = 0, i;
21209
21210 /*
21211 * SPEC cvc-type (3.1.1)
21212 * "The attributes of must be empty, excepting those whose namespace
21213 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21214 * whose local name is one of type, nil, schemaLocation or
21215 * noNamespaceSchemaLocation."
21216 */
21217 if (vctxt->nbAttrInfos == 0)
21218 return (0);
21219 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21220 iattr = vctxt->attrInfos[i];
21221 if (! iattr->metaType) {
21222 ACTIVATE_ATTRIBUTE(iattr)
21223 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21224 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21225 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21226 }
21227 }
21228 ACTIVATE_ELEM
21229 return (ret);
21230}
21231
21232/*
21233* Cleanup currently used attribute infos.
21234*/
21235static void
21236xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21237{
21238 int i;
21239 xmlSchemaAttrInfoPtr attr;
21240
21241 if (vctxt->nbAttrInfos == 0)
21242 return;
21243 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21244 attr = vctxt->attrInfos[i];
21245 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21246 if (attr->localName != NULL)
21247 xmlFree((xmlChar *) attr->localName);
21248 if (attr->nsName != NULL)
21249 xmlFree((xmlChar *) attr->nsName);
21250 }
21251 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21252 if (attr->value != NULL)
21253 xmlFree((xmlChar *) attr->value);
21254 }
21255 if (attr->val != NULL) {
21256 xmlSchemaFreeValue(attr->val);
21257 attr->val = NULL;
21258 }
21259 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21260 }
21261 vctxt->nbAttrInfos = 0;
21262}
21263
21264/*
21265* 3.4.4 Complex Type Definition Validation Rules
21266* Element Locally Valid (Complex Type) (cvc-complex-type)
21267* 3.2.4 Attribute Declaration Validation Rules
21268* Validation Rule: Attribute Locally Valid (cvc-attribute)
21269* Attribute Locally Valid (Use) (cvc-au)
21270*
21271* Only "assessed" attribute information items will be visible to
21272* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21273*/
21274static int
21275xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21276{
21277 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21278 xmlSchemaAttributeLinkPtr attrUseLink;
21279 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21280 xmlSchemaAttrInfoPtr attr, tmpAttr;
21281 int i, found, nbAttrs;
21282 int xpathRes = 0, res, wildIDs = 0, fixed;
21283
21284 /*
21285 * SPEC (cvc-attribute)
21286 * (1) "The declaration must not be ·absent· (see Missing
21287 * Sub-components (§5.3) for how this can fail to be
21288 * the case)."
21289 * (2) "Its {type definition} must not be absent."
21290 *
21291 * NOTE (1) + (2): This is not handled here, since we currently do not
21292 * allow validation against schemas which have missing sub-components.
21293 *
21294 * SPEC (cvc-complex-type)
21295 * (3) "For each attribute information item in the element information
21296 * item's [attributes] excepting those whose [namespace name] is
21297 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21298 * [local name] is one of type, nil, schemaLocation or
21299 * noNamespaceSchemaLocation, the appropriate case among the following
21300 * must be true:
21301 *
21302 */
21303 nbAttrs = vctxt->nbAttrInfos;
21304 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21305 attrUseLink = attrUseLink->next) {
21306
21307 found = 0;
21308 attrUse = attrUseLink->attr;
21309 /*
21310 * VAL TODO: Implement a real "attribute use" component.
21311 */
21312 if (attrUse->refDecl != NULL)
21313 attrDecl = attrUse->refDecl;
21314 else
21315 attrDecl = attrUse;
21316 for (i = 0; i < nbAttrs; i++) {
21317 attr = vctxt->attrInfos[i];
21318 /*
21319 * SPEC (cvc-complex-type) (3)
21320 * Skip meta attributes.
21321 */
21322 if (attr->metaType)
21323 continue;
21324 if (attr->localName[0] != attrDecl->name[0])
21325 continue;
21326 if (!xmlStrEqual(attr->localName, attrDecl->name))
21327 continue;
21328 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21329 continue;
21330 found = 1;
21331 /*
21332 * SPEC (cvc-complex-type)
21333 * (3.1) "If there is among the {attribute uses} an attribute
21334 * use with an {attribute declaration} whose {name} matches
21335 * the attribute information item's [local name] and whose
21336 * {target namespace} is identical to the attribute information
21337 * item's [namespace name] (where an ·absent· {target namespace}
21338 * is taken to be identical to a [namespace name] with no value),
21339 * then the attribute information must be ·valid· with respect
21340 * to that attribute use as per Attribute Locally Valid (Use)
21341 * (§3.5.4). In this case the {attribute declaration} of that
21342 * attribute use is the ·context-determined declaration· for the
21343 * attribute information item with respect to Schema-Validity
21344 * Assessment (Attribute) (§3.2.4) and
21345 * Assessment Outcome (Attribute) (§3.2.5).
21346 */
21347 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21348 attr->use = attrUse;
21349 /*
21350 * Context-determined declaration.
21351 */
21352 attr->decl = attrDecl;
21353 attr->typeDef = attrDecl->subtypes;
21354 break;
21355 }
21356
21357 if (found)
21358 continue;
21359
21360 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21361 /*
21362 * Handle non-existent, required attributes.
21363 *
21364 * SPEC (cvc-complex-type)
21365 * (4) "The {attribute declaration} of each attribute use in
21366 * the {attribute uses} whose {required} is true matches one
21367 * of the attribute information items in the element information
21368 * item's [attributes] as per clause 3.1 above."
21369 */
21370 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21371 if (tmpAttr == NULL) {
21372 VERROR_INT(
21373 "xmlSchemaVAttributesComplex",
21374 "calling xmlSchemaGetFreshAttrInfo()");
21375 return (-1);
21376 }
21377 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21378 tmpAttr->use = attrUse;
21379 tmpAttr->decl = attrDecl;
21380 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21381 ((attrUse->defValue != NULL) ||
21382 (attrDecl->defValue != NULL))) {
21383 /*
21384 * Handle non-existent, optional, default/fixed attributes.
21385 */
21386 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21387 if (tmpAttr == NULL) {
21388 VERROR_INT(
21389 "xmlSchemaVAttributesComplex",
21390 "calling xmlSchemaGetFreshAttrInfo()");
21391 return (-1);
21392 }
21393 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21394 tmpAttr->use = attrUse;
21395 tmpAttr->decl = attrDecl;
21396 tmpAttr->typeDef = attrDecl->subtypes;
21397 tmpAttr->localName = attrDecl->name;
21398 tmpAttr->nsName = attrDecl->targetNamespace;
21399 }
21400 }
21401 if (vctxt->nbAttrInfos == 0)
21402 return (0);
21403 /*
21404 * Validate against the wildcard.
21405 */
21406 if (type->attributeWildcard != NULL) {
21407 /*
21408 * SPEC (cvc-complex-type)
21409 * (3.2.1) "There must be an {attribute wildcard}."
21410 */
21411 for (i = 0; i < nbAttrs; i++) {
21412 attr = vctxt->attrInfos[i];
21413 /*
21414 * SPEC (cvc-complex-type) (3)
21415 * Skip meta attributes.
21416 */
21417 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21418 continue;
21419 /*
21420 * SPEC (cvc-complex-type)
21421 * (3.2.2) "The attribute information item must be ·valid· with
21422 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21423 *
21424 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21425 * "... its [namespace name] must be ·valid· with respect to
21426 * the wildcard constraint, as defined in Wildcard allows
21427 * Namespace Name (§3.10.4)."
21428 */
21429 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21430 attr->nsName)) {
21431 /*
21432 * Handle processContents.
21433 *
21434 * SPEC (cvc-wildcard):
21435 * processContents | context-determined declaration:
21436 * "strict" "mustFind"
21437 * "lax" "none"
21438 * "skip" "skip"
21439 */
21440 if (type->attributeWildcard->processContents ==
21441 XML_SCHEMAS_ANY_SKIP) {
21442 /*
21443 * context-determined declaration = "skip"
21444 *
21445 * SPEC PSVI Assessment Outcome (Attribute)
21446 * [validity] = "notKnown"
21447 * [validation attempted] = "none"
21448 */
21449 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21450 continue;
21451 }
21452 /*
21453 * Find an attribute declaration.
21454 */
21455 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21456 attr->localName, attr->nsName);
21457 if (attr->decl != NULL) {
21458 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21459 /*
21460 * SPEC (cvc-complex-type)
21461 * (5) "Let [Definition:] the wild IDs be the set of
21462 * all attribute information item to which clause 3.2
21463 * applied and whose ·validation· resulted in a
21464 * ·context-determined declaration· of mustFind or no
21465 * ·context-determined declaration· at all, and whose
21466 * [local name] and [namespace name] resolve (as
21467 * defined by QName resolution (Instance) (§3.15.4)) to
21468 * an attribute declaration whose {type definition} is
21469 * or is derived from ID. Then all of the following
21470 * must be true:"
21471 */
21472 attr->typeDef = attr->decl->subtypes;
21473 if (xmlSchemaIsDerivedFromBuiltInType(
21474 attr->typeDef, XML_SCHEMAS_ID)) {
21475 /*
21476 * SPEC (5.1) "There must be no more than one
21477 * item in ·wild IDs·."
21478 */
21479 if (wildIDs != 0) {
21480 /* VAL TODO */
21481 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21482 TODO
21483 continue;
21484 }
21485 wildIDs++;
21486 /*
21487 * SPEC (cvc-complex-type)
21488 * (5.2) "If ·wild IDs· is non-empty, there must not
21489 * be any attribute uses among the {attribute uses}
21490 * whose {attribute declaration}'s {type definition}
21491 * is or is derived from ID."
21492 */
21493 for (attrUseLink = type->attributeUses;
21494 attrUseLink != NULL;
21495 attrUseLink = attrUseLink->next) {
21496 if (xmlSchemaIsDerivedFromBuiltInType(
21497 attrUseLink->attr->subtypes,
21498 XML_SCHEMAS_ID)) {
21499 /* VAL TODO */
21500 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21501 TODO
21502 }
21503 }
21504 }
21505 } else if (type->attributeWildcard->processContents ==
21506 XML_SCHEMAS_ANY_LAX) {
21507 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21508 /*
21509 * SPEC PSVI Assessment Outcome (Attribute)
21510 * [validity] = "notKnown"
21511 * [validation attempted] = "none"
21512 */
21513 } else {
21514 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21515 }
21516 }
21517 }
21518 }
21519
21520
21521 if (vctxt->nbAttrInfos == 0)
21522 return (0);
21523
21524 /*
21525 * Validate values, create default attributes, evaluate IDCs.
21526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021527 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21528 attr = vctxt->attrInfos[i];
21529 /*
21530 * VAL TODO: Note that we won't try to resolve IDCs to
21531 * "lax" and "skip" validated attributes. Check what to
21532 * do in this case.
21533 */
21534 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21535 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21536 continue;
21537 /*
21538 * VAL TODO: What to do if the type definition is missing?
21539 */
21540 if (attr->typeDef == NULL) {
21541 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21542 continue;
21543 }
21544
21545 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021546 fixed = 0;
21547 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021548
21549 if (vctxt->xpathStates != NULL) {
21550 /*
21551 * Evaluate IDCs.
21552 */
21553 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21554 XML_ATTRIBUTE_NODE);
21555 if (xpathRes == -1) {
21556 VERROR_INT("xmlSchemaVAttributesComplex",
21557 "calling xmlSchemaXPathEvaluate()");
21558 goto internal_error;
21559 }
21560 }
21561
21562 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21563 /*
21564 * Default/fixed attributes.
21565 */
21566 if (xpathRes) {
21567 if (attr->use->defValue == NULL) {
21568 attr->value = (xmlChar *) attr->use->defValue;
21569 attr->val = attr->use->defVal;
21570 } else {
21571 attr->value = (xmlChar *) attr->decl->defValue;
21572 attr->val = attr->decl->defVal;
21573 }
21574 /*
21575 * IDCs will consume the precomputed default value,
21576 * so we need to clone it.
21577 */
21578 if (attr->val == NULL) {
21579 VERROR_INT("xmlSchemaVAttributesComplex",
21580 "default/fixed value on an attribute use was "
21581 "not precomputed");
21582 goto internal_error;
21583 }
21584 attr->val = xmlSchemaCopyValue(attr->val);
21585 if (attr->val == NULL) {
21586 VERROR_INT("xmlSchemaVAttributesComplex",
21587 "calling xmlSchemaCopyValue()");
21588 goto internal_error;
21589 }
21590 }
21591 /*
21592 * PSVI: Add the default attribute to the current element.
21593 * VAL TODO: Should we use the *normalized* value? This currently
21594 * uses the *initial* value.
21595 */
21596 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21597 (attr->node != NULL) && (attr->node->doc != NULL)) {
21598 xmlChar *normValue;
21599 const xmlChar *value;
21600
21601 value = attr->value;
21602 /*
21603 * Normalize the value.
21604 */
21605 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21606 attr->value);
21607 if (normValue != NULL)
21608 value = BAD_CAST normValue;
21609
21610 if (attr->nsName == NULL) {
21611 if (xmlNewProp(attr->node->parent,
21612 attr->localName, value) == NULL) {
21613 VERROR_INT("xmlSchemaVAttributesComplex",
21614 "callling xmlNewProp()");
21615 if (normValue != NULL)
21616 xmlFree(normValue);
21617 goto internal_error;
21618 }
21619 } else {
21620 xmlNsPtr ns;
21621
21622 ns = xmlSearchNsByHref(attr->node->doc,
21623 attr->node->parent, attr->nsName);
21624 if (ns == NULL) {
21625 xmlChar prefix[12];
21626 int counter = 0;
21627
21628 /*
21629 * Create a namespace declaration on the validation
21630 * root node if no namespace declaration is in scope.
21631 */
21632 do {
21633 snprintf((char *) prefix, 12, "p%d", counter++);
21634 ns = xmlSearchNs(attr->node->doc,
21635 attr->node->parent, BAD_CAST prefix);
21636 if (counter > 1000) {
21637 VERROR_INT(
21638 "xmlSchemaVAttributesComplex",
21639 "could not compute a ns prefix for a "
21640 "default/fixed attribute");
21641 if (normValue != NULL)
21642 xmlFree(normValue);
21643 goto internal_error;
21644 }
21645 } while (ns != NULL);
21646 ns = xmlNewNs(vctxt->validationRoot,
21647 attr->nsName, BAD_CAST prefix);
21648 }
21649 xmlNewNsProp(attr->node->parent, ns,
21650 attr->localName, value);
21651 }
21652 if (normValue != NULL)
21653 xmlFree(normValue);
21654 }
21655 /*
21656 * Go directly to IDC evaluation.
21657 */
21658 goto eval_idcs;
21659 }
21660 /*
21661 * Validate the value.
21662 */
21663 if (vctxt->value != NULL) {
21664 /*
21665 * Free last computed value; just for safety reasons.
21666 */
21667 xmlSchemaFreeValue(vctxt->value);
21668 vctxt->value = NULL;
21669 }
21670 /*
21671 * Note that the attribute *use* can be unavailable, if
21672 * the attribute was a wild attribute.
21673 */
21674 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21675 ((attr->use != NULL) &&
21676 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21677 fixed = 1;
21678 else
21679 fixed = 0;
21680 /*
21681 * SPEC (cvc-attribute)
21682 * (3) "The item's ·normalized value· must be locally ·valid·
21683 * with respect to that {type definition} as per
21684 * String Valid (§3.14.4)."
21685 *
21686 * VAL TODO: Do we already have the
21687 * "normalized attribute value" here?
21688 */
21689 if (xpathRes || fixed) {
21690 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21691 /*
21692 * Request a computed value.
21693 */
21694 res = xmlSchemaVCheckCVCSimpleType(
21695 (xmlSchemaAbstractCtxtPtr) vctxt,
21696 attr->node, attr->typeDef, attr->value, &(attr->val),
21697 1, 1, 0);
21698 } else {
21699 res = xmlSchemaVCheckCVCSimpleType(
21700 (xmlSchemaAbstractCtxtPtr) vctxt,
21701 attr->node, attr->typeDef, attr->value, NULL,
21702 1, 0, 0);
21703 }
21704
21705 if (res != 0) {
21706 if (res == -1) {
21707 VERROR_INT("xmlSchemaVAttributesComplex",
21708 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21709 goto internal_error;
21710 }
21711 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21712 /*
21713 * SPEC PSVI Assessment Outcome (Attribute)
21714 * [validity] = "invalid"
21715 */
21716 goto eval_idcs;
21717 }
21718
21719 if (fixed) {
21720 int ws;
21721 /*
21722 * SPEC Attribute Locally Valid (Use) (cvc-au)
21723 * "For an attribute information item to be·valid·
21724 * with respect to an attribute use its *normalized*
21725 * value· must match the *canonical* lexical
21726 * representation of the attribute use's {value
21727 * constraint}value, if it is present and fixed."
21728 *
21729 * VAL TODO: The requirement for the *canonical* value
21730 * will be removed in XML Schema 1.1.
21731 */
21732 /*
21733 * SPEC Attribute Locally Valid (cvc-attribute)
21734 * (4) "The item's *actual* value· must match the *value* of
21735 * the {value constraint}, if it is present and fixed."
21736 */
21737 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21738 if (attr->val == NULL) {
21739 /* VAL TODO: A value was not precomputed. */
21740 TODO
21741 goto eval_idcs;
21742 }
21743 if ((attr->use != NULL) &&
21744 (attr->use->defValue != NULL)) {
21745 if (attr->use->defVal == NULL) {
21746 /* VAL TODO: A default value was not precomputed. */
21747 TODO
21748 goto eval_idcs;
21749 }
21750 attr->vcValue = attr->use->defValue;
21751 /*
21752 if (xmlSchemaCompareValuesWhtsp(attr->val,
21753 (xmlSchemaWhitespaceValueType) ws,
21754 attr->use->defVal,
21755 (xmlSchemaWhitespaceValueType) ws) != 0) {
21756 */
21757 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21758 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21759 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021760 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021761 /* VAL TODO: A default value was not precomputed. */
21762 TODO
21763 goto eval_idcs;
21764 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021765 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021766 /*
21767 if (xmlSchemaCompareValuesWhtsp(attr->val,
21768 (xmlSchemaWhitespaceValueType) ws,
21769 attrDecl->defVal,
21770 (xmlSchemaWhitespaceValueType) ws) != 0) {
21771 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021772 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021773 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21774 }
21775 /*
21776 * [validity] = "valid"
21777 */
21778 }
21779eval_idcs:
21780 /*
21781 * Evaluate IDCs.
21782 */
21783 if (xpathRes) {
21784 if (xmlSchemaXPathProcessHistory(vctxt,
21785 vctxt->depth +1) == -1) {
21786 VERROR_INT("xmlSchemaVAttributesComplex",
21787 "calling xmlSchemaXPathEvaluate()");
21788 goto internal_error;
21789 }
21790 }
21791 }
21792
21793 /*
21794 * Report errors.
21795 */
21796 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21797 attr = vctxt->attrInfos[i];
21798 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21799 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21800 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21801 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21802 continue;
21803 ACTIVATE_ATTRIBUTE(attr);
21804 switch (attr->state) {
21805 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21806 xmlChar *str = NULL;
21807 ACTIVATE_ELEM;
21808 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21809 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21810 "The attribute '%s' is required but missing",
21811 xmlSchemaFormatQName(&str,
21812 attr->decl->targetNamespace,
21813 attr->decl->name),
21814 NULL);
21815 FREE_AND_NULL(str)
21816 break;
21817 }
21818 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21819 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21820 "The type definition is absent");
21821 break;
21822 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21823 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21824 XML_SCHEMAV_CVC_AU, NULL, NULL,
21825 "The value '%s' does not match the fixed "
21826 "value constraint '%s'",
21827 attr->value, attr->vcValue);
21828 break;
21829 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21830 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21831 "No matching global attribute declaration available, but "
21832 "demanded by the strict wildcard");
21833 break;
21834 case XML_SCHEMAS_ATTR_UNKNOWN:
21835 if (attr->metaType)
21836 break;
21837 /*
21838 * MAYBE VAL TODO: One might report different error messages
21839 * for the following errors.
21840 */
21841 if (type->attributeWildcard == NULL) {
21842 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21843 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21844 } else {
21845 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21846 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21847 }
21848 break;
21849 default:
21850 break;
21851 }
21852 }
21853
21854 ACTIVATE_ELEM;
21855 return (0);
21856internal_error:
21857 ACTIVATE_ELEM;
21858 return (-1);
21859}
21860
21861static int
21862xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21863 int *skip)
21864{
21865 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21866 /*
21867 * The namespace of the element was already identified to be
21868 * matching the wildcard.
21869 */
21870 if ((skip == NULL) || (wild == NULL) ||
21871 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21872 VERROR_INT("xmlSchemaValidateElemWildcard",
21873 "bad arguments");
21874 return (-1);
21875 }
21876 *skip = 0;
21877 if (wild->negNsSet != NULL) {
21878 /*
21879 * URGENT VAL TODO: Fix the content model to reject
21880 * "##other" wildcards.
21881 */
21882 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21883 vctxt->inode->nsName) != 0) {
21884 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21885 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21886 /*
21887 * VAL TODO: Workaround possible *only* if minOccurs and
21888 * maxOccurs are 1.
21889 */
21890 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21891 /* VAL TODO: error code? */
21892 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21893 (xmlSchemaTypePtr) wild,
21894 "This element is not accepted by the wildcard",
21895 0, 0, NULL);
21896 vctxt->skipDepth = vctxt->depth;
21897 if ((pinode->flags &
21898 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21899 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21900 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21901 return (XML_SCHEMAV_ELEMENT_CONTENT);
21902 }
21903 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21904 *skip = 1;
21905 return (0);
21906 }
21907 vctxt->inode->typeDef =
21908 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21909 return (0);
21910 }
21911 }
21912 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21913 /*
21914 * URGENT VAL TODO: Either we need to position the stream to the
21915 * next sibling, or walk the whole subtree.
21916 */
21917 *skip = 1;
21918 return (0);
21919 }
21920 {
21921 xmlSchemaElementPtr decl = NULL;
21922
21923 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21924 vctxt->inode->localName, vctxt->inode->nsName,
21925 NULL);
21926 if (decl != NULL) {
21927 vctxt->inode->decl = decl;
21928 return (0);
21929 }
21930 }
21931 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21932 /* VAL TODO: Change to proper error code. */
21933 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21934 "No matching global element declaration available, but "
21935 "demanded by the strict wildcard");
21936 return (vctxt->err);
21937 }
21938 if (vctxt->nbAttrInfos != 0) {
21939 xmlSchemaAttrInfoPtr iattr;
21940 /*
21941 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21942 * (1.2.1.2.1) - (1.2.1.2.3 )
21943 *
21944 * Use the xsi:type attribute for the type definition.
21945 */
21946 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21947 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21948 if (iattr != NULL) {
21949 if (xmlSchemaProcessXSIType(vctxt, iattr,
21950 &(vctxt->inode->typeDef), NULL) == -1) {
21951 VERROR_INT("xmlSchemaValidateElemWildcard",
21952 "calling xmlSchemaProcessXSIType() to "
21953 "process the attribute 'xsi:nil'");
21954 return (-1);
21955 }
21956 /*
21957 * Don't return an error on purpose.
21958 */
21959 return (0);
21960 }
21961 }
21962 /*
21963 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21964 *
21965 * Fallback to "anyType".
21966 */
21967 vctxt->inode->typeDef =
21968 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21969 return (0);
21970}
21971
21972/*
21973* xmlSchemaCheckCOSValidDefault:
21974*
21975* This will be called if: not nilled, no content and a default/fixed
21976* value is provided.
21977*/
21978
21979static int
21980xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21981 const xmlChar *value,
21982 xmlSchemaValPtr *val)
21983{
21984 int ret = 0;
21985 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21986
21987 /*
21988 * cos-valid-default:
21989 * Schema Component Constraint: Element Default Valid (Immediate)
21990 * For a string to be a valid default with respect to a type
21991 * definition the appropriate case among the following must be true:
21992 */
21993 if IS_COMPLEX_TYPE(inode->typeDef) {
21994 /*
21995 * Complex type.
21996 *
21997 * SPEC (2.1) "its {content type} must be a simple type definition
21998 * or mixed."
21999 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
22000 * type}'s particle must be ·emptiable· as defined by
22001 * Particle Emptiable (§3.9.6)."
22002 */
22003 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
22004 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
22005 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
22006 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
22007 /* NOTE that this covers (2.2.2) as well. */
22008 VERROR(ret, NULL,
22009 "For a string to be a valid default, the type definition "
22010 "must be a simple type or a complex type with simple content "
22011 "or mixed content and a particle emptiable");
22012 return(ret);
22013 }
22014 }
22015 /*
22016 * 1 If the type definition is a simple type definition, then the string
22017 * must be ·valid· with respect to that definition as defined by String
22018 * Valid (§3.14.4).
22019 *
22020 * AND
22021 *
22022 * 2.2.1 If the {content type} is a simple type definition, then the
22023 * string must be ·valid· with respect to that simple type definition
22024 * as defined by String Valid (§3.14.4).
22025 */
22026 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22027
22028 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22029 NULL, inode->typeDef, value, val, 1, 1, 0);
22030
22031 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22032
22033 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22034 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22035 }
22036 if (ret < 0) {
22037 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22038 "calling xmlSchemaVCheckCVCSimpleType()");
22039 }
22040 return (ret);
22041}
22042
22043static void
22044xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22045 const xmlChar * name ATTRIBUTE_UNUSED,
22046 xmlSchemaElementPtr item,
22047 xmlSchemaNodeInfoPtr inode)
22048{
22049 inode->decl = item;
22050#ifdef DEBUG_CONTENT
22051 {
22052 xmlChar *str = NULL;
22053
22054 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22055 xmlGenericError(xmlGenericErrorContext,
22056 "AUTOMATON callback for '%s' [declaration]\n",
22057 xmlSchemaFormatQName(&str,
22058 inode->localName, inode->nsName));
22059 } else {
22060 xmlGenericError(xmlGenericErrorContext,
22061 "AUTOMATON callback for '%s' [wildcard]\n",
22062 xmlSchemaFormatQName(&str,
22063 inode->localName, inode->nsName));
22064
22065 }
22066 FREE_AND_NULL(str)
22067 }
22068#endif
22069}
22070
22071static int
22072xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022073{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022074 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22075 if (vctxt->inode == NULL) {
22076 VERROR_INT("xmlSchemaValidatorPushElem",
22077 "calling xmlSchemaGetFreshElemInfo()");
22078 return (-1);
22079 }
22080 vctxt->nbAttrInfos = 0;
22081 return (0);
22082}
22083
22084static int
22085xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22086 xmlSchemaNodeInfoPtr inode,
22087 xmlSchemaTypePtr type,
22088 const xmlChar *value)
22089{
22090 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22091 return (xmlSchemaVCheckCVCSimpleType(
22092 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22093 type, value, &(inode->val), 1, 1, 0));
22094 else
22095 return (xmlSchemaVCheckCVCSimpleType(
22096 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22097 type, value, NULL, 1, 0, 0));
22098}
22099
22100
22101
22102/*
22103* Process END of element.
22104*/
22105static int
22106xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22107{
22108 int ret = 0;
22109 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22110
22111 if (vctxt->nbAttrInfos != 0)
22112 xmlSchemaClearAttrInfos(vctxt);
22113 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22114 /*
22115 * This element was not expected;
22116 * we will not validate child elements of broken parents.
22117 * Skip validation of all content of the parent.
22118 */
22119 vctxt->skipDepth = vctxt->depth -1;
22120 goto end_elem;
22121 }
22122 if ((inode->typeDef == NULL) ||
22123 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22124 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022125 * 1. the type definition might be missing if the element was
22126 * error prone
22127 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022128 */
22129 goto end_elem;
22130 }
22131 /*
22132 * Check the content model.
22133 */
22134 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22135 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22136
22137 /*
22138 * Workaround for "anyType".
22139 */
22140 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22141 goto character_content;
22142
22143 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22144 xmlChar *values[10];
22145 int terminal, nbval = 10, nbneg;
22146
22147 if (inode->regexCtxt == NULL) {
22148 /*
22149 * Create the regex context.
22150 */
22151 inode->regexCtxt =
22152 xmlRegNewExecCtxt(inode->typeDef->contModel,
22153 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22154 vctxt);
22155 if (inode->regexCtxt == NULL) {
22156 VERROR_INT("xmlSchemaValidatorPopElem",
22157 "failed to create a regex context");
22158 goto internal_error;
22159 }
22160#ifdef DEBUG_AUTOMATA
22161 xmlGenericError(xmlGenericErrorContext,
22162 "AUTOMATON create on '%s'\n", inode->localName);
22163#endif
22164 }
22165 /*
22166 * Get hold of the still expected content, since a further
22167 * call to xmlRegExecPushString() will loose this information.
22168 */
22169 xmlRegExecNextValues(inode->regexCtxt,
22170 &nbval, &nbneg, &values[0], &terminal);
22171 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22172 if (ret <= 0) {
22173 /*
22174 * Still missing something.
22175 */
22176 ret = 1;
22177 inode->flags |=
22178 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22179 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22180 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22181 "Missing child element(s)",
22182 nbval, nbneg, values);
22183#ifdef DEBUG_AUTOMATA
22184 xmlGenericError(xmlGenericErrorContext,
22185 "AUTOMATON missing ERROR on '%s'\n",
22186 inode->localName);
22187#endif
22188 } else {
22189 /*
22190 * Content model is satisfied.
22191 */
22192 ret = 0;
22193#ifdef DEBUG_AUTOMATA
22194 xmlGenericError(xmlGenericErrorContext,
22195 "AUTOMATON succeeded on '%s'\n",
22196 inode->localName);
22197#endif
22198 }
22199
22200 }
22201 }
22202 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22203 goto end_elem;
22204
22205character_content:
22206
22207 if (vctxt->value != NULL) {
22208 xmlSchemaFreeValue(vctxt->value);
22209 vctxt->value = NULL;
22210 }
22211 /*
22212 * Check character content.
22213 */
22214 if (inode->decl == NULL) {
22215 /*
22216 * Speedup if no declaration exists.
22217 */
22218 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22219 ret = xmlSchemaVCheckINodeDataType(vctxt,
22220 inode, inode->typeDef, inode->value);
22221 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22222 ret = xmlSchemaVCheckINodeDataType(vctxt,
22223 inode, inode->typeDef->contentTypeDef,
22224 inode->value);
22225 }
22226 if (ret < 0) {
22227 VERROR_INT("xmlSchemaValidatorPopElem",
22228 "calling xmlSchemaVCheckCVCSimpleType()");
22229 goto internal_error;
22230 }
22231 goto end_elem;
22232 }
22233 /*
22234 * cvc-elt (3.3.4) : 5
22235 * The appropriate case among the following must be true:
22236 */
22237 /*
22238 * cvc-elt (3.3.4) : 5.1
22239 * If the declaration has a {value constraint},
22240 * the item has neither element nor character [children] and
22241 * clause 3.2 has not applied, then all of the following must be true:
22242 */
22243 if ((inode->decl->value != NULL) &&
22244 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22245 (! INODE_NILLED(inode))) {
22246 /*
22247 * cvc-elt (3.3.4) : 5.1.1
22248 * If the ·actual type definition· is a ·local type definition·
22249 * then the canonical lexical representation of the {value constraint}
22250 * value must be a valid default for the ·actual type definition· as
22251 * defined in Element Default Valid (Immediate) (§3.3.6).
22252 */
22253 /*
22254 * NOTE: 'local' above means types aquired by xsi:type.
22255 * NOTE: Although the *canonical* value is stated, it is not
22256 * relevant if canonical or not. Additionally XML Schema 1.1
22257 * will removed this requirement as well.
22258 */
22259 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22260
22261 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22262 inode->decl->value, &(inode->val));
22263 if (ret != 0) {
22264 if (ret < 0) {
22265 VERROR_INT("xmlSchemaValidatorPopElem",
22266 "calling xmlSchemaCheckCOSValidDefault()");
22267 goto internal_error;
22268 }
22269 goto end_elem;
22270 }
22271 /*
22272 * Stop here, to avoid redundant validation of the value
22273 * (see following).
22274 */
22275 goto default_psvi;
22276 }
22277 /*
22278 * cvc-elt (3.3.4) : 5.1.2
22279 * The element information item with the canonical lexical
22280 * representation of the {value constraint} value used as its
22281 * ·normalized value· must be ·valid· with respect to the
22282 * ·actual type definition· as defined by Element Locally Valid (Type)
22283 * (§3.3.4).
22284 */
22285 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22286 ret = xmlSchemaVCheckINodeDataType(vctxt,
22287 inode, inode->typeDef, inode->decl->value);
22288 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22289 ret = xmlSchemaVCheckINodeDataType(vctxt,
22290 inode, inode->typeDef->contentTypeDef,
22291 inode->decl->value);
22292 }
22293 if (ret != 0) {
22294 if (ret < 0) {
22295 VERROR_INT("xmlSchemaValidatorPopElem",
22296 "calling xmlSchemaVCheckCVCSimpleType()");
22297 goto internal_error;
22298 }
22299 goto end_elem;
22300 }
22301
22302default_psvi:
22303 /*
22304 * PSVI: Create a text node on the instance element.
22305 */
22306 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22307 (inode->node != NULL)) {
22308 xmlNodePtr textChild;
22309 xmlChar *normValue;
22310 /*
22311 * VAL TODO: Normalize the value.
22312 */
22313 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22314 inode->decl->value);
22315 if (normValue != NULL) {
22316 textChild = xmlNewText(BAD_CAST normValue);
22317 xmlFree(normValue);
22318 } else
22319 textChild = xmlNewText(inode->decl->value);
22320 if (textChild == NULL) {
22321 VERROR_INT("xmlSchemaValidatorPopElem",
22322 "calling xmlNewText()");
22323 goto internal_error;
22324 } else
22325 xmlAddChild(inode->node, textChild);
22326 }
22327
22328 } else if (! INODE_NILLED(inode)) {
22329 /*
22330 * 5.2.1 The element information item must be ·valid· with respect
22331 * to the ·actual type definition· as defined by Element Locally
22332 * Valid (Type) (§3.3.4).
22333 */
22334 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22335 /*
22336 * SPEC (cvc-type) (3.1)
22337 * "If the type definition is a simple type definition, ..."
22338 * (3.1.3) "If clause 3.2 of Element Locally Valid
22339 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22340 * must be ·valid· with respect to the type definition as defined
22341 * by String Valid (§3.14.4).
22342 */
22343 ret = xmlSchemaVCheckINodeDataType(vctxt,
22344 inode, inode->typeDef, inode->value);
22345 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22346 /*
22347 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22348 * definition, then the element information item must be
22349 * ·valid· with respect to the type definition as per
22350 * Element Locally Valid (Complex Type) (§3.4.4);"
22351 *
22352 * SPEC (cvc-complex-type) (2.2)
22353 * "If the {content type} is a simple type definition, ...
22354 * the ·normalized value· of the element information item is
22355 * ·valid· with respect to that simple type definition as
22356 * defined by String Valid (§3.14.4)."
22357 */
22358 ret = xmlSchemaVCheckINodeDataType(vctxt,
22359 inode, inode->typeDef->contentTypeDef, inode->value);
22360 }
22361 if (ret != 0) {
22362 if (ret < 0) {
22363 VERROR_INT("xmlSchemaValidatorPopElem",
22364 "calling xmlSchemaVCheckCVCSimpleType()");
22365 goto internal_error;
22366 }
22367 goto end_elem;
22368 }
22369 /*
22370 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22371 * not applied, all of the following must be true:
22372 */
22373 if ((inode->decl->value != NULL) &&
22374 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22375
22376 /*
22377 * TODO: We will need a computed value, when comparison is
22378 * done on computed values.
22379 */
22380 /*
22381 * 5.2.2.1 The element information item must have no element
22382 * information item [children].
22383 */
22384 if (inode->flags &
22385 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22386 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22387 VERROR(ret, NULL,
22388 "The content must not containt element nodes since "
22389 "there is a fixed value constraint");
22390 goto end_elem;
22391 } else {
22392 /*
22393 * 5.2.2.2 The appropriate case among the following must
22394 * be true:
22395 */
22396 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22397 /*
22398 * 5.2.2.2.1 If the {content type} of the ·actual type
22399 * definition· is mixed, then the *initial value* of the
22400 * item must match the canonical lexical representation
22401 * of the {value constraint} value.
22402 *
22403 * ... the *initial value* of an element information
22404 * item is the string composed of, in order, the
22405 * [character code] of each character information item in
22406 * the [children] of that element information item.
22407 */
22408 if (! xmlStrEqual(inode->value, inode->decl->value)){
22409 /*
22410 * VAL TODO: Report invalid & expected values as well.
22411 * VAL TODO: Implement the canonical stuff.
22412 */
22413 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22414 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22415 ret, NULL, NULL,
22416 "The initial value '%s' does not match the fixed "
22417 "value constraint '%s'",
22418 inode->value, inode->decl->value);
22419 goto end_elem;
22420 }
22421 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22422 /*
22423 * 5.2.2.2.2 If the {content type} of the ·actual type
22424 * definition· is a simple type definition, then the
22425 * *actual value* of the item must match the canonical
22426 * lexical representation of the {value constraint} value.
22427 */
22428 /*
22429 * VAL TODO: *actual value* is the normalized value, impl.
22430 * this.
22431 * VAL TODO: Report invalid & expected values as well.
22432 * VAL TODO: Implement a comparison with the computed values.
22433 */
22434 if (! xmlStrEqual(inode->value,
22435 inode->decl->value)) {
22436 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22437 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22438 ret, NULL, NULL,
22439 "The actual value '%s' does not match the fixed "
22440 "value constraint '%s'",
22441 inode->value,
22442 inode->decl->value);
22443 goto end_elem;
22444 }
22445 }
22446 }
22447 }
22448 }
22449
22450end_elem:
22451 if (vctxt->depth < 0) {
22452 /* TODO: raise error? */
22453 return (0);
22454 }
22455 if (vctxt->depth == vctxt->skipDepth)
22456 vctxt->skipDepth = -1;
22457 /*
22458 * Evaluate the history of XPath state objects.
22459 */
22460 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22461 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022462 /*
22463 * TODO: 6 The element information item must be ·valid· with respect to each of
22464 * the {identity-constraint definitions} as per Identity-constraint
22465 * Satisfied (§3.11.4).
22466 */
22467 /*
22468 * Validate IDC keyrefs.
22469 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022470 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22471 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022472 /*
22473 * Merge/free the IDC table.
22474 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022475 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022476#ifdef DEBUG_IDC
22477 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022478 inode->nsName,
22479 inode->localName,
22480 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022481#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022482 if (vctxt->depth > 0) {
22483 /*
22484 * Merge the IDC node table with the table of the parent node.
22485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022486 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22487 goto internal_error;
22488 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022489 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022490 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022491 * Clear the current ielem.
22492 * VAL TODO: Don't free the PSVI IDC tables if they are
22493 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022494 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022495 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022496 /*
22497 * Skip further processing if we are on the validation root.
22498 */
22499 if (vctxt->depth == 0) {
22500 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022501 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022502 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022503 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022504 /*
22505 * Reset the bubbleDepth if needed.
22506 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022507 if (vctxt->aidcs != NULL) {
22508 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22509 do {
22510 if (aidc->bubbleDepth == vctxt->depth) {
22511 /*
22512 * A bubbleDepth of a key/unique IDC matches the current
22513 * depth, this means that we are leaving the scope of the
22514 * top-most keyref IDC.
22515 */
22516 aidc->bubbleDepth = -1;
22517 }
22518 aidc = aidc->next;
22519 } while (aidc != NULL);
22520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022521 vctxt->depth--;
22522 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022523 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022524 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022525 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022527 return (ret);
22528
22529internal_error:
22530 vctxt->err = -1;
22531 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022532}
22533
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022534/*
22535* 3.4.4 Complex Type Definition Validation Rules
22536* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22537*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022538static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022539xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022540{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022541 xmlSchemaNodeInfoPtr pielem;
22542 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022543 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022544
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022545 if (vctxt->depth <= 0) {
22546 VERROR_INT("xmlSchemaValidateChildElem",
22547 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022548 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022549 }
22550 pielem = vctxt->elemInfos[vctxt->depth -1];
22551 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22552 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022553 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022554 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022555 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022556 if (INODE_NILLED(pielem)) {
22557 /*
22558 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22559 */
22560 ACTIVATE_PARENT_ELEM;
22561 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22562 VERROR(ret, NULL,
22563 "Neither character nor element content is allowed, "
22564 "because the element was 'nilled'");
22565 ACTIVATE_ELEM;
22566 goto unexpected_elem;
22567 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022568
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022569 ptype = pielem->typeDef;
22570
22571 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22572 /*
22573 * Workaround for "anyType": we have currently no content model
22574 * assigned for "anyType", so handle it explicitely.
22575 * "anyType" has an unbounded, lax "any" wildcard.
22576 */
22577 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22578 vctxt->inode->localName,
22579 vctxt->inode->nsName);
22580
22581 if (vctxt->inode->decl == NULL) {
22582 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022583 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022584 * Process "xsi:type".
22585 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022586 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022587 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22588 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22589 if (iattr != NULL) {
22590 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22591 &(vctxt->inode->typeDef), NULL);
22592 if (ret != 0) {
22593 if (ret == -1) {
22594 VERROR_INT("xmlSchemaValidateChildElem",
22595 "calling xmlSchemaProcessXSIType() to "
22596 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022597 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022599 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022601 } else {
22602 /*
22603 * Fallback to "anyType".
22604 *
22605 * SPEC (cvc-assess-elt)
22606 * "If the item cannot be ·strictly assessed·, [...]
22607 * an element information item's schema validity may be laxly
22608 * assessed if its ·context-determined declaration· is not
22609 * skip by ·validating· with respect to the ·ur-type
22610 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22611 */
22612 vctxt->inode->typeDef =
22613 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022614 }
22615 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022616 return (0);
22617 }
22618
22619 switch (ptype->contentType) {
22620 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022621 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022622 * SPEC (2.1) "If the {content type} is empty, then the
22623 * element information item has no character or element
22624 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022625 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022626 ACTIVATE_PARENT_ELEM
22627 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22628 VERROR(ret, NULL,
22629 "Element content is not allowed, "
22630 "because the content type is empty");
22631 ACTIVATE_ELEM
22632 goto unexpected_elem;
22633 break;
22634
22635 case XML_SCHEMA_CONTENT_MIXED:
22636 case XML_SCHEMA_CONTENT_ELEMENTS: {
22637 xmlRegExecCtxtPtr regexCtxt;
22638 xmlChar *values[10];
22639 int terminal, nbval = 10, nbneg;
22640
22641 /* VAL TODO: Optimized "anyType" validation.*/
22642
22643 if (ptype->contModel == NULL) {
22644 VERROR_INT("xmlSchemaValidateChildElem",
22645 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022646 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022647 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022648 /*
22649 * Safety belf for evaluation if the cont. model was already
22650 * examined to be invalid.
22651 */
22652 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22653 VERROR_INT("xmlSchemaValidateChildElem",
22654 "validating elem, but elem content is already invalid");
22655 return (-1);
22656 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022657
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022658 regexCtxt = pielem->regexCtxt;
22659 if (regexCtxt == NULL) {
22660 /*
22661 * Create the regex context.
22662 */
22663 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22664 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22665 vctxt);
22666 if (regexCtxt == NULL) {
22667 VERROR_INT("xmlSchemaValidateChildElem",
22668 "failed to create a regex context");
22669 return (-1);
22670 }
22671 pielem->regexCtxt = regexCtxt;
22672#ifdef DEBUG_AUTOMATA
22673 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22674 pielem->localName);
22675#endif
22676 }
22677
22678 /*
22679 * SPEC (2.4) "If the {content type} is element-only or mixed,
22680 * then the sequence of the element information item's
22681 * element information item [children], if any, taken in
22682 * order, is ·valid· with respect to the {content type}'s
22683 * particle, as defined in Element Sequence Locally Valid
22684 * (Particle) (§3.9.4)."
22685 */
22686 ret = xmlRegExecPushString2(regexCtxt,
22687 vctxt->inode->localName,
22688 vctxt->inode->nsName,
22689 vctxt->inode);
22690#ifdef DEBUG_AUTOMATA
22691 if (ret < 0)
22692 xmlGenericError(xmlGenericErrorContext,
22693 "AUTOMATON push ERROR for '%s' on '%s'\n",
22694 vctxt->inode->localName, pielem->localName);
22695 else
22696 xmlGenericError(xmlGenericErrorContext,
22697 "AUTOMATON push OK for '%s' on '%s'\n",
22698 vctxt->inode->localName, pielem->localName);
22699#endif
22700 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22701 VERROR_INT("xmlSchemaValidateChildElem",
22702 "calling xmlRegExecPushString2()");
22703 return (-1);
22704 }
22705 if (ret < 0) {
22706 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22707 &values[0], &terminal);
22708 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22709 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22710 "This element is not expected",
22711 nbval, nbneg, values);
22712 ret = vctxt->err;
22713 goto unexpected_elem;
22714 } else
22715 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022716 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022717 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022718 case XML_SCHEMA_CONTENT_SIMPLE:
22719 case XML_SCHEMA_CONTENT_BASIC:
22720 ACTIVATE_PARENT_ELEM
22721 if (IS_COMPLEX_TYPE(ptype)) {
22722 /*
22723 * SPEC (cvc-complex-type) (2.2)
22724 * "If the {content type} is a simple type definition, then
22725 * the element information item has no element information
22726 * item [children], ..."
22727 */
22728 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22729 VERROR(ret, NULL, "Element content is not allowed, "
22730 "because the content type is a simple type definition");
22731 } else {
22732 /*
22733 * SPEC (cvc-type) (3.1.2) "The element information item must
22734 * have no element information item [children]."
22735 */
22736 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22737 VERROR(ret, NULL, "Element content is not allowed, "
22738 "because the type definition is simple");
22739 }
22740 ACTIVATE_ELEM
22741 ret = vctxt->err;
22742 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022743 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022744
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022745 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022746 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022747 }
22748 return (ret);
22749unexpected_elem:
22750 /*
22751 * Pop this element and set the skipDepth to skip
22752 * all further content of the parent element.
22753 */
22754 vctxt->skipDepth = vctxt->depth;
22755 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22756 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22757 return (ret);
22758}
22759
22760#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22761#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22762#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22763
22764static int
22765xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22766 int nodeType, const xmlChar *value, int len,
22767 int mode, int *consumed)
22768{
22769 /*
22770 * Unfortunately we have to duplicate the text sometimes.
22771 * OPTIMIZE: Maybe we could skip it, if:
22772 * 1. content type is simple
22773 * 2. whitespace is "collapse"
22774 * 3. it consists of whitespace only
22775 *
22776 * Process character content.
22777 */
22778 if (consumed != NULL)
22779 *consumed = 0;
22780 if (INODE_NILLED(vctxt->inode)) {
22781 /*
22782 * SPEC cvc-elt (3.3.4 - 3.2.1)
22783 * "The element information item must have no character or
22784 * element information item [children]."
22785 */
22786 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22787 "Neither character nor element content is allowed "
22788 "because the element is 'nilled'");
22789 return (vctxt->err);
22790 }
22791 /*
22792 * SPEC (2.1) "If the {content type} is empty, then the
22793 * element information item has no character or element
22794 * information item [children]."
22795 */
22796 if (vctxt->inode->typeDef->contentType ==
22797 XML_SCHEMA_CONTENT_EMPTY) {
22798 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22799 "Character content is not allowed, "
22800 "because the content type is empty");
22801 return (vctxt->err);
22802 }
22803
22804 if (vctxt->inode->typeDef->contentType ==
22805 XML_SCHEMA_CONTENT_ELEMENTS) {
22806 if ((nodeType != XML_TEXT_NODE) ||
22807 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22808 /*
22809 * SPEC cvc-complex-type (2.3)
22810 * "If the {content type} is element-only, then the
22811 * element information item has no character information
22812 * item [children] other than those whose [character
22813 * code] is defined as a white space in [XML 1.0 (Second
22814 * Edition)]."
22815 */
22816 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22817 "Character content other than whitespace is not allowed "
22818 "because the content type is 'element-only'");
22819 return (vctxt->err);
22820 }
22821 return (0);
22822 }
22823
22824 if ((value == NULL) || (value[0] == 0))
22825 return (0);
22826 /*
22827 * Save the value.
22828 * NOTE that even if the content type is *mixed*, we need the
22829 * *initial value* for default/fixed value constraints.
22830 */
22831 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22832 ((vctxt->inode->decl == NULL) ||
22833 (vctxt->inode->decl->value == NULL)))
22834 return (0);
22835
22836 if (vctxt->inode->value == NULL) {
22837 /*
22838 * Set the value.
22839 */
22840 switch (mode) {
22841 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22842 /*
22843 * When working on a tree.
22844 */
22845 vctxt->inode->value = value;
22846 break;
22847 case XML_SCHEMA_PUSH_TEXT_CREATED:
22848 /*
22849 * When working with the reader.
22850 * The value will be freed by the element info.
22851 */
22852 vctxt->inode->value = value;
22853 if (consumed != NULL)
22854 *consumed = 1;
22855 vctxt->inode->flags |=
22856 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22857 break;
22858 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22859 /*
22860 * When working with SAX.
22861 * The value will be freed by the element info.
22862 */
22863 if (len != -1)
22864 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22865 else
22866 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22867 vctxt->inode->flags |=
22868 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22869 break;
22870 default:
22871 break;
22872 }
22873 } else {
22874 /*
22875 * Concat the value.
22876 */
22877 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022878 vctxt->inode->value = BAD_CAST xmlStrncat(
22879 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022880 } else {
22881 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022882 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022883 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22884 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022885 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022886
22887 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022888}
22889
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022890static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022891xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022892{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022893 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022894
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022895 if ((vctxt->skipDepth != -1) &&
22896 (vctxt->depth >= vctxt->skipDepth)) {
22897 VERROR_INT("xmlSchemaValidateElem",
22898 "in skip-state");
22899 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022900 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022901 if (vctxt->xsiAssemble) {
22902 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22903 goto internal_error;
22904 }
22905 if (vctxt->depth > 0) {
22906 /*
22907 * Validate this element against the content model
22908 * of the parent.
22909 */
22910 ret = xmlSchemaValidateChildElem(vctxt);
22911 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022912 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022913 VERROR_INT("xmlSchemaValidateElem",
22914 "calling xmlSchemaStreamValidateChildElement()");
22915 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022916 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022917 goto exit;
22918 }
22919 if (vctxt->depth == vctxt->skipDepth)
22920 goto exit;
22921 if ((vctxt->inode->decl == NULL) &&
22922 (vctxt->inode->typeDef == NULL)) {
22923 VERROR_INT("xmlSchemaValidateElem",
22924 "the child element was valid but neither the "
22925 "declaration nor the type was set");
22926 goto internal_error;
22927 }
22928 } else {
22929 /*
22930 * Get the declaration of the validation root.
22931 */
22932 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22933 vctxt->inode->localName,
22934 vctxt->inode->nsName);
22935 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022936 ret = XML_SCHEMAV_CVC_ELT_1;
22937 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022938 "No matching global declaration available "
22939 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022940 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022941 }
22942 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022943
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022944 if (vctxt->inode->decl == NULL)
22945 goto type_validation;
22946
22947 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22948 int skip;
22949 /*
22950 * Wildcards.
22951 */
22952 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22953 if (ret != 0) {
22954 if (ret < 0) {
22955 VERROR_INT("xmlSchemaValidateElem",
22956 "calling xmlSchemaValidateElemWildcard()");
22957 goto internal_error;
22958 }
22959 goto exit;
22960 }
22961 if (skip) {
22962 vctxt->skipDepth = vctxt->depth;
22963 goto exit;
22964 }
22965 /*
22966 * The declaration might be set by the wildcard validation,
22967 * when the processContents is "lax" or "strict".
22968 */
22969 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22970 /*
22971 * Clear the "decl" field to not confuse further processing.
22972 */
22973 vctxt->inode->decl = NULL;
22974 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022975 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022976 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022977 /*
22978 * Validate against the declaration.
22979 */
22980 ret = xmlSchemaValidateElemDecl(vctxt);
22981 if (ret != 0) {
22982 if (ret < 0) {
22983 VERROR_INT("xmlSchemaValidateElem",
22984 "calling xmlSchemaValidateElemDecl()");
22985 goto internal_error;
22986 }
22987 goto exit;
22988 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022989 /*
22990 * Validate against the type definition.
22991 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022992type_validation:
22993
22994 if (vctxt->inode->typeDef == NULL) {
22995 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22996 ret = XML_SCHEMAV_CVC_TYPE_1;
22997 VERROR(ret, NULL,
22998 "The type definition is absent");
22999 goto exit;
23000 }
23001 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
23002 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23003 ret = XML_SCHEMAV_CVC_TYPE_2;
23004 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023005 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023006 goto exit;
23007 }
23008 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023009 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023010 * during validation against the declaration. This must be done
23011 * _before_ attribute validation.
23012 */
23013 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
23014 if (ret == -1) {
23015 VERROR_INT("xmlSchemaValidateElem",
23016 "calling xmlSchemaXPathEvaluate()");
23017 goto internal_error;
23018 }
23019 /*
23020 * Validate attributes.
23021 */
23022 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
23023 if ((vctxt->nbAttrInfos != 0) ||
23024 (vctxt->inode->typeDef->attributeUses != NULL)) {
23025
23026 ret = xmlSchemaVAttributesComplex(vctxt);
23027 }
23028 } else if (vctxt->nbAttrInfos != 0) {
23029
23030 ret = xmlSchemaVAttributesSimple(vctxt);
23031 }
23032 /*
23033 * Clear registered attributes.
23034 */
23035 if (vctxt->nbAttrInfos != 0)
23036 xmlSchemaClearAttrInfos(vctxt);
23037 if (ret == -1) {
23038 VERROR_INT("xmlSchemaValidateElem",
23039 "calling attributes validation");
23040 goto internal_error;
23041 }
23042 /*
23043 * Don't return an error if attributes are invalid on purpose.
23044 */
23045 ret = 0;
23046
23047exit:
23048 if (ret != 0)
23049 vctxt->skipDepth = vctxt->depth;
23050 return (ret);
23051internal_error:
23052 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023053}
23054
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023055#ifdef XML_SCHEMA_READER_ENABLED
23056static int
23057xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023058{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023059 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23060 int depth, nodeType, ret = 0, consumed;
23061 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023062
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023063 vctxt->depth = -1;
23064 ret = xmlTextReaderRead(vctxt->reader);
23065 /*
23066 * Move to the document element.
23067 */
23068 while (ret == 1) {
23069 nodeType = xmlTextReaderNodeType(vctxt->reader);
23070 if (nodeType == XML_ELEMENT_NODE)
23071 goto root_found;
23072 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023073 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023074 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023075
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023076root_found:
23077
23078 do {
23079 depth = xmlTextReaderDepth(vctxt->reader);
23080 nodeType = xmlTextReaderNodeType(vctxt->reader);
23081
23082 if (nodeType == XML_ELEMENT_NODE) {
23083
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023084 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023085 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23086 VERROR_INT("xmlSchemaVReaderWalk",
23087 "calling xmlSchemaValidatorPushElem()");
23088 goto internal_error;
23089 }
23090 ielem = vctxt->inode;
23091 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23092 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23093 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23094 /*
23095 * Is the element empty?
23096 */
23097 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23098 if (ret == -1) {
23099 VERROR_INT("xmlSchemaVReaderWalk",
23100 "calling xmlTextReaderIsEmptyElement()");
23101 goto internal_error;
23102 }
23103 if (ret) {
23104 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23105 }
23106 /*
23107 * Register attributes.
23108 */
23109 vctxt->nbAttrInfos = 0;
23110 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23111 if (ret == -1) {
23112 VERROR_INT("xmlSchemaVReaderWalk",
23113 "calling xmlTextReaderMoveToFirstAttribute()");
23114 goto internal_error;
23115 }
23116 if (ret == 1) {
23117 do {
23118 /*
23119 * VAL TODO: How do we know that the reader works on a
23120 * node tree, to be able to pass a node here?
23121 */
23122 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23123 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23124 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23125 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23126
23127 VERROR_INT("xmlSchemaVReaderWalk",
23128 "calling xmlSchemaValidatorPushAttribute()");
23129 goto internal_error;
23130 }
23131 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23132 if (ret == -1) {
23133 VERROR_INT("xmlSchemaVReaderWalk",
23134 "calling xmlTextReaderMoveToFirstAttribute()");
23135 goto internal_error;
23136 }
23137 } while (ret == 1);
23138 /*
23139 * Back to element position.
23140 */
23141 ret = xmlTextReaderMoveToElement(vctxt->reader);
23142 if (ret == -1) {
23143 VERROR_INT("xmlSchemaVReaderWalk",
23144 "calling xmlTextReaderMoveToElement()");
23145 goto internal_error;
23146 }
23147 }
23148 /*
23149 * Validate the element.
23150 */
23151 ret= xmlSchemaValidateElem(vctxt);
23152 if (ret != 0) {
23153 if (ret == -1) {
23154 VERROR_INT("xmlSchemaVReaderWalk",
23155 "calling xmlSchemaValidateElem()");
23156 goto internal_error;
23157 }
23158 goto exit;
23159 }
23160 if (vctxt->depth == vctxt->skipDepth) {
23161 int curDepth;
23162 /*
23163 * Skip all content.
23164 */
23165 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23166 ret = xmlTextReaderRead(vctxt->reader);
23167 curDepth = xmlTextReaderDepth(vctxt->reader);
23168 while ((ret == 1) && (curDepth != depth)) {
23169 ret = xmlTextReaderRead(vctxt->reader);
23170 curDepth = xmlTextReaderDepth(vctxt->reader);
23171 }
23172 if (ret < 0) {
23173 /*
23174 * VAL TODO: A reader error occured; what to do here?
23175 */
23176 ret = 1;
23177 goto exit;
23178 }
23179 }
23180 goto leave_elem;
23181 }
23182 /*
23183 * READER VAL TODO: Is an END_ELEM really never called
23184 * if the elem is empty?
23185 */
23186 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23187 goto leave_elem;
23188 } else if (nodeType == END_ELEM) {
23189 /*
23190 * Process END of element.
23191 */
23192leave_elem:
23193 ret = xmlSchemaValidatorPopElem(vctxt);
23194 if (ret != 0) {
23195 if (ret < 0) {
23196 VERROR_INT("xmlSchemaVReaderWalk",
23197 "calling xmlSchemaValidatorPopElem()");
23198 goto internal_error;
23199 }
23200 goto exit;
23201 }
23202 if (vctxt->depth >= 0)
23203 ielem = vctxt->inode;
23204 else
23205 ielem = NULL;
23206 } else if ((nodeType == XML_TEXT_NODE) ||
23207 (nodeType == XML_CDATA_SECTION_NODE) ||
23208 (nodeType == WHTSP) ||
23209 (nodeType == SIGN_WHTSP)) {
23210 /*
23211 * Process character content.
23212 */
23213 xmlChar *value;
23214
23215 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23216 nodeType = XML_TEXT_NODE;
23217
23218 value = xmlTextReaderValue(vctxt->reader);
23219 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23220 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23221 if (! consumed)
23222 xmlFree(value);
23223 if (ret == -1) {
23224 VERROR_INT("xmlSchemaVReaderWalk",
23225 "calling xmlSchemaVPushText()");
23226 goto internal_error;
23227 }
23228 } else if ((nodeType == XML_ENTITY_NODE) ||
23229 (nodeType == XML_ENTITY_REF_NODE)) {
23230 /*
23231 * VAL TODO: What to do with entities?
23232 */
23233 TODO
23234 }
23235 /*
23236 * Read next node.
23237 */
23238 ret = xmlTextReaderRead(vctxt->reader);
23239 } while (ret == 1);
23240
23241exit:
23242 return (ret);
23243internal_error:
23244 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023245}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023246#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023247
23248/************************************************************************
23249 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023250 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023251 * *
23252 ************************************************************************/
23253
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023254#ifdef XML_SCHEMA_SAX_ENABLED
23255/*
23256* Process text content.
23257*/
23258static void
23259xmlSchemaSAXHandleText(void *ctx,
23260 const xmlChar * ch,
23261 int len)
23262{
23263 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23264
23265 if (vctxt->depth < 0)
23266 return;
23267 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23268 return;
23269 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23270 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23271 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23272 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23273 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23274 "calling xmlSchemaVPushText()");
23275 vctxt->err = -1;
23276 xmlStopParser(vctxt->parserCtxt);
23277 }
23278}
23279
23280/*
23281* Process CDATA content.
23282*/
23283static void
23284xmlSchemaSAXHandleCDataSection(void *ctx,
23285 const xmlChar * ch,
23286 int len)
23287{
23288 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23289
23290 if (vctxt->depth < 0)
23291 return;
23292 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23293 return;
23294 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23295 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23296 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23297 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23298 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23299 "calling xmlSchemaVPushText()");
23300 vctxt->err = -1;
23301 xmlStopParser(vctxt->parserCtxt);
23302 }
23303}
23304
23305static void
23306xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23307 const xmlChar * name ATTRIBUTE_UNUSED)
23308{
23309 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23310
23311 if (vctxt->depth < 0)
23312 return;
23313 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23314 return;
23315 /* SAX VAL TODO: What to do here? */
23316 TODO
23317}
23318
23319static void
23320xmlSchemaSAXHandleStartElementNs(void *ctx,
23321 const xmlChar * localname,
23322 const xmlChar * prefix ATTRIBUTE_UNUSED,
23323 const xmlChar * URI,
23324 int nb_namespaces,
23325 const xmlChar ** namespaces,
23326 int nb_attributes,
23327 int nb_defaulted ATTRIBUTE_UNUSED,
23328 const xmlChar ** attributes)
23329{
23330 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23331 int ret;
23332 xmlSchemaNodeInfoPtr ielem;
23333 int i, j;
23334
23335 /*
23336 * SAX VAL TODO: What to do with nb_defaulted?
23337 */
23338 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023339 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023340 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023341 vctxt->depth++;
23342 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023343 return;
23344 /*
23345 * Push the element.
23346 */
23347 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23348 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23349 "calling xmlSchemaValidatorPushElem()");
23350 goto internal_error;
23351 }
23352 ielem = vctxt->inode;
23353 ielem->localName = localname;
23354 ielem->nsName = URI;
23355 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23356 /*
23357 * Register namespaces on the elem info.
23358 */
23359 if (nb_namespaces != 0) {
23360 /*
23361 * Although the parser builds its own namespace list,
23362 * we have no access to it, so we'll use an own one.
23363 */
23364 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23365 /*
23366 * Store prefix and namespace name.
23367 */
23368 if (ielem->nsBindings == NULL) {
23369 ielem->nsBindings =
23370 (const xmlChar **) xmlMalloc(10 *
23371 sizeof(const xmlChar *));
23372 if (ielem->nsBindings == NULL) {
23373 xmlSchemaVErrMemory(vctxt,
23374 "allocating namespace bindings for SAX validation",
23375 NULL);
23376 goto internal_error;
23377 }
23378 ielem->nbNsBindings = 0;
23379 ielem->sizeNsBindings = 5;
23380 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23381 ielem->sizeNsBindings *= 2;
23382 ielem->nsBindings =
23383 (const xmlChar **) xmlRealloc(
23384 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023385 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023386 if (ielem->nsBindings == NULL) {
23387 xmlSchemaVErrMemory(vctxt,
23388 "re-allocating namespace bindings for SAX validation",
23389 NULL);
23390 goto internal_error;
23391 }
23392 }
23393
23394 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23395 if (namespaces[j+1][0] == 0) {
23396 /*
23397 * Handle xmlns="".
23398 */
23399 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23400 } else
23401 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23402 namespaces[j+1];
23403 ielem->nbNsBindings++;
23404 }
23405 }
23406 /*
23407 * Register attributes.
23408 * SAX VAL TODO: We are not adding namespace declaration
23409 * attributes yet.
23410 */
23411 if (nb_attributes != 0) {
23412 xmlChar *value;
23413
23414 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23415 /*
23416 * Duplicate the value.
23417 */
23418 value = xmlStrndup(attributes[j+3],
23419 attributes[j+4] - attributes[j+3]);
23420 ret = xmlSchemaValidatorPushAttribute(vctxt,
23421 NULL, attributes[j], attributes[j+2], 0,
23422 value, 1);
23423 if (ret == -1) {
23424 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23425 "calling xmlSchemaValidatorPushAttribute()");
23426 goto internal_error;
23427 }
23428 }
23429 }
23430 /*
23431 * Validate the element.
23432 */
23433 ret = xmlSchemaValidateElem(vctxt);
23434 if (ret != 0) {
23435 if (ret == -1) {
23436 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23437 "calling xmlSchemaValidateElem()");
23438 goto internal_error;
23439 }
23440 goto exit;
23441 }
23442
23443exit:
23444 return;
23445internal_error:
23446 vctxt->err = -1;
23447 xmlStopParser(vctxt->parserCtxt);
23448 return;
23449}
23450
23451static void
23452xmlSchemaSAXHandleEndElementNs(void *ctx,
23453 const xmlChar * localname ATTRIBUTE_UNUSED,
23454 const xmlChar * prefix ATTRIBUTE_UNUSED,
23455 const xmlChar * URI ATTRIBUTE_UNUSED)
23456{
23457 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23458 int res;
23459
23460 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023461 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023462 */
23463 if (vctxt->skipDepth != -1) {
23464 if (vctxt->depth > vctxt->skipDepth) {
23465 vctxt->depth--;
23466 return;
23467 } else
23468 vctxt->skipDepth = -1;
23469 }
23470 /*
23471 * SAX VAL TODO: Just a temporary check.
23472 */
23473 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23474 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23475 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23476 "elem pop mismatch");
23477 }
23478 res = xmlSchemaValidatorPopElem(vctxt);
23479 if (res != 0) {
23480 if (res < 0) {
23481 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23482 "calling xmlSchemaValidatorPopElem()");
23483 goto internal_error;
23484 }
23485 goto exit;
23486 }
23487exit:
23488 return;
23489internal_error:
23490 vctxt->err = -1;
23491 xmlStopParser(vctxt->parserCtxt);
23492 return;
23493}
23494#endif
23495
Daniel Veillard4255d502002-04-16 15:50:10 +000023496/************************************************************************
23497 * *
23498 * Validation interfaces *
23499 * *
23500 ************************************************************************/
23501
23502/**
23503 * xmlSchemaNewValidCtxt:
23504 * @schema: a precompiled XML Schemas
23505 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023506 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023507 *
23508 * Returns the validation context or NULL in case of error
23509 */
23510xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023511xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23512{
Daniel Veillard4255d502002-04-16 15:50:10 +000023513 xmlSchemaValidCtxtPtr ret;
23514
23515 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23516 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023517 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023518 return (NULL);
23519 }
23520 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023521 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23522 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023523 return (ret);
23524}
23525
23526/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023527 * xmlSchemaClearValidCtxt:
23528 * @ctxt: the schema validation context
23529 *
23530 * Free the resources associated to the schema validation context;
23531 * leaves some fields alive intended for reuse of the context.
23532 */
23533static void
23534xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23535{
23536 if (vctxt == NULL)
23537 return;
23538
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023539 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023540 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023541 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023542#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023543 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023544#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023545 if (vctxt->value != NULL) {
23546 xmlSchemaFreeValue(vctxt->value);
23547 vctxt->value = NULL;
23548 }
23549 /*
23550 * Augmented IDC information.
23551 */
23552 if (vctxt->aidcs != NULL) {
23553 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23554 do {
23555 next = cur->next;
23556 xmlFree(cur);
23557 cur = next;
23558 } while (cur != NULL);
23559 vctxt->aidcs = NULL;
23560 }
23561 if (vctxt->idcNodes != NULL) {
23562 int i;
23563 xmlSchemaPSVIIDCNodePtr item;
23564
23565 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023566 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023567 xmlFree(item->keys);
23568 xmlFree(item);
23569 }
23570 xmlFree(vctxt->idcNodes);
23571 vctxt->idcNodes = NULL;
23572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023573 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023574 * Note that we won't delete the XPath state pool here.
23575 */
23576 if (vctxt->xpathStates != NULL) {
23577 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23578 vctxt->xpathStates = NULL;
23579 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023580 /*
23581 * Attribute info.
23582 */
23583 if (vctxt->nbAttrInfos != 0) {
23584 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023586 /*
23587 * Element info.
23588 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023589 if (vctxt->elemInfos != NULL) {
23590 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023591 xmlSchemaNodeInfoPtr ei;
23592
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023593 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023594 ei = vctxt->elemInfos[i];
23595 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023596 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023597 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023598 }
23599 }
23600}
23601
23602/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023603 * xmlSchemaFreeValidCtxt:
23604 * @ctxt: the schema validation context
23605 *
23606 * Free the resources associated to the schema validation context
23607 */
23608void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023609xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23610{
Daniel Veillard4255d502002-04-16 15:50:10 +000023611 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023612 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023613 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023614 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023615 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023616 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023617 if (ctxt->idcNodes != NULL) {
23618 int i;
23619 xmlSchemaPSVIIDCNodePtr item;
23620
23621 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023622 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023623 xmlFree(item->keys);
23624 xmlFree(item);
23625 }
23626 xmlFree(ctxt->idcNodes);
23627 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023628 if (ctxt->idcKeys != NULL) {
23629 int i;
23630 for (i = 0; i < ctxt->nbIdcKeys; i++)
23631 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23632 xmlFree(ctxt->idcKeys);
23633 }
23634
23635 if (ctxt->xpathStates != NULL)
23636 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23637 if (ctxt->xpathStatePool != NULL)
23638 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23639
23640 /*
23641 * Augmented IDC information.
23642 */
23643 if (ctxt->aidcs != NULL) {
23644 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23645 do {
23646 next = cur->next;
23647 xmlFree(cur);
23648 cur = next;
23649 } while (cur != NULL);
23650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023651 if (ctxt->attrInfos != NULL) {
23652 int i;
23653 xmlSchemaAttrInfoPtr attr;
23654
23655 /* Just a paranoid call to the cleanup. */
23656 if (ctxt->nbAttrInfos != 0)
23657 xmlSchemaClearAttrInfos(ctxt);
23658 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23659 attr = ctxt->attrInfos[i];
23660 xmlFree(attr);
23661 }
23662 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023663 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023664 if (ctxt->elemInfos != NULL) {
23665 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023666 xmlSchemaNodeInfoPtr ei;
23667
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023668 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023669 ei = ctxt->elemInfos[i];
23670 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023671 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023672 xmlSchemaClearElemInfo(ei);
23673 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023674 }
23675 xmlFree(ctxt->elemInfos);
23676 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023677 if (ctxt->dict != NULL)
23678 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023679 xmlFree(ctxt);
23680}
23681
23682/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023683 * xmlSchemaIsValid:
23684 * @ctxt: the schema validation context
23685 *
23686 * Check if any error was detected during validation.
23687 *
23688 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23689 * of internal error.
23690 */
23691int
23692xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23693{
23694 if (ctxt == NULL)
23695 return(-1);
23696 return(ctxt->err == 0);
23697}
23698
23699/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023700 * xmlSchemaSetValidErrors:
23701 * @ctxt: a schema validation context
23702 * @err: the error function
23703 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023704 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023705 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023706 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023707 */
23708void
23709xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023710 xmlSchemaValidityErrorFunc err,
23711 xmlSchemaValidityWarningFunc warn, void *ctx)
23712{
Daniel Veillard4255d502002-04-16 15:50:10 +000023713 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023714 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023715 ctxt->error = err;
23716 ctxt->warning = warn;
23717 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023718 if (ctxt->pctxt != NULL)
23719 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023720}
23721
23722/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023723 * xmlSchemaSetValidStructuredErrors:
23724 * @ctxt: a schema validation context
23725 * @serror: the structured error function
23726 * @ctx: the functions context
23727 *
23728 * Set the structured error callback
23729 */
23730void
23731xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23732 xmlStructuredErrorFunc serror, void *ctx)
23733{
23734 if (ctxt == NULL)
23735 return;
23736 ctxt->serror = serror;
23737 ctxt->error = NULL;
23738 ctxt->warning = NULL;
23739 ctxt->userData = ctx;
23740}
23741
23742/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023743 * xmlSchemaGetValidErrors:
23744 * @ctxt: a XML-Schema validation context
23745 * @err: the error function result
23746 * @warn: the warning function result
23747 * @ctx: the functions context result
23748 *
23749 * Get the error and warning callback informations
23750 *
23751 * Returns -1 in case of error and 0 otherwise
23752 */
23753int
23754xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23755 xmlSchemaValidityErrorFunc * err,
23756 xmlSchemaValidityWarningFunc * warn, void **ctx)
23757{
23758 if (ctxt == NULL)
23759 return (-1);
23760 if (err != NULL)
23761 *err = ctxt->error;
23762 if (warn != NULL)
23763 *warn = ctxt->warning;
23764 if (ctx != NULL)
23765 *ctx = ctxt->userData;
23766 return (0);
23767}
23768
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023769
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023770/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023771 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023772 * @ctxt: a schema validation context
23773 * @options: a combination of xmlSchemaValidOption
23774 *
23775 * Sets the options to be used during the validation.
23776 *
23777 * Returns 0 in case of success, -1 in case of an
23778 * API error.
23779 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023780int
23781xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23782 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023783
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023784{
23785 int i;
23786
23787 if (ctxt == NULL)
23788 return (-1);
23789 /*
23790 * WARNING: Change the start value if adding to the
23791 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023792 * TODO: Is there an other, more easy to maintain,
23793 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023794 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023795 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023796 if (options & 1<<i)
23797 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023798 }
23799 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023800 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023801}
23802
23803/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023804 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023805 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023806 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023807 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023808 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023809 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023810 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023811int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023812xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023813
23814{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023815 if (ctxt == NULL)
23816 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023817 else
23818 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023819}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023820
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023821static int
23822xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23823{
23824 xmlAttrPtr attr;
23825 int ret = 0;
23826 xmlSchemaNodeInfoPtr ielem = NULL;
23827 xmlNodePtr node, valRoot;
23828 const xmlChar *nsName;
23829
23830 /* DOC VAL TODO: Move this to the start function. */
23831 valRoot = xmlDocGetRootElement(vctxt->doc);
23832 if (valRoot == NULL) {
23833 /* VAL TODO: Error code? */
23834 VERROR(1, NULL, "The document has no document element");
23835 return (1);
23836 }
23837 vctxt->depth = -1;
23838 vctxt->validationRoot = valRoot;
23839 node = valRoot;
23840 while (node != NULL) {
23841 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23842 goto next_sibling;
23843 if (node->type == XML_ELEMENT_NODE) {
23844
23845 /*
23846 * Init the node-info.
23847 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023848 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023849 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23850 goto internal_error;
23851 ielem = vctxt->inode;
23852 ielem->node = node;
23853 ielem->localName = node->name;
23854 if (node->ns != NULL)
23855 ielem->nsName = node->ns->href;
23856 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23857 /*
23858 * Register attributes.
23859 * DOC VAL TODO: We do not register namespace declaration
23860 * attributes yet.
23861 */
23862 vctxt->nbAttrInfos = 0;
23863 if (node->properties != NULL) {
23864 attr = node->properties;
23865 do {
23866 if (attr->ns != NULL)
23867 nsName = attr->ns->href;
23868 else
23869 nsName = NULL;
23870 ret = xmlSchemaValidatorPushAttribute(vctxt,
23871 (xmlNodePtr) attr,
23872 attr->name, nsName, 0,
23873 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23874 if (ret == -1) {
23875 VERROR_INT("xmlSchemaDocWalk",
23876 "calling xmlSchemaValidatorPushAttribute()");
23877 goto internal_error;
23878 }
23879 attr = attr->next;
23880 } while (attr);
23881 }
23882 /*
23883 * Validate the element.
23884 */
23885 ret = xmlSchemaValidateElem(vctxt);
23886 if (ret != 0) {
23887 if (ret == -1) {
23888 VERROR_INT("xmlSchemaDocWalk",
23889 "calling xmlSchemaValidateElem()");
23890 goto internal_error;
23891 }
23892 /*
23893 * Don't stop validation; just skip the content
23894 * of this element.
23895 */
23896 goto leave_node;
23897 }
23898 if ((vctxt->skipDepth != -1) &&
23899 (vctxt->depth >= vctxt->skipDepth))
23900 goto leave_node;
23901 } else if ((node->type == XML_TEXT_NODE) ||
23902 (node->type == XML_CDATA_SECTION_NODE)) {
23903 /*
23904 * Process character content.
23905 */
23906 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23907 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23908 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23909 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23910 if (ret < 0) {
23911 VERROR_INT("xmlSchemaVDocWalk",
23912 "calling xmlSchemaVPushText()");
23913 goto internal_error;
23914 }
23915 /*
23916 * DOC VAL TODO: Should we skip further validation of the
23917 * element content here?
23918 */
23919 } else if ((node->type == XML_ENTITY_NODE) ||
23920 (node->type == XML_ENTITY_REF_NODE)) {
23921 /*
23922 * DOC VAL TODO: What to do with entities?
23923 */
23924 TODO
23925 } else {
23926 goto leave_node;
23927 /*
23928 * DOC VAL TODO: XInclude nodes, etc.
23929 */
23930 }
23931 /*
23932 * Walk the doc.
23933 */
23934 if (node->children != NULL) {
23935 node = node->children;
23936 continue;
23937 }
23938leave_node:
23939 if (node->type == XML_ELEMENT_NODE) {
23940 /*
23941 * Leaving the scope of an element.
23942 */
23943 if (node != vctxt->inode->node) {
23944 VERROR_INT("xmlSchemaVDocWalk",
23945 "element position mismatch");
23946 goto internal_error;
23947 }
23948 ret = xmlSchemaValidatorPopElem(vctxt);
23949 if (ret != 0) {
23950 if (ret < 0) {
23951 VERROR_INT("xmlSchemaVDocWalk",
23952 "calling xmlSchemaValidatorPopElem()");
23953 goto internal_error;
23954 }
23955 }
23956 if (node == valRoot)
23957 goto exit;
23958 }
23959next_sibling:
23960 if (node->next != NULL)
23961 node = node->next;
23962 else {
23963 node = node->parent;
23964 goto leave_node;
23965 }
23966 }
23967
23968exit:
23969 return (ret);
23970internal_error:
23971 return (-1);
23972}
23973
23974static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023975xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023976 /*
23977 * Some initialization.
23978 */
23979 vctxt->err = 0;
23980 vctxt->nberrors = 0;
23981 vctxt->depth = -1;
23982 vctxt->skipDepth = -1;
23983 /*
23984 * Create a schema + parser if necessary.
23985 */
23986 if (vctxt->schema == NULL) {
23987
23988 if ((vctxt->pctxt == NULL) &&
23989 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23990 return (-1);
23991
23992 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23993 if (vctxt->schema == NULL) {
23994 VERROR_INT("xmlSchemaVStartValidation",
23995 "creating a schema");
23996 return (-1);
23997 }
23998 vctxt->xsiAssemble = 1;
23999 } else
24000 vctxt->xsiAssemble = 0;
24001 /*
24002 * Augment the IDC definitions.
24003 */
24004 if (vctxt->schema->idcDef != NULL) {
24005 xmlHashScan(vctxt->schema->idcDef,
24006 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
24007 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000024008 return(0);
24009}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024010
Daniel Veillardf10ae122005-07-10 19:03:16 +000024011static void
24012xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024013 if (vctxt->xsiAssemble) {
24014 if (vctxt->schema != NULL) {
24015 xmlSchemaFree(vctxt->schema);
24016 vctxt->schema = NULL;
24017 }
24018 }
24019 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024020}
24021
24022static int
24023xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
24024{
24025 int ret = 0;
24026
24027 if (xmlSchemaPreRun(vctxt) < 0)
24028 return(-1);
24029
24030 if (vctxt->doc != NULL) {
24031 /*
24032 * Tree validation.
24033 */
24034 ret = xmlSchemaVDocWalk(vctxt);
24035#ifdef LIBXML_READER_ENABLED
24036 } else if (vctxt->reader != NULL) {
24037 /*
24038 * XML Reader validation.
24039 */
24040#ifdef XML_SCHEMA_READER_ENABLED
24041 ret = xmlSchemaVReaderWalk(vctxt);
24042#endif
24043#endif
24044 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24045 /*
24046 * SAX validation.
24047 */
24048 ret = xmlParseDocument(vctxt->parserCtxt);
24049 } else {
24050 VERROR_INT("xmlSchemaVStartValidation",
24051 "no instance to validate");
24052 ret = -1;
24053 }
24054
24055 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024056 if (ret == 0)
24057 ret = vctxt->err;
24058 return (ret);
24059}
24060
24061/**
24062 * xmlSchemaValidateOneElement:
24063 * @ctxt: a schema validation context
24064 * @elem: an element node
24065 *
24066 * Validate a branch of a tree, starting with the given @elem.
24067 *
24068 * Returns 0 if the element and its subtree is valid, a positive error
24069 * code number otherwise and -1 in case of an internal or API error.
24070 */
24071int
24072xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24073{
24074 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24075 return (-1);
24076
24077 if (ctxt->schema == NULL)
24078 return (-1);
24079
24080 ctxt->doc = elem->doc;
24081 ctxt->node = elem;
24082 ctxt->validationRoot = elem;
24083 return(xmlSchemaVStart(ctxt));
24084}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024085
Daniel Veillard259f0df2004-08-18 09:13:18 +000024086/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024087 * xmlSchemaValidateDoc:
24088 * @ctxt: a schema validation context
24089 * @doc: a parsed document tree
24090 *
24091 * Validate a document tree in memory.
24092 *
24093 * Returns 0 if the document is schemas valid, a positive error code
24094 * number otherwise and -1 in case of internal or API error.
24095 */
24096int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024097xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24098{
Daniel Veillard4255d502002-04-16 15:50:10 +000024099 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024100 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024101
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024102 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024103 ctxt->node = xmlDocGetRootElement(doc);
24104 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024105 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024106 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24107 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024108 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024109 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024110 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024111 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024112 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024113}
24114
Daniel Veillardcdc82732005-07-08 15:04:06 +000024115
24116/************************************************************************
24117 * *
24118 * Function and data for SAX streaming API *
24119 * *
24120 ************************************************************************/
24121typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24122typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24123
24124struct _xmlSchemaSplitSAXData {
24125 xmlSAXHandlerPtr user_sax;
24126 void *user_data;
24127 xmlSchemaValidCtxtPtr ctxt;
24128 xmlSAXHandlerPtr schemas_sax;
24129};
24130
Daniel Veillard971771e2005-07-09 17:32:57 +000024131#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24132
24133struct _xmlSchemaSAXPlug {
24134 unsigned int magic;
24135
24136 /* the original callbacks informations */
24137 xmlSAXHandlerPtr *user_sax_ptr;
24138 xmlSAXHandlerPtr user_sax;
24139 void **user_data_ptr;
24140 void *user_data;
24141
24142 /* the block plugged back and validation informations */
24143 xmlSAXHandler schemas_sax;
24144 xmlSchemaValidCtxtPtr ctxt;
24145};
24146
Daniel Veillardcdc82732005-07-08 15:04:06 +000024147/* All those functions just bounces to the user provided SAX handlers */
24148static void
24149internalSubsetSplit(void *ctx, const xmlChar *name,
24150 const xmlChar *ExternalID, const xmlChar *SystemID)
24151{
Daniel Veillard971771e2005-07-09 17:32:57 +000024152 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024153 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24154 (ctxt->user_sax->internalSubset != NULL))
24155 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24156 SystemID);
24157}
24158
24159static int
24160isStandaloneSplit(void *ctx)
24161{
Daniel Veillard971771e2005-07-09 17:32:57 +000024162 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024163 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24164 (ctxt->user_sax->isStandalone != NULL))
24165 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24166 return(0);
24167}
24168
24169static int
24170hasInternalSubsetSplit(void *ctx)
24171{
Daniel Veillard971771e2005-07-09 17:32:57 +000024172 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024173 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24174 (ctxt->user_sax->hasInternalSubset != NULL))
24175 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24176 return(0);
24177}
24178
24179static int
24180hasExternalSubsetSplit(void *ctx)
24181{
Daniel Veillard971771e2005-07-09 17:32:57 +000024182 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024183 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24184 (ctxt->user_sax->hasExternalSubset != NULL))
24185 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24186 return(0);
24187}
24188
24189static void
24190externalSubsetSplit(void *ctx, const xmlChar *name,
24191 const xmlChar *ExternalID, const xmlChar *SystemID)
24192{
Daniel Veillard971771e2005-07-09 17:32:57 +000024193 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024194 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24195 (ctxt->user_sax->internalSubset != NULL))
24196 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24197 SystemID);
24198}
24199
24200static xmlParserInputPtr
24201resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24202{
Daniel Veillard971771e2005-07-09 17:32:57 +000024203 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024204 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24205 (ctxt->user_sax->resolveEntity != NULL))
24206 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24207 systemId));
24208 return(NULL);
24209}
24210
24211static xmlEntityPtr
24212getEntitySplit(void *ctx, const xmlChar *name)
24213{
Daniel Veillard971771e2005-07-09 17:32:57 +000024214 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024215 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24216 (ctxt->user_sax->getEntity != NULL))
24217 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24218 return(NULL);
24219}
24220
24221static xmlEntityPtr
24222getParameterEntitySplit(void *ctx, const xmlChar *name)
24223{
Daniel Veillard971771e2005-07-09 17:32:57 +000024224 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024225 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24226 (ctxt->user_sax->getParameterEntity != NULL))
24227 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24228 return(NULL);
24229}
24230
24231
24232static void
24233entityDeclSplit(void *ctx, const xmlChar *name, int type,
24234 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24235{
Daniel Veillard971771e2005-07-09 17:32:57 +000024236 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024237 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24238 (ctxt->user_sax->entityDecl != NULL))
24239 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24240 systemId, content);
24241}
24242
24243static void
24244attributeDeclSplit(void *ctx, const xmlChar * elem,
24245 const xmlChar * name, int type, int def,
24246 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24247{
Daniel Veillard971771e2005-07-09 17:32:57 +000024248 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024249 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24250 (ctxt->user_sax->attributeDecl != NULL)) {
24251 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24252 def, defaultValue, tree);
24253 } else {
24254 xmlFreeEnumeration(tree);
24255 }
24256}
24257
24258static void
24259elementDeclSplit(void *ctx, const xmlChar *name, int type,
24260 xmlElementContentPtr content)
24261{
Daniel Veillard971771e2005-07-09 17:32:57 +000024262 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024263 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24264 (ctxt->user_sax->elementDecl != NULL))
24265 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24266}
24267
24268static void
24269notationDeclSplit(void *ctx, const xmlChar *name,
24270 const xmlChar *publicId, const xmlChar *systemId)
24271{
Daniel Veillard971771e2005-07-09 17:32:57 +000024272 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024273 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24274 (ctxt->user_sax->notationDecl != NULL))
24275 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24276 systemId);
24277}
24278
24279static void
24280unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24281 const xmlChar *publicId, const xmlChar *systemId,
24282 const xmlChar *notationName)
24283{
Daniel Veillard971771e2005-07-09 17:32:57 +000024284 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024285 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24286 (ctxt->user_sax->unparsedEntityDecl != NULL))
24287 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24288 systemId, notationName);
24289}
24290
24291static void
24292setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24293{
Daniel Veillard971771e2005-07-09 17:32:57 +000024294 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024295 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24296 (ctxt->user_sax->setDocumentLocator != NULL))
24297 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24298}
24299
24300static void
24301startDocumentSplit(void *ctx)
24302{
Daniel Veillard971771e2005-07-09 17:32:57 +000024303 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024304 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24305 (ctxt->user_sax->startDocument != NULL))
24306 ctxt->user_sax->startDocument(ctxt->user_data);
24307}
24308
24309static void
24310endDocumentSplit(void *ctx)
24311{
Daniel Veillard971771e2005-07-09 17:32:57 +000024312 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024313 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24314 (ctxt->user_sax->endDocument != NULL))
24315 ctxt->user_sax->endDocument(ctxt->user_data);
24316}
24317
24318static void
24319processingInstructionSplit(void *ctx, const xmlChar *target,
24320 const xmlChar *data)
24321{
Daniel Veillard971771e2005-07-09 17:32:57 +000024322 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024323 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24324 (ctxt->user_sax->processingInstruction != NULL))
24325 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24326}
24327
24328static void
24329commentSplit(void *ctx, const xmlChar *value)
24330{
Daniel Veillard971771e2005-07-09 17:32:57 +000024331 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024332 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24333 (ctxt->user_sax->comment != NULL))
24334 ctxt->user_sax->comment(ctxt->user_data, value);
24335}
24336
24337/*
24338 * Varargs error callbacks to the user application, harder ...
24339 */
24340
Daniel Veillardffa3c742005-07-21 13:24:09 +000024341static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024342warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024343 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024344 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24345 (ctxt->user_sax->warning != NULL)) {
24346 TODO
24347 }
24348}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024349static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024350errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024351 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024352 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24353 (ctxt->user_sax->error != NULL)) {
24354 TODO
24355 }
24356}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024357static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024358fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024359 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024360 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24361 (ctxt->user_sax->fatalError != NULL)) {
24362 TODO
24363 }
24364}
24365
24366/*
24367 * Those are function where both the user handler and the schemas handler
24368 * need to be called.
24369 */
24370static void
24371charactersSplit(void *ctx, const xmlChar *ch, int len)
24372{
Daniel Veillard971771e2005-07-09 17:32:57 +000024373 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024374 if (ctxt == NULL)
24375 return;
24376 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24377 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24378 if (ctxt->ctxt != NULL)
24379 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24380}
24381
24382static void
24383ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24384{
Daniel Veillard971771e2005-07-09 17:32:57 +000024385 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024386 if (ctxt == NULL)
24387 return;
24388 if ((ctxt->user_sax != NULL) &&
24389 (ctxt->user_sax->ignorableWhitespace != NULL))
24390 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24391 if (ctxt->ctxt != NULL)
24392 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24393}
24394
24395static void
24396cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24397{
Daniel Veillard971771e2005-07-09 17:32:57 +000024398 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024399 if (ctxt == NULL)
24400 return;
24401 if ((ctxt->user_sax != NULL) &&
24402 (ctxt->user_sax->ignorableWhitespace != NULL))
24403 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24404 if (ctxt->ctxt != NULL)
24405 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24406}
24407
24408static void
24409referenceSplit(void *ctx, const xmlChar *name)
24410{
Daniel Veillard971771e2005-07-09 17:32:57 +000024411 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024412 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24413 (ctxt->user_sax->reference != NULL))
24414 ctxt->user_sax->reference(ctxt->user_data, name);
24415 if (ctxt->ctxt != NULL)
24416 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24417}
24418
24419static void
24420startElementNsSplit(void *ctx, const xmlChar * localname,
24421 const xmlChar * prefix, const xmlChar * URI,
24422 int nb_namespaces, const xmlChar ** namespaces,
24423 int nb_attributes, int nb_defaulted,
24424 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024425 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024426 if (ctxt == NULL)
24427 return;
24428 if ((ctxt->user_sax != NULL) &&
24429 (ctxt->user_sax->startElementNs != NULL))
24430 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24431 URI, nb_namespaces, namespaces,
24432 nb_attributes, nb_defaulted,
24433 attributes);
24434 if (ctxt->ctxt != NULL)
24435 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24436 URI, nb_namespaces, namespaces,
24437 nb_attributes, nb_defaulted,
24438 attributes);
24439}
24440
24441static void
24442endElementNsSplit(void *ctx, const xmlChar * localname,
24443 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024444 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024445 if (ctxt == NULL)
24446 return;
24447 if ((ctxt->user_sax != NULL) &&
24448 (ctxt->user_sax->endElementNs != NULL))
24449 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24450 if (ctxt->ctxt != NULL)
24451 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24452}
24453
Daniel Veillard4255d502002-04-16 15:50:10 +000024454/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024455 * xmlSchemaSAXPlug:
24456 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024457 * @sax: a pointer to the original xmlSAXHandlerPtr
24458 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024459 *
24460 * Plug a SAX based validation layer in a SAX parsing event flow.
24461 * The original @saxptr and @dataptr data are replaced by new pointers
24462 * but the calls to the original will be maintained.
24463 *
24464 * Returns a pointer to a data structure needed to unplug the validation layer
24465 * or NULL in case of errors.
24466 */
24467xmlSchemaSAXPlugPtr
24468xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24469 xmlSAXHandlerPtr *sax, void **user_data)
24470{
24471 xmlSchemaSAXPlugPtr ret;
24472 xmlSAXHandlerPtr old_sax;
24473
24474 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24475 return(NULL);
24476
24477 /*
24478 * We only allow to plug into SAX2 event streams
24479 */
24480 old_sax = *sax;
24481 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24482 return(NULL);
24483 if ((old_sax != NULL) &&
24484 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24485 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24486 return(NULL);
24487
24488 /*
24489 * everything seems right allocate the local data needed for that layer
24490 */
24491 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24492 if (ret == NULL) {
24493 return(NULL);
24494 }
24495 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24496 ret->magic = XML_SAX_PLUG_MAGIC;
24497 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24498 ret->ctxt = ctxt;
24499 ret->user_sax_ptr = sax;
24500 ret->user_sax = old_sax;
24501 if (old_sax == NULL) {
24502 /*
24503 * go direct, no need for the split block and functions.
24504 */
24505 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24506 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24507 /*
24508 * Note that we use the same text-function for both, to prevent
24509 * the parser from testing for ignorable whitespace.
24510 */
24511 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24512 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24513
24514 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24515 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24516
24517 ret->user_data = ctxt;
24518 *user_data = ctxt;
24519 } else {
24520 /*
24521 * for each callback unused by Schemas initialize it to the Split
24522 * routine only if non NULL in the user block, this can speed up
24523 * things at the SAX level.
24524 */
24525 if (old_sax->internalSubset != NULL)
24526 ret->schemas_sax.internalSubset = internalSubsetSplit;
24527 if (old_sax->isStandalone != NULL)
24528 ret->schemas_sax.isStandalone = isStandaloneSplit;
24529 if (old_sax->hasInternalSubset != NULL)
24530 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24531 if (old_sax->hasExternalSubset != NULL)
24532 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24533 if (old_sax->resolveEntity != NULL)
24534 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24535 if (old_sax->getEntity != NULL)
24536 ret->schemas_sax.getEntity = getEntitySplit;
24537 if (old_sax->entityDecl != NULL)
24538 ret->schemas_sax.entityDecl = entityDeclSplit;
24539 if (old_sax->notationDecl != NULL)
24540 ret->schemas_sax.notationDecl = notationDeclSplit;
24541 if (old_sax->attributeDecl != NULL)
24542 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24543 if (old_sax->elementDecl != NULL)
24544 ret->schemas_sax.elementDecl = elementDeclSplit;
24545 if (old_sax->unparsedEntityDecl != NULL)
24546 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24547 if (old_sax->setDocumentLocator != NULL)
24548 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24549 if (old_sax->startDocument != NULL)
24550 ret->schemas_sax.startDocument = startDocumentSplit;
24551 if (old_sax->endDocument != NULL)
24552 ret->schemas_sax.endDocument = endDocumentSplit;
24553 if (old_sax->processingInstruction != NULL)
24554 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24555 if (old_sax->comment != NULL)
24556 ret->schemas_sax.comment = commentSplit;
24557 if (old_sax->warning != NULL)
24558 ret->schemas_sax.warning = warningSplit;
24559 if (old_sax->error != NULL)
24560 ret->schemas_sax.error = errorSplit;
24561 if (old_sax->fatalError != NULL)
24562 ret->schemas_sax.fatalError = fatalErrorSplit;
24563 if (old_sax->getParameterEntity != NULL)
24564 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24565 if (old_sax->externalSubset != NULL)
24566 ret->schemas_sax.externalSubset = externalSubsetSplit;
24567
24568 /*
24569 * the 6 schemas callback have to go to the splitter functions
24570 * Note that we use the same text-function for ignorableWhitespace
24571 * if possible, to prevent the parser from testing for ignorable
24572 * whitespace.
24573 */
24574 ret->schemas_sax.characters = charactersSplit;
24575 if ((old_sax->ignorableWhitespace != NULL) &&
24576 (old_sax->ignorableWhitespace != old_sax->characters))
24577 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24578 else
24579 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24580 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24581 ret->schemas_sax.reference = referenceSplit;
24582 ret->schemas_sax.startElementNs = startElementNsSplit;
24583 ret->schemas_sax.endElementNs = endElementNsSplit;
24584
24585 ret->user_data_ptr = user_data;
24586 ret->user_data = *user_data;
24587 *user_data = ret;
24588 }
24589
24590 /*
24591 * plug the pointers back.
24592 */
24593 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024594 ctxt->sax = *sax;
24595 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24596 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024597 return(ret);
24598}
24599
24600/**
24601 * xmlSchemaSAXUnplug:
24602 * @plug: a data structure returned by xmlSchemaSAXPlug
24603 *
24604 * Unplug a SAX based validation layer in a SAX parsing event flow.
24605 * The original pointers used in the call are restored.
24606 *
24607 * Returns 0 in case of success and -1 in case of failure.
24608 */
24609int
24610xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24611{
24612 xmlSAXHandlerPtr *sax;
24613 void **user_data;
24614
24615 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24616 return(-1);
24617 plug->magic = 0;
24618
Daniel Veillardf10ae122005-07-10 19:03:16 +000024619 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024620 /* restore the data */
24621 sax = plug->user_sax_ptr;
24622 *sax = plug->user_sax;
24623 if (plug->user_sax != NULL) {
24624 user_data = plug->user_data_ptr;
24625 *user_data = plug->user_data;
24626 }
24627
24628 /* free and return */
24629 xmlFree(plug);
24630 return(0);
24631}
24632
24633/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024634 * xmlSchemaValidateStream:
24635 * @ctxt: a schema validation context
24636 * @input: the input to use for reading the data
24637 * @enc: an optional encoding information
24638 * @sax: a SAX handler for the resulting events
24639 * @user_data: the context to provide to the SAX handler.
24640 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024641 * Validate an input based on a flow of SAX event from the parser
24642 * and forward the events to the @sax handler with the provided @user_data
24643 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024644 *
24645 * Returns 0 if the document is schemas valid, a positive error code
24646 * number otherwise and -1 in case of internal or API error.
24647 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024648int
Daniel Veillard4255d502002-04-16 15:50:10 +000024649xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024650 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24651 xmlSAXHandlerPtr sax, void *user_data)
24652{
Daniel Veillard971771e2005-07-09 17:32:57 +000024653 xmlSchemaSAXPlugPtr plug = NULL;
24654 xmlSAXHandlerPtr old_sax = NULL;
24655 xmlParserCtxtPtr pctxt = NULL;
24656 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024657 int ret;
24658
Daniel Veillard4255d502002-04-16 15:50:10 +000024659 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024660 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024661
Daniel Veillardcdc82732005-07-08 15:04:06 +000024662 /*
24663 * prepare the parser
24664 */
24665 pctxt = xmlNewParserCtxt();
24666 if (pctxt == NULL)
24667 return (-1);
24668 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024669 pctxt->sax = sax;
24670 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024671#if 0
24672 if (options)
24673 xmlCtxtUseOptions(pctxt, options);
24674#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024675 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024676
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024677 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024678 if (inputStream == NULL) {
24679 ret = -1;
24680 goto done;
24681 }
24682 inputPush(pctxt, inputStream);
24683 ctxt->parserCtxt = pctxt;
24684 ctxt->input = input;
24685
24686 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024687 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024688 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024689 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24690 if (plug == NULL) {
24691 ret = -1;
24692 goto done;
24693 }
24694 ctxt->input = input;
24695 ctxt->enc = enc;
24696 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024697 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24698 ret = xmlSchemaVStart(ctxt);
24699
24700 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24701 ret = ctxt->parserCtxt->errNo;
24702 if (ret == 0)
24703 ret = 1;
24704 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024705
24706done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024707 ctxt->parserCtxt = NULL;
24708 ctxt->sax = NULL;
24709 ctxt->input = NULL;
24710 if (plug != NULL) {
24711 xmlSchemaSAXUnplug(plug);
24712 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024713 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024714 if (pctxt != NULL) {
24715 pctxt->sax = old_sax;
24716 xmlFreeParserCtxt(pctxt);
24717 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024718 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024719}
24720
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024721/**
24722 * xmlSchemaValidateFile:
24723 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024724 * @filename: the URI of the instance
24725 * @options: a future set of options, currently unused
24726 *
24727 * Do a schemas validation of the given resource, it will use the
24728 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024729 *
24730 * Returns 0 if the document is valid, a positive error code
24731 * number otherwise and -1 in case of an internal or API error.
24732 */
24733int
24734xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024735 const char * filename,
24736 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024737{
Daniel Veillard81562d22005-06-15 13:27:56 +000024738#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024739 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024740 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024741
24742 if ((ctxt == NULL) || (filename == NULL))
24743 return (-1);
24744
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024745 input = xmlParserInputBufferCreateFilename(filename,
24746 XML_CHAR_ENCODING_NONE);
24747 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024748 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024749 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24750 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024751 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024752#else
24753 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024754#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024755}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024756
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024757#define bottom_xmlschemas
24758#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024759#endif /* LIBXML_SCHEMAS_ENABLED */