blob: 45b79be4cc20e69bf94ef8b99a07b470f1d553e5 [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");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001574 int line = 0;
1575 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001576
1577 vctxt->nberrors++;
1578 vctxt->err = error;
1579 channel = vctxt->error;
1580 schannel = vctxt->serror;
1581 data = vctxt->userData;
1582 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001583 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001585 }
1586 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1587 (vctxt->parserCtxt->input != NULL)) {
1588 file = vctxt->parserCtxt->input->filename;
1589 line = vctxt->parserCtxt->input->line;
1590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 __xmlRaiseError(schannel, channel, data, ctxt,
1592 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 (const char *) str1, (const char *) str2,
1595 (const char *) str3, 0, 0, msg, str1, str2, str3);
1596
1597 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1598 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1599
1600 pctxt->nberrors++;
1601 pctxt->err = error;
1602 channel = pctxt->error;
1603 schannel = pctxt->serror;
1604 data = pctxt->userData;
1605 __xmlRaiseError(schannel, channel, data, ctxt,
1606 node, XML_FROM_SCHEMASP,
1607 error, XML_ERR_ERROR, NULL, 0,
1608 (const char *) str1, (const char *) str2,
1609 (const char *) str3, 0, 0, msg, str1, str2, str3);
1610 } else {
1611 TODO
1612 }
1613 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static void
1617xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1618 int error, xmlNodePtr node, const char *msg,
1619 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001620{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static xmlChar *
1625xmlSchemaFormatNodeForError(xmlChar ** msg,
1626 xmlSchemaAbstractCtxtPtr actxt,
1627 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628{
1629 xmlChar *str = NULL;
1630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 if (node != NULL) {
1632 /*
1633 * Work on tree nodes.
1634 */
1635 if (node->type == XML_ATTRIBUTE_NODE) {
1636 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 *msg = xmlStrdup(BAD_CAST "Element '");
1639 if (elem->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, elem->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1647 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1648 } else {
1649 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 if (node->ns != NULL)
1652 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1653 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1656 NULL, node->name));
1657 FREE_AND_NULL(str);
1658 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1659 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1660 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1661 /*
1662 * Work on node infos.
1663 */
1664 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1665 xmlSchemaNodeInfoPtr ielem =
1666 vctxt->elemInfos[vctxt->depth];
1667
1668 *msg = xmlStrdup(BAD_CAST "Element '");
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 ielem->nsName, ielem->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1673 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1674 } else {
1675 *msg = xmlStrdup(BAD_CAST "Element '");
1676 }
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 vctxt->inode->nsName, vctxt->inode->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1681 } else {
1682 TODO
1683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 /*
1686 * VAL TODO: The output of the given schema component is currently
1687 * disabled.
1688 */
1689#if 0
1690 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1691 *msg = xmlStrcat(*msg, BAD_CAST " [");
1692 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1693 NULL, type, NULL, 0));
1694 FREE_AND_NULL(str)
1695 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697#endif
1698 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699}
1700
Daniel Veillardc0826a72004-08-10 14:17:33 +00001701static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1703 const char *funcName,
1704 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 xmlChar *msg = NULL;
1707
1708 msg = xmlStrdup(BAD_CAST "Internal error: ");
1709 msg = xmlStrcat(msg, BAD_CAST funcName);
1710 msg = xmlStrcat(msg, BAD_CAST ", ");
1711 msg = xmlStrcat(msg, BAD_CAST message);
1712 msg = xmlStrcat(msg, BAD_CAST ".\n");
1713
1714 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1715 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1716 (const char *) msg, NULL, NULL);
1717
1718 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1719 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1720 (const char *) msg, NULL, NULL);
1721
1722 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723}
1724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725static void
1726xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1730 const char *message,
1731 const xmlChar *str1,
1732 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001733{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001735
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001736 xmlSchemaFormatNodeForError(&msg, actxt, node);
1737 msg = xmlStrcat(msg, (const xmlChar *) message);
1738 msg = xmlStrcat(msg, BAD_CAST ".\n");
1739 xmlSchemaErr(actxt, error, node,
1740 (const char *) msg, str1, str2);
1741 FREE_AND_NULL(msg)
1742}
1743
1744static int
1745xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlNodePtr node)
1747{
1748 if (node != NULL)
1749 return (node->type);
1750 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1751 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1752 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1753 return (-1);
1754}
1755
1756static int
1757xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1758{
1759 switch (item->type) {
1760 case XML_SCHEMA_TYPE_COMPLEX:
1761 case XML_SCHEMA_TYPE_SIMPLE:
1762 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1763 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 case XML_SCHEMA_TYPE_GROUP:
1766 return (1);
1767 case XML_SCHEMA_TYPE_ELEMENT:
1768 if ( ((xmlSchemaElementPtr) item)->flags &
1769 XML_SCHEMAS_ELEM_GLOBAL)
1770 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001771 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 case XML_SCHEMA_TYPE_ATTRIBUTE:
1773 if ( ((xmlSchemaAttributePtr) item)->flags &
1774 XML_SCHEMAS_ATTR_GLOBAL)
1775 return(1);
1776 break;
1777 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001778 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001779 return(1);
1780 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001781 return (0);
1782}
1783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001784static void
1785xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlParserErrors error,
1787 xmlNodePtr node,
1788 const xmlChar *value,
1789 xmlSchemaTypePtr type,
1790 int displayValue)
1791{
1792 xmlChar *msg = NULL;
1793
1794 xmlSchemaFormatNodeForError(&msg, actxt, node);
1795
1796 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1797 XML_ATTRIBUTE_NODE))
1798 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1799 else
1800 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1801 "value of ");
1802
1803 if (! xmlSchemaIsGlobalItem(type))
1804 msg = xmlStrcat(msg, BAD_CAST "the local ");
1805 else
1806 msg = xmlStrcat(msg, BAD_CAST "the ");
1807
1808 if (VARIETY_ATOMIC(type))
1809 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1810 else if (VARIETY_LIST(type))
1811 msg = xmlStrcat(msg, BAD_CAST "list type");
1812 else if (VARIETY_UNION(type))
1813 msg = xmlStrcat(msg, BAD_CAST "union type");
1814
1815 if (xmlSchemaIsGlobalItem(type)) {
1816 xmlChar *str = NULL;
1817 msg = xmlStrcat(msg, BAD_CAST " '");
1818 if (type->builtInType != 0) {
1819 msg = xmlStrcat(msg, BAD_CAST "xs:");
1820 msg = xmlStrcat(msg, type->name);
1821 } else
1822 msg = xmlStrcat(msg,
1823 xmlSchemaFormatQName(&str,
1824 type->targetNamespace, type->name));
1825 msg = xmlStrcat(msg, BAD_CAST "'");
1826 FREE_AND_NULL(str);
1827 }
1828 msg = xmlStrcat(msg, BAD_CAST ".\n");
1829 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1830 XML_ATTRIBUTE_NODE))
1831 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1832 else
1833 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1834 FREE_AND_NULL(msg)
1835}
1836
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1839 xmlSchemaNodeInfoPtr ni,
1840 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842 if (node != NULL) {
1843 if (node->ns != NULL)
1844 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1845 else
1846 return (xmlSchemaFormatQName(str, NULL, node->name));
1847 } else if (ni != NULL)
1848 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850}
1851
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1854 xmlParserErrors error,
1855 xmlSchemaAttrInfoPtr ni,
1856 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 xmlChar *msg = NULL, *str = NULL;
1859
1860 xmlSchemaFormatNodeForError(&msg, actxt, node);
1861 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1862 xmlSchemaErr(actxt, error, node, (const char *) msg,
1863 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1864 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001865 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867}
1868
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001870xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1871 xmlParserErrors error,
1872 xmlNodePtr node,
1873 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 const char *message,
1875 int nbval,
1876 int nbneg,
1877 xmlChar **values)
1878{
1879 xmlChar *str = NULL, *msg = NULL;
1880 xmlChar *localName, *nsName;
1881 const xmlChar *cur, *end;
1882 int i;
1883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 /*
1888 * Note that is does not make sense to report that we have a
1889 * wildcard here, since the wildcard might be unfolded into
1890 * multiple transitions.
1891 */
1892 if (nbval + nbneg > 0) {
1893 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001894 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001895 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001896 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001897 nsName = NULL;
1898
1899 for (i = 0; i < nbval + nbneg; i++) {
1900 cur = values[i];
1901 /*
1902 * Get the local name.
1903 */
1904 localName = NULL;
1905
1906 end = cur;
1907 if (*end == '*') {
1908 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001909 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001910 } else {
1911 while ((*end != 0) && (*end != '|'))
1912 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001913 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914 }
1915 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001916 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001917 /*
1918 * Skip "*|*" if they come with negated expressions, since
1919 * they represent the same negated wildcard.
1920 */
1921 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1922 /*
1923 * Get the namespace name.
1924 */
1925 cur = end;
1926 if (*end == '*') {
1927 nsName = xmlStrdup(BAD_CAST "{*}");
1928 } else {
1929 while (*end != 0)
1930 end++;
1931
1932 if (i >= nbval)
1933 nsName = xmlStrdup(BAD_CAST "{##other:");
1934 else
1935 nsName = xmlStrdup(BAD_CAST "{");
1936
1937 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1938 nsName = xmlStrcat(nsName, BAD_CAST "}");
1939 }
1940 str = xmlStrcat(str, BAD_CAST nsName);
1941 FREE_AND_NULL(nsName)
1942 } else {
1943 FREE_AND_NULL(localName);
1944 continue;
1945 }
1946 }
1947 str = xmlStrcat(str, BAD_CAST localName);
1948 FREE_AND_NULL(localName);
1949
1950 if (i < nbval + nbneg -1)
1951 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001952 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001953 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001954 msg = xmlStrcat(msg, BAD_CAST str);
1955 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001956 } else
1957 msg = xmlStrcat(msg, BAD_CAST "\n");
1958 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001959 xmlFree(msg);
1960}
1961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001962static void
1963xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1964 xmlParserErrors error,
1965 xmlNodePtr node,
1966 const xmlChar *value,
1967 unsigned long length,
1968 xmlSchemaTypePtr type,
1969 xmlSchemaFacetPtr facet,
1970 const char *message,
1971 const xmlChar *str1,
1972 const xmlChar *str2)
1973{
1974 xmlChar *str = NULL, *msg = NULL;
1975 xmlSchemaTypeType facetType;
1976 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1977
1978 xmlSchemaFormatNodeForError(&msg, actxt, node);
1979 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1980 facetType = XML_SCHEMA_FACET_ENUMERATION;
1981 /*
1982 * If enumerations are validated, one must not expect the
1983 * facet to be given.
1984 */
1985 } else
1986 facetType = facet->type;
1987 msg = xmlStrcat(msg, BAD_CAST "[");
1988 msg = xmlStrcat(msg, BAD_CAST "facet '");
1989 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1990 msg = xmlStrcat(msg, BAD_CAST "'] ");
1991 if (message == NULL) {
1992 /*
1993 * Use a default message.
1994 */
1995 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1996 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1997 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1998
1999 char len[25], actLen[25];
2000
2001 /* FIXME, TODO: What is the max expected string length of the
2002 * this value?
2003 */
2004 if (nodeType == XML_ATTRIBUTE_NODE)
2005 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2006 else
2007 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2008
2009 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2010 snprintf(actLen, 24, "%lu", length);
2011
2012 if (facetType == XML_SCHEMA_FACET_LENGTH)
2013 msg = xmlStrcat(msg,
2014 BAD_CAST "this differs from the allowed length of '%s'.\n");
2015 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2016 msg = xmlStrcat(msg,
2017 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2018 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2019 msg = xmlStrcat(msg,
2020 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2021
2022 if (nodeType == XML_ATTRIBUTE_NODE)
2023 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2024 value, (const xmlChar *) actLen, (const xmlChar *) len);
2025 else
2026 xmlSchemaErr(actxt, error, node, (const char *) msg,
2027 (const xmlChar *) actLen, (const xmlChar *) len);
2028
2029 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2030 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2031 "of the set {%s}.\n");
2032 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2033 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2034 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2035 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2036 "by the pattern '%s'.\n");
2037 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2038 facet->value);
2039 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2041 "minimum value allowed ('%s').\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 facet->value);
2044 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2046 "maximum value allowed ('%s').\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2051 "'%s'.\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2056 "'%s'.\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2061 "digits than are allowed ('%s').\n");
2062 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2066 "digits than are allowed ('%s').\n");
2067 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2068 facet->value);
2069 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2072 } else {
2073 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2074 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2075 }
2076 } else {
2077 msg = xmlStrcat(msg, (const xmlChar *) message);
2078 msg = xmlStrcat(msg, BAD_CAST ".\n");
2079 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2080 }
2081 FREE_AND_NULL(str)
2082 xmlFree(msg);
2083}
2084
2085#define VERROR(err, type, msg) \
2086 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2087
2088#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2089
2090#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2091
2092#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2093
2094
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002095/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002096 * xmlSchemaPMissingAttrErr:
2097 * @ctxt: the schema validation context
2098 * @ownerDes: the designation of the owner
2099 * @ownerName: the name of the owner
2100 * @ownerItem: the owner as a schema object
2101 * @ownerElem: the owner as an element node
2102 * @node: the parent element node of the missing attribute node
2103 * @type: the corresponding type of the attribute node
2104 *
2105 * Reports an illegal attribute.
2106 */
2107static void
2108xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002110 xmlSchemaTypePtr ownerItem,
2111 xmlNodePtr ownerElem,
2112 const char *name,
2113 const char *message)
2114{
2115 xmlChar *des = NULL;
2116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2118
Daniel Veillardc0826a72004-08-10 14:17:33 +00002119 if (message != NULL)
2120 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002121 else
2122 xmlSchemaPErr(ctxt, ownerElem, error,
2123 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002124 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002125 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002126}
2127
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129/**
2130 * xmlSchemaPResCompAttrErr:
2131 * @ctxt: the schema validation context
2132 * @error: the error code
2133 * @ownerDes: the designation of the owner
2134 * @ownerItem: the owner as a schema object
2135 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002136 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002137 * @refName: the referenced local name
2138 * @refURI: the referenced namespace URI
2139 * @message: optional message
2140 *
2141 * Used to report QName attribute values that failed to resolve
2142 * to schema components.
2143 */
2144static void
2145xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 xmlSchemaTypePtr ownerItem,
2148 xmlNodePtr ownerElem,
2149 const char *name,
2150 const xmlChar *refName,
2151 const xmlChar *refURI,
2152 xmlSchemaTypeType refType,
2153 const char *refTypeStr)
2154{
2155 xmlChar *des = NULL, *strA = NULL;
2156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002158 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002159 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2160 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2163 "%s.\n", BAD_CAST des, BAD_CAST name,
2164 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002167 FREE_AND_NULL(strA)
2168}
2169
William M. Brack2f2a6632004-08-20 23:09:47 +00002170/**
2171 * xmlSchemaPCustomAttrErr:
2172 * @ctxt: the schema parser context
2173 * @error: the error code
2174 * @ownerDes: the designation of the owner
2175 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002177 *
2178 * Reports an illegal attribute during the parse.
2179 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002180static void
2181xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002183 xmlChar **ownerDes,
2184 xmlSchemaTypePtr ownerItem,
2185 xmlAttrPtr attr,
2186 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187{
2188 xmlChar *des = NULL;
2189
2190 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002191 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002192 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002193 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002194 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002195 } else
2196 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2200 if (ownerDes == NULL)
2201 FREE_AND_NULL(des);
2202}
2203
2204/**
2205 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002206 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002208 * @ownerDes: the designation of the attribute's owner
2209 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002211 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002212 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002213 */
2214static void
2215xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 xmlChar **ownerDes,
2218 xmlSchemaTypePtr ownerItem,
2219 xmlAttrPtr attr)
2220{
2221 xmlChar *des = NULL, *strA = NULL;
2222
2223 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002224 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002225 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 } else
2229 des = *ownerDes;
2230 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2231 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2232 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 if (ownerDes == NULL)
2234 FREE_AND_NULL(des);
2235 FREE_AND_NULL(strA);
2236}
2237
William M. Brack2f2a6632004-08-20 23:09:47 +00002238/**
2239 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002240 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002241 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002242 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002243 * @itemElem: the node of the schema item
2244 *
2245 * Creates a designation for an item.
2246 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002247static void
2248xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250 xmlSchemaTypePtr item,
2251 xmlNodePtr itemElem)
2252{
2253 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002255 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002256 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002258 } else
2259 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260}
2261
William M. Brack2f2a6632004-08-20 23:09:47 +00002262/**
2263 * xmlSchemaPCustomErr:
2264 * @ctxt: the schema parser context
2265 * @error: the error code
2266 * @itemDes: the designation of the schema item
2267 * @item: the schema item
2268 * @itemElem: the node of the schema item
2269 * @message: the error message
2270 * @str1: an optional param for the error message
2271 * @str2: an optional param for the error message
2272 * @str3: an optional param for the error message
2273 *
2274 * Reports an error during parsing.
2275 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002276static void
2277xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002278 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002279 xmlChar **itemDes,
2280 xmlSchemaTypePtr item,
2281 xmlNodePtr itemElem,
2282 const char *message,
2283 const xmlChar *str1,
2284 const xmlChar *str2,
2285 const xmlChar *str3)
2286{
2287 xmlChar *des = NULL, *msg = NULL;
2288
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002289 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002290 msg = xmlStrdup(BAD_CAST "%s: ");
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 if ((itemElem == NULL) && (item != NULL))
2294 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2297 if (itemDes == NULL)
2298 FREE_AND_NULL(des);
2299 FREE_AND_NULL(msg);
2300}
2301
William M. Brack2f2a6632004-08-20 23:09:47 +00002302/**
2303 * xmlSchemaPCustomErr:
2304 * @ctxt: the schema parser context
2305 * @error: the error code
2306 * @itemDes: the designation of the schema item
2307 * @item: the schema item
2308 * @itemElem: the node of the schema item
2309 * @message: the error message
2310 * @str1: the optional param for the error message
2311 *
2312 * Reports an error during parsing.
2313 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002314static void
2315xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002316 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002317 xmlChar **itemDes,
2318 xmlSchemaTypePtr item,
2319 xmlNodePtr itemElem,
2320 const char *message,
2321 const xmlChar *str1)
2322{
2323 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2324 str1, NULL, NULL);
2325}
2326
William M. Brack2f2a6632004-08-20 23:09:47 +00002327/**
2328 * xmlSchemaPAttrUseErr:
2329 * @ctxt: the schema parser context
2330 * @error: the error code
2331 * @itemDes: the designation of the schema type
2332 * @item: the schema type
2333 * @itemElem: the node of the schema type
2334 * @attr: the invalid schema attribute
2335 * @message: the error message
2336 * @str1: the optional param for the error message
2337 *
2338 * Reports an attribute use error during parsing.
2339 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002340static void
2341xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002342 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002343 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 const xmlSchemaAttributePtr attr,
2345 const char *message,
2346 const xmlChar *str1)
2347{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002348 xmlChar *str = NULL, *msg = NULL;
2349 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2350 msg = xmlStrcat(msg, BAD_CAST ", ");
2351 msg = xmlStrcat(msg,
2352 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2353 (xmlSchemaTypePtr) attr, NULL));
2354 FREE_AND_NULL(str);
2355 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002356 msg = xmlStrcat(msg, (const xmlChar *) message);
2357 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlSchemaPErr(ctxt, attr->node, error,
2359 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002360 xmlFree(msg);
2361}
2362
William M. Brack2f2a6632004-08-20 23:09:47 +00002363/**
2364 * xmlSchemaPIllegalFacetAtomicErr:
2365 * @ctxt: the schema parser context
2366 * @error: the error code
2367 * @itemDes: the designation of the type
2368 * @item: the schema type
2369 * @baseItem: the base type of type
2370 * @facet: the illegal facet
2371 *
2372 * Reports an illegal facet for atomic simple types.
2373 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002374static void
2375xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002376 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002377 xmlChar **itemDes,
2378 xmlSchemaTypePtr item,
2379 xmlSchemaTypePtr baseItem,
2380 xmlSchemaFacetPtr facet)
2381{
2382 xmlChar *des = NULL, *strT = NULL;
2383
2384 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2385 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2386 "%s: The facet '%s' is not allowed on types derived from the "
2387 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002388 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002390 NULL, NULL);
2391 if (itemDes == NULL)
2392 FREE_AND_NULL(des);
2393 FREE_AND_NULL(strT);
2394}
2395
William M. Brack2f2a6632004-08-20 23:09:47 +00002396/**
2397 * xmlSchemaPIllegalFacetListUnionErr:
2398 * @ctxt: the schema parser context
2399 * @error: the error code
2400 * @itemDes: the designation of the schema item involved
2401 * @item: the schema item involved
2402 * @facet: the illegal facet
2403 *
2404 * Reports an illegal facet for <list> and <union>.
2405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002406static void
2407xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002409 xmlChar **itemDes,
2410 xmlSchemaTypePtr item,
2411 xmlSchemaFacetPtr facet)
2412{
2413 xmlChar *des = NULL, *strT = NULL;
2414
2415 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002416 xmlSchemaPErr(ctxt, item->node, error,
2417 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002418 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 if (itemDes == NULL)
2420 FREE_AND_NULL(des);
2421 FREE_AND_NULL(strT);
2422}
2423
2424/**
2425 * xmlSchemaPMutualExclAttrErr:
2426 * @ctxt: the schema validation context
2427 * @error: the error code
2428 * @elemDes: the designation of the parent element node
2429 * @attr: the bad attribute node
2430 * @type: the corresponding type of the attribute node
2431 *
2432 * Reports an illegal attribute.
2433 */
2434static void
2435xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2436 xmlParserErrors error,
2437 xmlChar **ownerDes,
2438 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002440 const char *name1,
2441 const char *name2)
2442{
2443 xmlChar *des = NULL;
2444
2445 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002446 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002449 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002450 } else
2451 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002452 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002453 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002454 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2455 if (ownerDes == NULL)
2456 FREE_AND_NULL(des)
2457}
2458
2459/**
2460 * xmlSchemaPSimpleTypeErr:
2461 * @ctxt: the schema validation context
2462 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002463 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 * @ownerDes: the designation of the owner
2465 * @ownerItem: the schema object if existent
2466 * @node: the validated node
2467 * @value: the validated value
2468 *
2469 * Reports a simple type validation error.
2470 * TODO: Should this report the value of an element as well?
2471 */
2472static void
2473xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2474 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002475 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002476 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002477 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 const xmlChar *value,
2480 const char *message,
2481 const xmlChar *str1,
2482 const xmlChar *str2)
2483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487 if (message == NULL) {
2488 /*
2489 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490 */
2491 if (type != NULL) {
2492 if (node->type == XML_ATTRIBUTE_NODE)
2493 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2494 else
2495 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2496 "valid value of ");
2497 if (! xmlSchemaIsGlobalItem(type))
2498 msg = xmlStrcat(msg, BAD_CAST "the local ");
2499 else
2500 msg = xmlStrcat(msg, BAD_CAST "the ");
2501
2502 if (VARIETY_ATOMIC(type))
2503 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2504 else if (VARIETY_LIST(type))
2505 msg = xmlStrcat(msg, BAD_CAST "list type");
2506 else if (VARIETY_UNION(type))
2507 msg = xmlStrcat(msg, BAD_CAST "union type");
2508
2509 if (xmlSchemaIsGlobalItem(type)) {
2510 xmlChar *str = NULL;
2511 msg = xmlStrcat(msg, BAD_CAST " '");
2512 if (type->builtInType != 0) {
2513 msg = xmlStrcat(msg, BAD_CAST "xs:");
2514 msg = xmlStrcat(msg, type->name);
2515 } else
2516 msg = xmlStrcat(msg,
2517 xmlSchemaFormatQName(&str,
2518 type->targetNamespace, type->name));
2519 msg = xmlStrcat(msg, BAD_CAST "'.");
2520 FREE_AND_NULL(str);
2521 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002522 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002523 if (node->type == XML_ATTRIBUTE_NODE)
2524 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2527 "valid.");
2528 }
2529 if (expected) {
2530 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2531 msg = xmlStrcat(msg, BAD_CAST expected);
2532 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2533 } else
2534 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002535 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2537 else
2538 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2539 } else {
2540 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2541 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002543 /* Cleanup. */
2544 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545}
2546
William M. Brack2f2a6632004-08-20 23:09:47 +00002547/**
2548 * xmlSchemaPContentErr:
2549 * @ctxt: the schema parser context
2550 * @error: the error code
2551 * @onwerDes: the designation of the holder of the content
2552 * @ownerItem: the owner item of the holder of the content
2553 * @ownerElem: the node of the holder of the content
2554 * @child: the invalid child node
2555 * @message: the optional error message
2556 * @content: the optional string describing the correct content
2557 *
2558 * Reports an error concerning the content of a schema element.
2559 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002560static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002561xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002562 xmlParserErrors error,
2563 xmlChar **ownerDes,
2564 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 xmlNodePtr child,
2567 const char *message,
2568 const char *content)
2569{
2570 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002573 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 } else
2578 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2581 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 BAD_CAST des, BAD_CAST message);
2583 else {
2584 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2586 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 BAD_CAST des, BAD_CAST content);
2588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2590 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002591 BAD_CAST des, NULL);
2592 }
2593 }
2594 if (ownerDes == NULL)
2595 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002596}
2597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002598/************************************************************************
2599 * *
2600 * Streamable error functions *
2601 * *
2602 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002603
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002604
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002605
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002607/************************************************************************
2608 * *
2609 * Validation helper functions *
2610 * *
2611 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002612
Daniel Veillardc0826a72004-08-10 14:17:33 +00002613
Daniel Veillard4255d502002-04-16 15:50:10 +00002614/************************************************************************
2615 * *
2616 * Allocation functions *
2617 * *
2618 ************************************************************************/
2619
2620/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002621 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002622 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002623 *
2624 * Allocate a new Schema structure.
2625 *
2626 * Returns the newly allocated structure or NULL in case or error
2627 */
2628static xmlSchemaPtr
2629xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2630{
2631 xmlSchemaPtr ret;
2632
2633 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2634 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002635 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 return (NULL);
2637 }
2638 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002639 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002640 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002641
2642 return (ret);
2643}
2644
2645/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002646 * xmlSchemaNewSchema:
2647 * @ctxt: a schema validation context
2648 *
2649 * Allocate a new Schema structure.
2650 *
2651 * Returns the newly allocated structure or NULL in case or error
2652 */
2653static xmlSchemaAssemblePtr
2654xmlSchemaNewAssemble(void)
2655{
2656 xmlSchemaAssemblePtr ret;
2657
2658 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2659 if (ret == NULL) {
2660 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2661 return (NULL);
2662 }
2663 memset(ret, 0, sizeof(xmlSchemaAssemble));
2664 ret->items = NULL;
2665 return (ret);
2666}
2667
2668/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 *
2671 * Allocate a new Facet structure.
2672 *
2673 * Returns the newly allocated structure or NULL in case or error
2674 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002675xmlSchemaFacetPtr
2676xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002677{
2678 xmlSchemaFacetPtr ret;
2679
2680 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2681 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002682 return (NULL);
2683 }
2684 memset(ret, 0, sizeof(xmlSchemaFacet));
2685
2686 return (ret);
2687}
2688
2689/**
2690 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002691 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 * @node: a node
2693 *
2694 * Allocate a new annotation structure.
2695 *
2696 * Returns the newly allocated structure or NULL in case or error
2697 */
2698static xmlSchemaAnnotPtr
2699xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2700{
2701 xmlSchemaAnnotPtr ret;
2702
2703 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2704 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002705 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 return (NULL);
2707 }
2708 memset(ret, 0, sizeof(xmlSchemaAnnot));
2709 ret->content = node;
2710 return (ret);
2711}
2712
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002713static xmlSchemaItemListPtr
2714xmlSchemaNewItemList(void)
2715{
2716 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002718 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2719 if (ret == NULL) {
2720 xmlSchemaPErrMemory(NULL,
2721 "allocating an item list structure", NULL);
2722 return (NULL);
2723 }
2724 memset(ret, 0, sizeof(xmlSchemaItemList));
2725 return (ret);
2726}
2727
2728/**
2729 * xmlSchemaAddElementSubstitutionMember:
2730 * @pctxt: a schema parser context
2731 * @head: the head of the substitution group
2732 * @member: the new member of the substitution group
2733 *
2734 * Allocate a new annotation structure.
2735 *
2736 * Returns the newly allocated structure or NULL in case or error
2737 */
2738static int
2739xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2740 xmlSchemaElementPtr head,
2741 xmlSchemaElementPtr member)
2742{
2743 xmlSchemaSubstGroupPtr substGroup;
2744
2745 if (pctxt == NULL)
2746 return (-1);
2747
2748 if (pctxt->substGroups == NULL) {
2749 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2750 if (pctxt->substGroups == NULL)
2751 return (-1);
2752 }
2753 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2754 head->targetNamespace);
2755 if (substGroup == NULL) {
2756 int res;
2757
2758 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2759 if (substGroup == NULL) {
2760 xmlSchemaPErrMemory(NULL,
2761 "xmlSchemaAddElementSubstitution, allocating a substitution "
2762 "group container",
2763 NULL);
2764 return (-1);
2765 }
2766 substGroup->members = xmlSchemaNewItemList();
2767 if (substGroup->members == NULL) {
2768 xmlFree(substGroup);
2769 return (-1);
2770 }
2771 substGroup->head = head;
2772
2773 res = xmlHashAddEntry2(pctxt->substGroups,
2774 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002776 xmlFree(substGroup->members);
2777 xmlFree(substGroup);
2778 xmlSchemaPErr(pctxt, member->node,
2779 XML_SCHEMAP_INTERNAL,
2780 "Internal error: xmlSchemaAddElementSubstitution, "
2781 "failed to add a new substitution group container for "
2782 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 return (-1);
2784 }
2785 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 if (substGroup->members->items == NULL) {
2787 substGroup->members->items = (void **) xmlMalloc(
2788 5 * sizeof(xmlSchemaElementPtr));
2789 if (substGroup->members->items == NULL) {
2790 xmlSchemaPErrMemory(NULL,
2791 "allocating list of substitution group members", NULL);
2792 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002794 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 substGroup->members->nbItems) {
2797 substGroup->members->sizeItems *= 2;
2798 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002800 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2801 if (substGroup->members->items == NULL) {
2802 xmlSchemaPErrMemory(NULL,
2803 "re-allocating list of substitution group members", NULL);
2804 substGroup->members->sizeItems = 0;
2805 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002806 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002807 }
2808 ((xmlSchemaElementPtr *) substGroup->members->items)
2809 [substGroup->members->nbItems++] = (void *) member;
2810 return (0);
2811}
2812
2813/**
2814 * xmlSchemaGetElementSubstitutionGroup:
2815 * @pctxt: a schema parser context
2816 * @head: the head of the substitution group
2817 * @member: the new member of the substitution group
2818 *
2819 * Allocate a new annotation structure.
2820 *
2821 * Returns the newly allocated structure or NULL in case or error
2822 */
2823static xmlSchemaSubstGroupPtr
2824xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2825 xmlSchemaElementPtr head)
2826{
2827 if (pctxt == NULL)
2828 return (NULL);
2829
2830 if (pctxt->substGroups == NULL)
2831 return (NULL);
2832
2833 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2834 head->name, head->targetNamespace));
2835}
2836
2837/**
2838 * xmlSchemaFreeItemList:
2839 * @annot: a schema type structure
2840 *
2841 * Deallocate a annotation structure
2842 */
2843static void
2844xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2845{
2846 if (list == NULL)
2847 return;
2848 if (list->items != NULL)
2849 xmlFree(list->items);
2850 xmlFree(list);
2851}
2852
Daniel Veillard4255d502002-04-16 15:50:10 +00002853/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002854 * xmlSchemaFreeAnnot:
2855 * @annot: a schema type structure
2856 *
2857 * Deallocate a annotation structure
2858 */
2859static void
2860xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2861{
2862 if (annot == NULL)
2863 return;
2864 xmlFree(annot);
2865}
2866
2867/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002868 * xmlSchemaFreeImport:
2869 * @import: a schema import structure
2870 *
2871 * Deallocate an import structure
2872 */
2873static void
2874xmlSchemaFreeImport(xmlSchemaImportPtr import)
2875{
2876 if (import == NULL)
2877 return;
2878
2879 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002880 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002881 xmlFree(import);
2882}
2883
2884/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002885 * xmlSchemaFreeInclude:
2886 * @include: a schema include structure
2887 *
2888 * Deallocate an include structure
2889 */
2890static void
2891xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2892{
2893 if (include == NULL)
2894 return;
2895
2896 xmlFreeDoc(include->doc);
2897 xmlFree(include);
2898}
2899
2900/**
2901 * xmlSchemaFreeIncludeList:
2902 * @includes: a schema include list
2903 *
2904 * Deallocate an include structure
2905 */
2906static void
2907xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2908{
2909 xmlSchemaIncludePtr next;
2910
2911 while (includes != NULL) {
2912 next = includes->next;
2913 xmlSchemaFreeInclude(includes);
2914 includes = next;
2915 }
2916}
2917
2918/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 * xmlSchemaFreeNotation:
2920 * @schema: a schema notation structure
2921 *
2922 * Deallocate a Schema Notation structure.
2923 */
2924static void
2925xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2926{
2927 if (nota == NULL)
2928 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 xmlFree(nota);
2930}
2931
2932/**
2933 * xmlSchemaFreeAttribute:
2934 * @schema: a schema attribute structure
2935 *
2936 * Deallocate a Schema Attribute structure.
2937 */
2938static void
2939xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2940{
2941 if (attr == NULL)
2942 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002943 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002944 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002945 if (attr->defVal != NULL)
2946 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002947 xmlFree(attr);
2948}
2949
2950/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002951 * xmlSchemaFreeWildcardNsSet:
2952 * set: a schema wildcard namespace
2953 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002954 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002955 */
2956static void
2957xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2958{
2959 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002960
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 while (set != NULL) {
2962 next = set->next;
2963 xmlFree(set);
2964 set = next;
2965 }
2966}
2967
2968/**
2969 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002970 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002972 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002974void
Daniel Veillard3646d642004-06-02 19:19:14 +00002975xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2976{
2977 if (wildcard == NULL)
2978 return;
2979 if (wildcard->annot != NULL)
2980 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002981 if (wildcard->nsSet != NULL)
2982 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2983 if (wildcard->negNsSet != NULL)
2984 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002985 xmlFree(wildcard);
2986}
2987
2988/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002989 * xmlSchemaFreeAttributeGroup:
2990 * @schema: a schema attribute group structure
2991 *
2992 * Deallocate a Schema Attribute Group structure.
2993 */
2994static void
2995xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2996{
2997 if (attr == NULL)
2998 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002999 if (attr->annot != NULL)
3000 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003001 xmlFree(attr);
3002}
3003
3004/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003005 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003006 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003007 *
3008 * Deallocate a list of schema attribute uses.
3009 */
3010static void
3011xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3012{
3013 xmlSchemaAttributeLinkPtr next;
3014
3015 while (attrUse != NULL) {
3016 next = attrUse->next;
3017 xmlFree(attrUse);
3018 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003019 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003020}
3021
3022/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003023 * xmlSchemaFreeQNameRef:
3024 * @item: a QName reference structure
3025 *
3026 * Deallocatea a QName reference structure.
3027 */
3028static void
3029xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3030{
3031 xmlFree(item);
3032}
3033
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003034/**
3035 * xmlSchemaFreeQNameRef:
3036 * @item: a QName reference structure
3037 *
3038 * Deallocatea a QName reference structure.
3039 */
3040static void
3041xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3042{
3043 if (item == NULL)
3044 return;
3045 if (item->members != NULL)
3046 xmlSchemaFreeItemList(item->members);
3047 xmlFree(item);
3048}
3049
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003050static int
3051xmlSchemaAddVolatile(xmlSchemaPtr schema,
3052 xmlSchemaBasicItemPtr item)
3053{
3054 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003055
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003056 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003057 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003058 if (schema->volatiles == NULL) {
3059 xmlSchemaPErrMemory(NULL,
3060 "allocating list of volatiles", NULL);
3061 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003062 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003063 }
3064 list = (xmlSchemaItemListPtr) schema->volatiles;
3065 if (list->items == NULL) {
3066 list->items = (void **) xmlMalloc(
3067 20 * sizeof(xmlSchemaBasicItemPtr));
3068 if (list->items == NULL) {
3069 xmlSchemaPErrMemory(NULL,
3070 "allocating new volatile item buffer", NULL);
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 list->sizeItems = 20;
3074 } else if (list->sizeItems <= list->nbItems) {
3075 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003076 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003077 list->sizeItems * sizeof(xmlSchemaTypePtr));
3078 if (list->items == NULL) {
3079 xmlSchemaPErrMemory(NULL,
3080 "growing volatile item buffer", NULL);
3081 list->sizeItems = 0;
3082 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003084 }
3085 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3086 return (0);
3087}
3088
3089/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003090 * xmlSchemaFreeTypeLinkList:
3091 * @alink: a type link
3092 *
3093 * Deallocate a list of types.
3094 */
3095static void
3096xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3097{
3098 xmlSchemaTypeLinkPtr next;
3099
3100 while (link != NULL) {
3101 next = link->next;
3102 xmlFree(link);
3103 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003104 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003105}
3106
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003107static void
3108xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3109{
3110 xmlSchemaIDCStateObjPtr next;
3111 while (sto != NULL) {
3112 next = sto->next;
3113 if (sto->history != NULL)
3114 xmlFree(sto->history);
3115 if (sto->xpathCtxt != NULL)
3116 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3117 xmlFree(sto);
3118 sto = next;
3119 }
3120}
3121
3122/**
3123 * xmlSchemaFreeIDC:
3124 * @idc: a identity-constraint definition
3125 *
3126 * Deallocates an identity-constraint definition.
3127 */
3128static void
3129xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3130{
3131 xmlSchemaIDCSelectPtr cur, prev;
3132
3133 if (idcDef == NULL)
3134 return;
3135 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003137 /* Selector */
3138 if (idcDef->selector != NULL) {
3139 if (idcDef->selector->xpathComp != NULL)
3140 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3141 xmlFree(idcDef->selector);
3142 }
3143 /* Fields */
3144 if (idcDef->fields != NULL) {
3145 cur = idcDef->fields;
3146 do {
3147 prev = cur;
3148 cur = cur->next;
3149 if (prev->xpathComp != NULL)
3150 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003151 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003152 } while (cur != NULL);
3153 }
3154 xmlFree(idcDef);
3155}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003156
Daniel Veillard01fa6152004-06-29 17:04:39 +00003157/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 * xmlSchemaFreeElement:
3159 * @schema: a schema element structure
3160 *
3161 * Deallocate a Schema Element structure.
3162 */
3163static void
3164xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3165{
3166 if (elem == NULL)
3167 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003168 if (elem->annot != NULL)
3169 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003172 if (elem->defVal != NULL)
3173 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003174 xmlFree(elem);
3175}
3176
3177/**
3178 * xmlSchemaFreeFacet:
3179 * @facet: a schema facet structure
3180 *
3181 * Deallocate a Schema Facet structure.
3182 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003183void
Daniel Veillard4255d502002-04-16 15:50:10 +00003184xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3185{
3186 if (facet == NULL)
3187 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003188 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003189 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003191 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003192 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003193 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 xmlFree(facet);
3195}
3196
3197/**
3198 * xmlSchemaFreeType:
3199 * @type: a schema type structure
3200 *
3201 * Deallocate a Schema Type structure.
3202 */
3203void
3204xmlSchemaFreeType(xmlSchemaTypePtr type)
3205{
3206 if (type == NULL)
3207 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003209 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003212
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003213 facet = type->facets;
3214 while (facet != NULL) {
3215 next = facet->next;
3216 xmlSchemaFreeFacet(facet);
3217 facet = next;
3218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003219 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003220 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3221 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003222 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003223 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003224 if (type->memberTypes != NULL)
3225 xmlSchemaFreeTypeLinkList(type->memberTypes);
3226 if (type->facetSet != NULL) {
3227 xmlSchemaFacetLinkPtr next, link;
3228
3229 link = type->facetSet;
3230 do {
3231 next = link->next;
3232 xmlFree(link);
3233 link = next;
3234 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003235 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003236 if (type->contModel != NULL)
3237 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 xmlFree(type);
3239}
3240
3241/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003242 * xmlSchemaFreeModelGroupDef:
3243 * @item: a schema model group definition
3244 *
3245 * Deallocates a schema model group definition.
3246 */
3247static void
3248xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3249{
3250 if (item->annot != NULL)
3251 xmlSchemaFreeAnnot(item->annot);
3252 xmlFree(item);
3253}
3254
3255/**
3256 * xmlSchemaFreeModelGroup:
3257 * @item: a schema model group
3258 *
3259 * Deallocates a schema model group structure.
3260 */
3261static void
3262xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3263{
3264 if (item->annot != NULL)
3265 xmlSchemaFreeAnnot(item->annot);
3266 xmlFree(item);
3267}
3268
3269/**
3270 * xmlSchemaFreeParticle:
3271 * @type: a schema type structure
3272 *
3273 * Deallocate a Schema Type structure.
3274 */
3275static void
3276xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3277{
3278 if (item->annot != NULL)
3279 xmlSchemaFreeAnnot(item->annot);
3280 xmlFree(item);
3281}
3282
3283/**
3284 * xmlSchemaFreeMiscComponents:
3285 * @item: a schema component
3286 *
3287 * Deallocates misc. schema component structures.
3288 */
3289static void
3290xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3291{
3292 if (item == NULL)
3293 return;
3294 switch (item->type) {
3295 case XML_SCHEMA_TYPE_PARTICLE:
3296 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3297 return;
3298 case XML_SCHEMA_TYPE_SEQUENCE:
3299 case XML_SCHEMA_TYPE_CHOICE:
3300 case XML_SCHEMA_TYPE_ALL:
3301 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3302 return;
3303 case XML_SCHEMA_TYPE_ANY:
3304 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3305 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3306 break;
3307 default:
3308 /* TODO: This should never be hit. */
3309 TODO
3310 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003311 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003312}
3313
3314static void
3315xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3316{
3317 if (schema->volatiles == NULL)
3318 return;
3319 {
3320 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3321 xmlSchemaTreeItemPtr item;
3322 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003324 for (i = 0; i < list->nbItems; i++) {
3325 if (list->items[i] != NULL) {
3326 item = (xmlSchemaTreeItemPtr) list->items[i];
3327 switch (item->type) {
3328 case XML_SCHEMA_EXTRA_QNAMEREF:
3329 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3330 break;
3331 default:
3332 xmlSchemaFreeMiscComponents(item);
3333 }
3334 }
3335 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003336 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003337 }
3338}
3339/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003340 * xmlSchemaFreeTypeList:
3341 * @type: a schema type structure
3342 *
3343 * Deallocate a Schema Type structure.
3344 */
3345static void
3346xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3347{
3348 xmlSchemaTypePtr next;
3349
3350 while (type != NULL) {
3351 next = type->redef;
3352 xmlSchemaFreeType(type);
3353 type = next;
3354 }
3355}
3356
3357/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003358 * xmlSchemaFree:
3359 * @schema: a schema structure
3360 *
3361 * Deallocate a Schema structure.
3362 */
3363void
3364xmlSchemaFree(xmlSchemaPtr schema)
3365{
3366 if (schema == NULL)
3367 return;
3368
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003369 if (schema->volatiles != NULL)
3370 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003371 if (schema->notaDecl != NULL)
3372 xmlHashFree(schema->notaDecl,
3373 (xmlHashDeallocator) xmlSchemaFreeNotation);
3374 if (schema->attrDecl != NULL)
3375 xmlHashFree(schema->attrDecl,
3376 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3377 if (schema->attrgrpDecl != NULL)
3378 xmlHashFree(schema->attrgrpDecl,
3379 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3380 if (schema->elemDecl != NULL)
3381 xmlHashFree(schema->elemDecl,
3382 (xmlHashDeallocator) xmlSchemaFreeElement);
3383 if (schema->typeDecl != NULL)
3384 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003385 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003386 if (schema->groupDecl != NULL)
3387 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003388 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003389 if (schema->idcDef != NULL)
3390 xmlHashFree(schema->idcDef,
3391 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003392 if (schema->schemasImports != NULL)
3393 xmlHashFree(schema->schemasImports,
3394 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003395 if (schema->includes != NULL) {
3396 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3397 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003399 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003400 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003402 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403 xmlFree(schema);
3404}
3405
3406/************************************************************************
3407 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 * Debug functions *
3409 * *
3410 ************************************************************************/
3411
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003412#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413
Daniel Veillard4255d502002-04-16 15:50:10 +00003414/**
3415 * xmlSchemaElementDump:
3416 * @elem: an element
3417 * @output: the file output
3418 *
3419 * Dump the element
3420 */
3421static void
3422xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003424 const xmlChar * namespace ATTRIBUTE_UNUSED,
3425 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003426{
3427 if (elem == NULL)
3428 return;
3429
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003430 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3431 fprintf(output, "Particle: %s", name);
3432 fprintf(output, ", term element: %s", elem->ref);
3433 if (elem->refNs != NULL)
3434 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003435 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003436 fprintf(output, "Element");
3437 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3438 fprintf(output, " (global)");
3439 fprintf(output, ": %s ", elem->name);
3440 if (namespace != NULL)
3441 fprintf(output, "ns %s", namespace);
3442 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 fprintf(output, "\n");
3444 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003445 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003446 if (elem->maxOccurs >= UNBOUNDED)
3447 fprintf(output, "max: unbounded\n");
3448 else if (elem->maxOccurs != 1)
3449 fprintf(output, "max: %d\n", elem->maxOccurs);
3450 else
3451 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003452 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003453 /*
3454 * Misc other properties.
3455 */
3456 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3457 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3458 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3459 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3460 (elem->id != NULL)) {
3461 fprintf(output, " props: ");
3462 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3463 fprintf(output, "[fixed] ");
3464 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3465 fprintf(output, "[default] ");
3466 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3467 fprintf(output, "[abstract] ");
3468 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3469 fprintf(output, "[nillable] ");
3470 if (elem->id != NULL)
3471 fprintf(output, "[id: '%s'] ", elem->id);
3472 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003473 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003474 /*
3475 * Default/fixed value.
3476 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003478 fprintf(output, " value: '%s'\n", elem->value);
3479 /*
3480 * Type.
3481 */
3482 if (elem->namedType != NULL) {
3483 fprintf(output, " type: %s ", elem->namedType);
3484 if (elem->namedTypeNs != NULL)
3485 fprintf(output, "ns %s\n", elem->namedTypeNs);
3486 else
3487 fprintf(output, "\n");
3488 }
3489 /*
3490 * Substitution group.
3491 */
3492 if (elem->substGroup != NULL) {
3493 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3494 if (elem->substGroupNs != NULL)
3495 fprintf(output, "ns %s\n", elem->substGroupNs);
3496 else
3497 fprintf(output, "\n");
3498 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003499}
3500
3501/**
3502 * xmlSchemaAnnotDump:
3503 * @output: the file output
3504 * @annot: a annotation
3505 *
3506 * Dump the annotation
3507 */
3508static void
3509xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3510{
3511 xmlChar *content;
3512
3513 if (annot == NULL)
3514 return;
3515
3516 content = xmlNodeGetContent(annot->content);
3517 if (content != NULL) {
3518 fprintf(output, " Annot: %s\n", content);
3519 xmlFree(content);
3520 } else
3521 fprintf(output, " Annot: empty\n");
3522}
3523
3524/**
3525 * xmlSchemaTypeDump:
3526 * @output: the file output
3527 * @type: a type structure
3528 *
3529 * Dump a SchemaType structure
3530 */
3531static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003532xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3533{
3534 xmlChar *str = NULL;
3535 xmlSchemaTreeItemPtr term;
3536 char shift[100];
3537 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003538
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003539 if (particle == NULL)
3540 return;
3541 for (i = 0;((i < depth) && (i < 25));i++)
3542 shift[2 * i] = shift[2 * i + 1] = ' ';
3543 shift[2 * i] = shift[2 * i + 1] = 0;
3544 fprintf(output, shift);
3545 if (particle->children == NULL) {
3546 fprintf(output, "MISSING particle term\n");
3547 return;
3548 }
3549 term = particle->children;
3550 switch (term->type) {
3551 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003552 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003553 ((xmlSchemaElementPtr)term)->targetNamespace,
3554 ((xmlSchemaElementPtr)term)->name));
3555 break;
3556 case XML_SCHEMA_TYPE_SEQUENCE:
3557 fprintf(output, "SEQUENCE");
3558 break;
3559 case XML_SCHEMA_TYPE_CHOICE:
3560 fprintf(output, "CHOICE");
3561 break;
3562 case XML_SCHEMA_TYPE_ALL:
3563 fprintf(output, "ALL");
3564 break;
3565 case XML_SCHEMA_TYPE_ANY:
3566 fprintf(output, "ANY");
3567 break;
3568 default:
3569 fprintf(output, "UNKNOWN\n");
3570 return;
3571 }
3572 if (particle->minOccurs != 1)
3573 fprintf(output, " min: %d", particle->minOccurs);
3574 if (particle->maxOccurs >= UNBOUNDED)
3575 fprintf(output, " max: unbounded");
3576 else if (particle->maxOccurs != 1)
3577 fprintf(output, " max: %d", particle->maxOccurs);
3578 fprintf(output, "\n");
3579 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3580 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3581 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3582 (term->children != NULL)) {
3583 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3584 output, depth +1);
3585 }
3586 if (particle->next != NULL)
3587 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3588 output, depth);
3589}
3590/**
3591 * xmlSchemaTypeDump:
3592 * @output: the file output
3593 * @type: a type structure
3594 *
3595 * Dump a SchemaType structure
3596 */
3597static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003598xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3599{
3600 if (type == NULL) {
3601 fprintf(output, "Type: NULL\n");
3602 return;
3603 }
3604 fprintf(output, "Type: ");
3605 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003606 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "no name ");
3609 if (type->targetNamespace != NULL)
3610 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 switch (type->type) {
3612 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003613 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 break;
3615 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 break;
3618 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003619 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 break;
3621 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003622 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 break;
3624 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
3630 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 break;
3633 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 break;
3636 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 break;
3639 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003642 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003646 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 break;
3648 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 break;
3651 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 break;
3654 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 break;
3657 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003658 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003659 break;
3660 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003661 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 break;
3663 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 break;
3666 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003667 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669 }
3670 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003671 if (type->base != NULL) {
3672 fprintf(output, " base type: %s", type->base);
3673 if (type->baseNs != NULL)
3674 fprintf(output, " ns %s\n", type->baseNs);
3675 else
3676 fprintf(output, "\n");
3677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 if (type->annot != NULL)
3679 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003680#ifdef DUMP_CONTENT_MODEL
3681 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3682 (type->subtypes != NULL)) {
3683 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3684 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003686#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003687}
3688
3689/**
3690 * xmlSchemaDump:
3691 * @output: the file output
3692 * @schema: a schema structure
3693 *
3694 * Dump a Schema structure.
3695 */
3696void
3697xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3698{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003699 if (output == NULL)
3700 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 if (schema == NULL) {
3702 fprintf(output, "Schemas: NULL\n");
3703 return;
3704 }
3705 fprintf(output, "Schemas: ");
3706 if (schema->name != NULL)
3707 fprintf(output, "%s, ", schema->name);
3708 else
3709 fprintf(output, "no name, ");
3710 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003711 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 else
3713 fprintf(output, "no target namespace");
3714 fprintf(output, "\n");
3715 if (schema->annot != NULL)
3716 xmlSchemaAnnotDump(output, schema->annot);
3717
3718 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3719 output);
3720 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003723
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003724#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003725/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003726 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003727 * @vctxt: the WXS validation context
3728 *
3729 * Displays the current IDC table for debug purposes.
3730 */
3731static void
3732xmlSchemaDebugDumpIDCTable(FILE * output,
3733 const xmlChar *namespaceName,
3734 const xmlChar *localName,
3735 xmlSchemaPSVIIDCBindingPtr bind)
3736{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003737 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003738 xmlSchemaPSVIIDCNodePtr tab;
3739 xmlSchemaPSVIIDCKeyPtr key;
3740 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741
3742 fprintf(output, "IDC: TABLES on %s\n",
3743 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003744 FREE_AND_NULL(str)
3745
3746 if (bind == NULL)
3747 return;
3748 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 fprintf(output, "IDC: BINDING %s\n",
3750 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003751 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003753 for (i = 0; i < bind->nbNodes; i++) {
3754 tab = bind->nodeTable[i];
3755 fprintf(output, " ( ");
3756 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003757 key = tab->keys[j];
3758 if ((key != NULL) && (key->val != NULL)) {
3759 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003760 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003761 fprintf(output, "\"%s\" ", value);
3762 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003763 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003764 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003765 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003766 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003767 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003768 else
3769 fprintf(output, "(key missing), ");
3770 }
3771 fprintf(output, ")\n");
3772 }
3773 bind = bind->next;
3774 } while (bind != NULL);
3775}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003776#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003777#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003778
3779/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003780 * *
3781 * Utilities *
3782 * *
3783 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003784
Daniel Veillardc0826a72004-08-10 14:17:33 +00003785/**
3786 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003787 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003788 * @name: the name of the attribute
3789 *
3790 * Seeks an attribute with a name of @name in
3791 * no namespace.
3792 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003794 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003795static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003796xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003797{
3798 xmlAttrPtr prop;
3799
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003800 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003801 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003802 prop = node->properties;
3803 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003805 return(prop);
3806 prop = prop->next;
3807 }
3808 return (NULL);
3809}
3810
3811/**
3812 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003813 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003814 * @uri: the uri
3815 * @name: the name of the attribute
3816 *
3817 * Seeks an attribute with a local name of @name and
3818 * a namespace URI of @uri.
3819 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003820 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003821 */
3822static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003823xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003824{
3825 xmlAttrPtr prop;
3826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003827 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003828 return(NULL);
3829 prop = node->properties;
3830 while (prop != NULL) {
3831 if ((prop->ns != NULL) &&
3832 xmlStrEqual(prop->name, BAD_CAST name) &&
3833 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003834 return(prop);
3835 prop = prop->next;
3836 }
3837 return (NULL);
3838}
3839
3840static const xmlChar *
3841xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3842{
3843 xmlChar *val;
3844 const xmlChar *ret;
3845
3846 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003847 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003848 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003849 ret = xmlDictLookup(ctxt->dict, val, -1);
3850 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003852}
3853
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003854/**
3855 * xmlSchemaGetProp:
3856 * @ctxt: the parser context
3857 * @node: the node
3858 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003859 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003860 * Read a attribute value and internalize the string
3861 *
3862 * Returns the string or NULL if not present.
3863 */
3864static const xmlChar *
3865xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3866 const char *name)
3867{
3868 xmlChar *val;
3869 const xmlChar *ret;
3870
3871 val = xmlGetProp(node, BAD_CAST name);
3872 if (val == NULL)
3873 return(NULL);
3874 ret = xmlDictLookup(ctxt->dict, val, -1);
3875 xmlFree(val);
3876 return(ret);
3877}
3878
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003879/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 * *
3881 * Parsing functions *
3882 * *
3883 ************************************************************************/
3884
3885/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003887 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003888 * @name: the element name
3889 * @ns: the element namespace
3890 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003891 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003893 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003894 */
3895static xmlSchemaElementPtr
3896xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898{
3899 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003900
3901 if ((name == NULL) || (schema == NULL))
3902 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003905 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003906 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003907 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003908 } else
3909 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003910 /*
3911 * This one was removed, since top level element declarations have
3912 * the target namespace specified in targetNamespace of the <schema>
3913 * information element, even if elementFormDefault is "unqualified".
3914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915
William M. Bracke7091952004-05-11 15:09:58 +00003916 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917 if (xmlStrEqual(namespace, schema->targetNamespace))
3918 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3919 else
3920 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003921 if ((ret != NULL) &&
3922 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003924 }
William M. Bracke7091952004-05-11 15:09:58 +00003925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003926
William M. Brack2f2a6632004-08-20 23:09:47 +00003927 /*
3928 * Removed since imported components will be hold by the main schema only.
3929 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003930 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003931 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003932 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003934 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003935 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003936 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3937 return (ret);
3938 } else
3939 ret = NULL;
3940 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942#ifdef DEBUG
3943 if (ret == NULL) {
3944 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003945 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003947 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 namespace);
3949 }
3950#endif
3951 return (ret);
3952}
3953
3954/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 * xmlSchemaGetType:
3956 * @schema: the schemas context
3957 * @name: the type name
3958 * @ns: the type namespace
3959 *
3960 * Lookup a type in the schemas or the predefined types
3961 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003962 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 */
3964static xmlSchemaTypePtr
3965xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 const xmlChar * namespace)
3967{
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 xmlSchemaTypePtr ret;
3969
3970 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003971 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003972 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003973 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003974 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003975 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003976 }
3977 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003978 if (ret != NULL)
3979 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003980 /*
3981 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003983 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003984 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003985 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003986 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003987 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003988 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003989 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3990 return (ret);
3991 } else
3992 ret = NULL;
3993 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003994 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003995#ifdef DEBUG
3996 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003997 if (namespace == NULL)
3998 fprintf(stderr, "Unable to lookup type %s", name);
3999 else
4000 fprintf(stderr, "Unable to lookup type %s:%s", name,
4001 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004002 }
4003#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004004 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004005}
4006
Daniel Veillard3646d642004-06-02 19:19:14 +00004007/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004008 * xmlSchemaGetAttributeDecl:
4009 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004010 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004011 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004012 *
4013 * Lookup a an attribute in the schema or imported schemas
4014 *
4015 * Returns the attribute declaration or NULL if not found.
4016 */
4017static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 const xmlChar * namespace)
4020{
4021 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004022
4023 if ((name == NULL) || (schema == NULL))
4024 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004025
4026
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4028 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004029 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 else
4031 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004032 /*
4033 * Removed, since imported components will be hold by the main schema only.
4034 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004035 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004037 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004040 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4042 return (ret);
4043 } else
4044 ret = NULL;
4045 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004046 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004047#ifdef DEBUG
4048 if (ret == NULL) {
4049 if (namespace == NULL)
4050 fprintf(stderr, "Unable to lookup attribute %s", name);
4051 else
4052 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4053 namespace);
4054 }
4055#endif
4056 return (ret);
4057}
4058
4059/**
4060 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004061 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004062 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004063 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004064 *
4065 * Lookup a an attribute group in the schema or imported schemas
4066 *
4067 * Returns the attribute group definition or NULL if not found.
4068 */
4069static xmlSchemaAttributeGroupPtr
4070xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4071 const xmlChar * namespace)
4072{
4073 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004074
4075 if ((name == NULL) || (schema == NULL))
4076 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004077
4078
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4080 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 else
4083 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004084 /*
4085 * Removed since imported components will be hold by the main schema only.
4086 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004087 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004090 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 if (import != NULL) {
4092 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4093 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4094 return (ret);
4095 else
4096 ret = NULL;
4097 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004098 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004099#ifdef DEBUG
4100 if (ret == NULL) {
4101 if (namespace == NULL)
4102 fprintf(stderr, "Unable to lookup attribute group %s", name);
4103 else
4104 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4105 namespace);
4106 }
4107#endif
4108 return (ret);
4109}
4110
4111/**
4112 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004113 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004114 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004115 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004116 *
4117 * Lookup a group in the schema or imported schemas
4118 *
4119 * Returns the group definition or NULL if not found.
4120 */
4121static xmlSchemaTypePtr
4122xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4123 const xmlChar * namespace)
4124{
4125 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004126
4127 if ((name == NULL) || (schema == NULL))
4128 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004129
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004131 /*
4132 * Removed since imported components will be hold by the main schema only.
4133 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004134 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004135 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004136 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004137 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004138 if (import != NULL) {
4139 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4140 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4141 return (ret);
4142 else
4143 ret = NULL;
4144 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004146#ifdef DEBUG
4147 if (ret == NULL) {
4148 if (namespace == NULL)
4149 fprintf(stderr, "Unable to lookup group %s", name);
4150 else
4151 fprintf(stderr, "Unable to lookup group %s:%s", name,
4152 namespace);
4153 }
4154#endif
4155 return (ret);
4156}
4157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004158/**
4159 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004160 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004161 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004162 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004163 *
4164 * Lookup a group in the schema or imported schemas
4165 *
4166 * Returns the group definition or NULL if not found.
4167 */
4168static xmlSchemaTreeItemPtr
4169xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4170 xmlSchemaTypeType itemType,
4171 const xmlChar *name,
4172 const xmlChar *targetNs)
4173{
4174 switch (itemType) {
4175 case XML_SCHEMA_TYPE_GROUP:
4176 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4177 name, targetNs));
4178 case XML_SCHEMA_TYPE_ELEMENT:
4179 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4180 name, targetNs));
4181 default:
4182 return (NULL);
4183 }
4184}
4185
Daniel Veillard4255d502002-04-16 15:50:10 +00004186/************************************************************************
4187 * *
4188 * Parsing functions *
4189 * *
4190 ************************************************************************/
4191
4192#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004194
4195/**
4196 * xmlSchemaIsBlank:
4197 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004198 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 *
4200 * Check if a string is ignorable
4201 *
4202 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4203 */
4204static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004205xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004206{
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004208 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004209 if (len < 0) {
4210 while (*str != 0) {
4211 if (!(IS_BLANK_CH(*str)))
4212 return (0);
4213 str++;
4214 }
4215 } else while ((*str != 0) && (len != 0)) {
4216 if (!(IS_BLANK_CH(*str)))
4217 return (0);
4218 str++;
4219 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004220 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004221
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004222 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004223}
4224
4225/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004226 * xmlSchemaAddAssembledItem:
4227 * @ctxt: a schema parser context
4228 * @schema: the schema being built
4229 * @item: the item
4230 *
4231 * Add a item to the schema's list of current items.
4232 * This is used if the schema was already constructed and
4233 * new schemata need to be added to it.
4234 * *WARNING* this interface is highly subject to change.
4235 *
4236 * Returns 0 if suceeds and -1 if an internal error occurs.
4237 */
4238static int
4239xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4240 xmlSchemaTypePtr item)
4241{
4242 static int growSize = 100;
4243 xmlSchemaAssemblePtr ass;
4244
4245 ass = ctxt->assemble;
4246 if (ass->sizeItems < 0) {
4247 /* If disabled. */
4248 return (0);
4249 }
4250 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004251 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004252 if (ass->items == NULL) {
4253 xmlSchemaPErrMemory(ctxt,
4254 "allocating new item buffer", NULL);
4255 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004256 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004257 ass->sizeItems = growSize;
4258 } else if (ass->sizeItems <= ass->nbItems) {
4259 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004260 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004261 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4262 if (ass->items == NULL) {
4263 xmlSchemaPErrMemory(ctxt,
4264 "growing item buffer", NULL);
4265 ass->sizeItems = 0;
4266 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004267 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004269 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004270 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4271 return (0);
4272}
4273
4274/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004276 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004277 * @schema: the schema being built
4278 * @name: the item name
4279 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004280 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 * *WARNING* this interface is highly subject to change
4282 *
4283 * Returns the new struture or NULL in case of error
4284 */
4285static xmlSchemaNotationPtr
4286xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004287 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004288{
4289 xmlSchemaNotationPtr ret = NULL;
4290 int val;
4291
4292 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4293 return (NULL);
4294
4295 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004296 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 if (schema->notaDecl == NULL)
4298 return (NULL);
4299
4300 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4301 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 return (NULL);
4304 }
4305 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004306 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4308 ret);
4309 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 /*
4311 * TODO: This should never happen, since a unique name will be computed.
4312 * If it fails, then an other internal error must have occured.
4313 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004314 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4315 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004316 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 xmlFree(ret);
4319 return (NULL);
4320 }
4321 return (ret);
4322}
4323
4324
4325/**
4326 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004327 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 * @schema: the schema being built
4329 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004330 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 *
4332 * Add an XML schema Attrribute declaration
4333 * *WARNING* this interface is highly subject to change
4334 *
4335 * Returns the new struture or NULL in case of error
4336 */
4337static xmlSchemaAttributePtr
4338xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004339 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004340 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004341{
4342 xmlSchemaAttributePtr ret = NULL;
4343 int val;
4344
4345 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4346 return (NULL);
4347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004348#ifdef DEBUG
4349 fprintf(stderr, "Adding attribute %s\n", name);
4350 if (namespace != NULL)
4351 fprintf(stderr, " target namespace %s\n", namespace);
4352#endif
4353
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004355 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 if (schema->attrDecl == NULL)
4357 return (NULL);
4358
4359 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4360 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 return (NULL);
4363 }
4364 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004365 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004366 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004368 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004370 if (topLevel) {
4371 xmlSchemaPCustomErr(ctxt,
4372 XML_SCHEMAP_REDEFINED_ATTR,
4373 NULL, NULL, node,
4374 "A global attribute declaration with the name '%s' does "
4375 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004376 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004377 return (NULL);
4378 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004379 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 /*
4381 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4382 * in the scenario:
4383 * 1. multiple top-level complex types have different target
4384 * namespaces but have the SAME NAME; this can happen if
4385 * schemata are imported
4386 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004387 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004388 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004389 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004390 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004391 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004392 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004393
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004394 if (val != 0) {
4395 xmlSchemaPCustomErr(ctxt,
4396 XML_SCHEMAP_INTERNAL,
4397 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004398 "Internal error: xmlSchemaAddAttribute, "
4399 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004400 "could not be added to the hash.", name);
4401 xmlFree(ret);
4402 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004403 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004404 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004406 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004407 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 return (ret);
4409}
4410
4411/**
4412 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004413 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004414 * @schema: the schema being built
4415 * @name: the item name
4416 *
4417 * Add an XML schema Attrribute Group declaration
4418 *
4419 * Returns the new struture or NULL in case of error
4420 */
4421static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004423 xmlSchemaPtr schema, const xmlChar * name,
4424 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004425{
4426 xmlSchemaAttributeGroupPtr ret = NULL;
4427 int val;
4428
4429 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4430 return (NULL);
4431
4432 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004433 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 if (schema->attrgrpDecl == NULL)
4435 return (NULL);
4436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 ret =
4438 (xmlSchemaAttributeGroupPtr)
4439 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 return (NULL);
4443 }
4444 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004445 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004449 xmlSchemaPCustomErr(ctxt,
4450 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4451 NULL, NULL, node,
4452 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 xmlFree(ret);
4454 return (NULL);
4455 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004456 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004457 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 return (ret);
4459}
4460
4461/**
4462 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004463 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 * @schema: the schema being built
4465 * @name: the type name
4466 * @namespace: the type namespace
4467 *
4468 * Add an XML schema Element declaration
4469 * *WARNING* this interface is highly subject to change
4470 *
4471 * Returns the new struture or NULL in case of error
4472 */
4473static xmlSchemaElementPtr
4474xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004475 const xmlChar * name, const xmlChar * namespace,
4476 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004477{
4478 xmlSchemaElementPtr ret = NULL;
4479 int val;
4480
4481 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4482 return (NULL);
4483
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004484#ifdef DEBUG
4485 fprintf(stderr, "Adding element %s\n", name);
4486 if (namespace != NULL)
4487 fprintf(stderr, " target namespace %s\n", namespace);
4488#endif
4489
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004491 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 if (schema->elemDecl == NULL)
4493 return (NULL);
4494
4495 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004497 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (NULL);
4499 }
4500 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004501 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 if (topLevel) {
4506 xmlSchemaPCustomErr(ctxt,
4507 XML_SCHEMAP_REDEFINED_ELEMENT,
4508 NULL, NULL, node,
4509 "A global element declaration with the name '%s' does "
4510 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 xmlFree(ret);
4512 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004513 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004514 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004515
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004516 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004517 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004518 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004519 if (val != 0) {
4520 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004521 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004522 NULL, NULL, node,
4523 "Internal error: xmlSchemaAddElement, "
4524 "a dublicate element declaration with the name '%s' "
4525 "could not be added to the hash.", name);
4526 xmlFree(ret);
4527 return (NULL);
4528 }
4529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004530
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004532 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004533 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 return (ret);
4535}
4536
4537/**
4538 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004539 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 * @schema: the schema being built
4541 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004544 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 * *WARNING* this interface is highly subject to change
4546 *
4547 * Returns the new struture or NULL in case of error
4548 */
4549static xmlSchemaTypePtr
4550xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004551 const xmlChar * name, const xmlChar * namespace,
4552 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004553{
4554 xmlSchemaTypePtr ret = NULL;
4555 int val;
4556
4557 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4558 return (NULL);
4559
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004560#ifdef DEBUG
4561 fprintf(stderr, "Adding type %s\n", name);
4562 if (namespace != NULL)
4563 fprintf(stderr, " target namespace %s\n", namespace);
4564#endif
4565
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004567 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004568 if (schema->typeDecl == NULL)
4569 return (NULL);
4570
4571 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4572 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 return (NULL);
4575 }
4576 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004577 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004578 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004579 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004580 if (val != 0) {
4581 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004582 xmlSchemaPCustomErr(ctxt,
4583 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 NULL, NULL, node,
4585 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004586 xmlFree(ret);
4587 return (NULL);
4588 } else {
4589 xmlSchemaTypePtr prev;
4590
4591 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4592 if (prev == NULL) {
4593 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004594 XML_ERR_INTERNAL_ERROR,
4595 "Internal error: xmlSchemaAddType, on type "
4596 "'%s'.\n",
4597 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004598 xmlFree(ret);
4599 return (NULL);
4600 }
4601 ret->redef = prev->redef;
4602 prev->redef = ret;
4603 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004604 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004605 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004606 ret->minOccurs = 1;
4607 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004608 ret->attributeUses = NULL;
4609 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004611 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004612 return (ret);
4613}
4614
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004615static xmlSchemaQNameRefPtr
4616xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4617 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004619 const xmlChar *refNs)
4620{
4621 xmlSchemaQNameRefPtr ret;
4622
4623 ret = (xmlSchemaQNameRefPtr)
4624 xmlMalloc(sizeof(xmlSchemaQNameRef));
4625 if (ret == NULL) {
4626 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4627 NULL);
4628 return (NULL);
4629 }
4630 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4631 ret->name = refName;
4632 ret->targetNamespace = refNs;
4633 ret->item = NULL;
4634 ret->itemType = refType;
4635 /*
4636 * Store the reference item in the schema.
4637 */
4638 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4639 return (ret);
4640}
4641
4642/**
4643 * xmlSchemaAddModelGroup:
4644 * @ctxt: a schema parser context
4645 * @schema: the schema being built
4646 * @type: the "compositor" type of the model group
4647 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004648 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004649 *
4650 * Adds a schema model group
4651 * *WARNING* this interface is highly subject to change
4652 *
4653 * Returns the new struture or NULL in case of error
4654 */
4655static xmlSchemaModelGroupPtr
4656xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4657 xmlSchemaTypeType type, const xmlChar **container,
4658 xmlNodePtr node)
4659{
4660 xmlSchemaModelGroupPtr ret = NULL;
4661 xmlChar buf[30];
4662
4663 if ((ctxt == NULL) || (schema == NULL))
4664 return (NULL);
4665
4666#ifdef DEBUG
4667 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004668#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004669 ret = (xmlSchemaModelGroupPtr)
4670 xmlMalloc(sizeof(xmlSchemaModelGroup));
4671 if (ret == NULL) {
4672 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4673 NULL);
4674 return (NULL);
4675 }
4676 ret->type = type;
4677 ret->annot = NULL;
4678 ret->node = node;
4679 ret->children = NULL;
4680 ret->next = NULL;
4681 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4682 if (container != NULL)
4683 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4684 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004685 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004686 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4687 } else {
4688 if (container != NULL)
4689 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4690 }
4691 if (container != NULL)
4692 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4693 /*
4694 * Add to volatile items.
4695 * TODO: this should be changed someday.
4696 */
4697 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4698 xmlFree(ret);
4699 return (NULL);
4700 }
4701 return (ret);
4702}
4703
4704
4705/**
4706 * xmlSchemaAddParticle:
4707 * @ctxt: a schema parser context
4708 * @schema: the schema being built
4709 * @node: the corresponding node in the schema doc
4710 * @min: the minOccurs
4711 * @max: the maxOccurs
4712 *
4713 * Adds an XML schema particle component.
4714 * *WARNING* this interface is highly subject to change
4715 *
4716 * Returns the new struture or NULL in case of error
4717 */
4718static xmlSchemaParticlePtr
4719xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4720 xmlNodePtr node, int min, int max)
4721{
4722 xmlSchemaParticlePtr ret = NULL;
4723 if ((ctxt == NULL) || (schema == NULL))
4724 return (NULL);
4725
4726#ifdef DEBUG
4727 fprintf(stderr, "Adding particle component\n");
4728#endif
4729 ret = (xmlSchemaParticlePtr)
4730 xmlMalloc(sizeof(xmlSchemaParticle));
4731 if (ret == NULL) {
4732 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4733 NULL);
4734 return (NULL);
4735 }
4736 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4737 ret->annot = NULL;
4738 ret->node = node;
4739 ret->minOccurs = min;
4740 ret->maxOccurs = max;
4741 ret->next = NULL;
4742 ret->children = NULL;
4743
4744 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4745 xmlFree(ret);
4746 return (NULL);
4747 }
4748 return (ret);
4749}
4750
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004751/**
4752 * xmlSchemaAddGroup:
4753 * @ctxt: a schema validation context
4754 * @schema: the schema being built
4755 * @name: the group name
4756 *
4757 * Add an XML schema Group definition
4758 *
4759 * Returns the new struture or NULL in case of error
4760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004761static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004762xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004763 const xmlChar *name, const xmlChar *namespaceName,
4764 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004766 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004767 int val;
4768
4769 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4770 return (NULL);
4771
4772 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004773 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004774 if (schema->groupDecl == NULL)
4775 return (NULL);
4776
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004778 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 return (NULL);
4781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004782 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004783 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004784 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004785 ret->node = node;
4786 ret->targetNamespace = namespaceName;
4787 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004788 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004789 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004790 XML_SCHEMAP_REDEFINED_GROUP,
4791 NULL, NULL, node,
4792 "A global model group definition with the name '%s' does already "
4793 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 xmlFree(ret);
4795 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 }
4797 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004798 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004799 return (ret);
4800}
4801
Daniel Veillard3646d642004-06-02 19:19:14 +00004802/**
4803 * xmlSchemaNewWildcardNs:
4804 * @ctxt: a schema validation context
4805 *
4806 * Creates a new wildcard namespace constraint.
4807 *
4808 * Returns the new struture or NULL in case of error
4809 */
4810static xmlSchemaWildcardNsPtr
4811xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4812{
4813 xmlSchemaWildcardNsPtr ret;
4814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004815 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004816 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4817 if (ret == NULL) {
4818 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004819 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
4821 ret->value = NULL;
4822 ret->next = NULL;
4823 return (ret);
4824}
4825
4826/**
4827 * xmlSchemaAddWildcard:
4828 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004829 * @schema: a schema
4830 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004831 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004832 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004833 *
4834 * Returns the new struture or NULL in case of error
4835 */
4836static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004837xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4838 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004839{
4840 xmlSchemaWildcardPtr ret = NULL;
4841
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 return (NULL);
4844
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004845#ifdef DEBUG
4846 fprintf(stderr, "Adding wildcard component\n");
4847#endif
4848
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4850 if (ret == NULL) {
4851 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4852 return (NULL);
4853 }
4854 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004855 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004856 ret->minOccurs = 1;
4857 ret->maxOccurs = 1;
4858
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004859 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4860 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4861 "Failed to add a wildcard component to the list", NULL);
4862 xmlFree(ret);
4863 return (NULL);
4864 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004865 return (ret);
4866}
4867
Daniel Veillard4255d502002-04-16 15:50:10 +00004868/************************************************************************
4869 * *
4870 * Utilities for parsing *
4871 * *
4872 ************************************************************************/
4873
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004874#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004875/**
4876 * xmlGetQNameProp:
4877 * @ctxt: a schema validation context
4878 * @node: a subtree containing XML Schema informations
4879 * @name: the attribute name
4880 * @namespace: the result namespace if any
4881 *
4882 * Extract a QName Attribute value
4883 *
4884 * Returns the NCName or NULL if not found, and also update @namespace
4885 * with the namespace URI
4886 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004887static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004888xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004890{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004891 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004892 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004893 const xmlChar *ret, *prefix;
4894 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004895 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004896
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004898 attr = xmlSchemaGetPropNode(node, name);
4899 if (attr == NULL)
4900 return (NULL);
4901 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004902
Daniel Veillard4255d502002-04-16 15:50:10 +00004903 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004905
Daniel Veillardba0153a2004-04-01 10:42:31 +00004906 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004907 ns = xmlSearchNs(node->doc, node, 0);
4908 if (ns) {
4909 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4910 return (val);
4911 }
4912 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004913 ret = xmlSplitQName3(val, &len);
4914 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004916 }
4917 ret = xmlDictLookup(ctxt->dict, ret, -1);
4918 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919
4920 ns = xmlSearchNs(node->doc, node, prefix);
4921 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004922 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4923 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004924 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004925 "The QName value '%s' has no corresponding namespace "
4926 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004928 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004931}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004932#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004933
4934/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004935 * xmlSchemaPValAttrNodeQNameValue:
4936 * @ctxt: a schema parser context
4937 * @schema: the schema context
4938 * @ownerDes: the designation of the parent element
4939 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004940 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004941 * @local: the resulting local part if found, the attribute value otherwise
4942 * @uri: the resulting namespace URI if found
4943 *
4944 * Extracts the local name and the URI of a QName value and validates it.
4945 * This one is intended to be used on attribute values that
4946 * should resolve to schema components.
4947 *
4948 * Returns 0, in case the QName is valid, a positive error code
4949 * if not valid and -1 if an internal error occurs.
4950 */
4951static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004952xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004953 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004954 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004955 xmlSchemaTypePtr ownerItem,
4956 xmlAttrPtr attr,
4957 const xmlChar *value,
4958 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004959 const xmlChar **local)
4960{
4961 const xmlChar *pref;
4962 xmlNsPtr ns;
4963 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 *uri = NULL;
4966 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004968 if (ret > 0) {
4969 xmlSchemaPSimpleTypeErr(ctxt,
4970 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4971 ownerItem, (xmlNodePtr) attr,
4972 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4973 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004974 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004975 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004976 } else if (ret < 0)
4977 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978
4979 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004980 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4981 if (ns)
4982 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4983 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4984 /*
4985 * This one takes care of included schemas with no
4986 * target namespace.
4987 */
4988 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004989 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004990 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 return (0);
4992 }
4993 /*
4994 * At this point xmlSplitQName3 has to return a local name.
4995 */
4996 *local = xmlSplitQName3(value, &len);
4997 *local = xmlDictLookup(ctxt->dict, *local, -1);
4998 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5000 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005003 ownerItem, (xmlNodePtr) attr,
5004 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5005 "The value '%s' of simple type 'xs:QName' has no "
5006 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005007 return (ctxt->err);
5008 } else {
5009 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005010 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 return (0);
5012}
5013
5014/**
5015 * xmlSchemaPValAttrNodeQName:
5016 * @ctxt: a schema parser context
5017 * @schema: the schema context
5018 * @ownerDes: the designation of the owner element
5019 * @ownerItem: the owner as a schema object
5020 * @attr: the attribute node
5021 * @local: the resulting local part if found, the attribute value otherwise
5022 * @uri: the resulting namespace URI if found
5023 *
5024 * Extracts and validates the QName of an attribute value.
5025 * This one is intended to be used on attribute values that
5026 * should resolve to schema components.
5027 *
5028 * Returns 0, in case the QName is valid, a positive error code
5029 * if not valid and -1 if an internal error occurs.
5030 */
5031static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005032xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005033 xmlSchemaPtr schema,
5034 xmlChar **ownerDes,
5035 xmlSchemaTypePtr ownerItem,
5036 xmlAttrPtr attr,
5037 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005038 const xmlChar **local)
5039{
5040 const xmlChar *value;
5041
5042 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005043 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5044 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045}
5046
5047/**
5048 * xmlSchemaPValAttrQName:
5049 * @ctxt: a schema parser context
5050 * @schema: the schema context
5051 * @ownerDes: the designation of the parent element
5052 * @ownerItem: the owner as a schema object
5053 * @ownerElem: the parent node of the attribute
5054 * @name: the name of the attribute
5055 * @local: the resulting local part if found, the attribute value otherwise
5056 * @uri: the resulting namespace URI if found
5057 *
5058 * Extracts and validates the QName of an attribute value.
5059 *
5060 * Returns 0, in case the QName is valid, a positive error code
5061 * if not valid and -1 if an internal error occurs.
5062 */
5063static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005064xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5065 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005066 xmlChar **ownerDes,
5067 xmlSchemaTypePtr ownerItem,
5068 xmlNodePtr ownerElem,
5069 const char *name,
5070 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 const xmlChar **local)
5072{
5073 xmlAttrPtr attr;
5074
5075 attr = xmlSchemaGetPropNode(ownerElem, name);
5076 if (attr == NULL) {
5077 *local = NULL;
5078 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005079 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005081 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5082 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083}
5084
5085/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005086 * xmlSchemaPValAttrID:
5087 * @ctxt: a schema parser context
5088 * @schema: the schema context
5089 * @ownerDes: the designation of the parent element
5090 * @ownerItem: the owner as a schema object
5091 * @ownerElem: the parent node of the attribute
5092 * @name: the name of the attribute
5093 *
5094 * Extracts and validates the ID of an attribute value.
5095 *
5096 * Returns 0, in case the ID is valid, a positive error code
5097 * if not valid and -1 if an internal error occurs.
5098 */
5099static int
5100xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005101 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005102 xmlSchemaTypePtr ownerItem,
5103 xmlNodePtr ownerElem,
5104 const xmlChar *name)
5105{
5106 int ret;
5107 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005108 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005109
5110 value = xmlGetNoNsProp(ownerElem, name);
5111 if (value == NULL)
5112 return (0);
5113
5114 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5115 if (attr == NULL)
5116 return (-1);
5117
5118 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005119 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 /*
5121 * NOTE: the IDness might have already be declared in the DTD
5122 */
5123 if (attr->atype != XML_ATTRIBUTE_ID) {
5124 xmlIDPtr res;
5125 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005126
5127 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005128 * TODO: Use xmlSchemaStrip here; it's not exported at this
5129 * moment.
5130 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005131 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005132 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005133 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005134 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5135 if (res == NULL) {
5136 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005137 xmlSchemaPSimpleTypeErr(ctxt,
5138 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5139 ownerItem, (xmlNodePtr) attr,
5140 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5141 NULL, NULL, "Duplicate value '%s' of simple "
5142 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005143 } else
5144 attr->atype = XML_ATTRIBUTE_ID;
5145 if (strip != NULL)
5146 xmlFree(strip);
5147 }
5148 } else if (ret > 0) {
5149 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005150 xmlSchemaPSimpleTypeErr(ctxt,
5151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5152 ownerItem, (xmlNodePtr) attr,
5153 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5154 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5155 "not a valid 'xs:NCName'",
5156 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005157 }
5158 xmlFree(value);
5159
5160 return (ret);
5161}
5162
5163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 * xmlGetMaxOccurs:
5165 * @ctxt: a schema validation context
5166 * @node: a subtree containing XML Schema informations
5167 *
5168 * Get the maxOccurs property
5169 *
5170 * Returns the default if not found, or the value
5171 */
5172static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005173xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5174 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005176 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005177 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5181 if (attr == NULL)
5182 return (def);
5183 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005184
5185 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005186 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005187 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5189 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005190 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005191 val, NULL, NULL, NULL);
5192 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 }
5196
5197 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005198 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005200 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005201 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005202 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5203 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005204 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005205 val, NULL, NULL, NULL);
5206 return (def);
5207 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005208 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 ret = ret * 10 + (*cur - '0');
5210 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 }
William M. Brack76e95df2003-10-18 16:20:14 +00005212 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 /*
5215 * TODO: Restrict the maximal value to Integer.
5216 */
5217 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005218 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005219 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5220 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005221 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005222 val, NULL, NULL, NULL);
5223 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005225 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005226}
5227
5228/**
5229 * xmlGetMinOccurs:
5230 * @ctxt: a schema validation context
5231 * @node: a subtree containing XML Schema informations
5232 *
5233 * Get the minOccurs property
5234 *
5235 * Returns the default if not found, or the value
5236 */
5237static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005238xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005239 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005241 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 attr = xmlSchemaGetPropNode(node, "minOccurs");
5246 if (attr == NULL)
5247 return (def);
5248 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005250 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005252 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005253 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005254 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5255 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005256 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005257 val, NULL, NULL, NULL);
5258 return (def);
5259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 ret = ret * 10 + (*cur - '0');
5262 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 }
William M. Brack76e95df2003-10-18 16:20:14 +00005264 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 /*
5267 * TODO: Restrict the maximal value to Integer.
5268 */
5269 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005270 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005271 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5272 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005273 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005274 val, NULL, NULL, NULL);
5275 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005276 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005278}
5279
5280/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005281 * xmlSchemaPGetBoolNodeValue:
5282 * @ctxt: a schema validation context
5283 * @ownerDes: owner designation
5284 * @ownerItem: the owner as a schema item
5285 * @node: the node holding the value
5286 *
5287 * Converts a boolean string value into 1 or 0.
5288 *
5289 * Returns 0 or 1.
5290 */
5291static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005292xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5293 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005294 xmlSchemaTypePtr ownerItem,
5295 xmlNodePtr node)
5296{
5297 xmlChar *value = NULL;
5298 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005299
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005300 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005301 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005302 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005303 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 * can have the following legal literals {true, false, 1, 0}.
5305 */
5306 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5307 res = 1;
5308 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5309 res = 0;
5310 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5311 res = 1;
5312 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005315 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005316 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005317 ownerItem, node,
5318 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5319 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005320 NULL, NULL, NULL);
5321 }
5322 if (value != NULL)
5323 xmlFree(value);
5324 return (res);
5325}
5326
5327/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005328 * xmlGetBooleanProp:
5329 * @ctxt: a schema validation context
5330 * @node: a subtree containing XML Schema informations
5331 * @name: the attribute name
5332 * @def: the default value
5333 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005335 *
5336 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 */
5339static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005340xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5341 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005342 xmlSchemaTypePtr ownerItem,
5343 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 const char *name, int def)
5345{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005346 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005348 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005351 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005353 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 * can have the following legal literals {true, false, 1, 0}.
5355 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 if (xmlStrEqual(val, BAD_CAST "true"))
5357 def = 1;
5358 else if (xmlStrEqual(val, BAD_CAST "false"))
5359 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005360 else if (xmlStrEqual(val, BAD_CAST "1"))
5361 def = 1;
5362 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 def = 0;
5364 else {
5365 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005366 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005367 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005368 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5370 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373}
5374
5375/************************************************************************
5376 * *
5377 * Shema extraction from an Infoset *
5378 * *
5379 ************************************************************************/
5380static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5381 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005382 xmlNodePtr node,
5383 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005384static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5385 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005386 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005387 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005388 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5390 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005392 xmlNodePtr node,
5393 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005394static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5395 ctxt,
5396 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005397 xmlNodePtr node,
5398 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005399static xmlSchemaAttributeGroupPtr
5400xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005401 xmlSchemaPtr schema, xmlNodePtr node,
5402 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005403static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5404 xmlSchemaPtr schema,
5405 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005406static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5408 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409
5410/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005411 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005412 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005413 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005414 * @ownerDes: the designation of the parent element
5415 * @ownerItem: the schema object owner if existent
5416 * @attr: the schema attribute node being validated
5417 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005418 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005419 *
5420 * Validates a value against the given built-in type.
5421 * This one is intended to be used internally for validation
5422 * of schema attribute values during parsing of the schema.
5423 *
5424 * Returns 0 if the value is valid, a positive error code
5425 * number otherwise and -1 in case of an internal or API error.
5426 */
5427static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5429 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5430 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005431 xmlAttrPtr attr,
5432 const xmlChar *value,
5433 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005434{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005435
5436 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005437
5438 /*
5439 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5440 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005441 */
5442 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005443 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005444 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5445 PERROR_INT("xmlSchemaPValAttrNodeValue",
5446 "the given type is not a built-in type");
5447 return (-1);
5448 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005449 switch (type->builtInType) {
5450 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005451 case XML_SCHEMAS_QNAME:
5452 case XML_SCHEMAS_ANYURI:
5453 case XML_SCHEMAS_TOKEN:
5454 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005455 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5456 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005457 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005458 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 PERROR_INT("xmlSchemaPValAttrNodeValue",
5460 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005461 return (-1);
5462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005464 /*
5465 * TODO: Should we use the S4S error codes instead?
5466 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005467 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005468 PERROR_INT("xmlSchemaPValAttrNodeValue",
5469 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005470 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005471 } else if (ret > 0) {
5472 if (VARIETY_LIST(type))
5473 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5474 else
5475 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5476 xmlSchemaPSimpleTypeErr(pctxt,
5477 ret, ownerItem, (xmlNodePtr) attr,
5478 type, NULL, value, NULL, NULL, NULL);
5479 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005480 return (ret);
5481}
5482
5483/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005484 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005485 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005486 * @ctxt: a schema parser context
5487 * @ownerDes: the designation of the parent element
5488 * @ownerItem: the schema object owner if existent
5489 * @attr: the schema attribute node being validated
5490 * @type: the built-in type to be validated against
5491 * @value: the resulting value if any
5492 *
5493 * Extracts and validates a value against the given built-in type.
5494 * This one is intended to be used internally for validation
5495 * of schema attribute values during parsing of the schema.
5496 *
5497 * Returns 0 if the value is valid, a positive error code
5498 * number otherwise and -1 in case of an internal or API error.
5499 */
5500static int
5501xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5502 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 xmlSchemaTypePtr ownerItem,
5504 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 xmlSchemaTypePtr type,
5506 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005507{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005508 const xmlChar *val;
5509
5510 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 return (-1);
5512
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5514 if (value != NULL)
5515 *value = val;
5516
5517 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005518 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005519}
5520
5521/**
5522 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005523 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005524 * @ctxt: a schema parser context
5525 * @node: the element node of the attribute
5526 * @ownerDes: the designation of the parent element
5527 * @ownerItem: the schema object owner if existent
5528 * @ownerElem: the owner element node
5529 * @name: the name of the schema attribute node
5530 * @type: the built-in type to be validated against
5531 * @value: the resulting value if any
5532 *
5533 * Extracts and validates a value against the given built-in type.
5534 * This one is intended to be used internally for validation
5535 * of schema attribute values during parsing of the schema.
5536 *
5537 * Returns 0 if the value is valid, a positive error code
5538 * number otherwise and -1 in case of an internal or API error.
5539 */
5540static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 xmlChar **ownerDes,
5543 xmlSchemaTypePtr ownerItem,
5544 xmlNodePtr ownerElem,
5545 const char *name,
5546 xmlSchemaTypePtr type,
5547 const xmlChar **value)
5548{
5549 xmlAttrPtr attr;
5550
5551 if ((ctxt == NULL) || (type == NULL)) {
5552 if (value != NULL)
5553 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005554 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005555 }
5556 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5557 if (value != NULL)
5558 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005560 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 "Internal error: xmlSchemaPValAttr, the given "
5562 "type '%s' is not a built-in type.\n",
5563 type->name, NULL);
5564 return (-1);
5565 }
5566 attr = xmlSchemaGetPropNode(ownerElem, name);
5567 if (attr == NULL) {
5568 if (value != NULL)
5569 *value = NULL;
5570 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005571 }
5572 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 type, value));
5574}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005575
5576static int
5577xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5578 xmlSchemaPtr schema,
5579 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005580 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005581 const xmlChar *namespaceName)
5582{
5583 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005584 return (1);
5585 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5586 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005587 if (pctxt->localImports != NULL) {
5588 int i;
5589 for (i = 0; i < pctxt->nbLocalImports; i++)
5590 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5591 return (1);
5592 }
5593 if (namespaceName == NULL)
5594 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005595 NULL, (xmlSchemaTypePtr) item, node,
5596 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005597 "namespace are not valid, since not indicated by an import "
5598 "statement", NULL);
5599 else
5600 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005601 NULL, (xmlSchemaTypePtr) item, node,
5602 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005603 "namespace '%s' are not valid, since not indicated by an import "
5604 "statement", namespaceName);
5605 return (0);
5606}
5607
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 * xmlSchemaParseAttrDecls:
5610 * @ctxt: a schema validation context
5611 * @schema: the schema being built
5612 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005613 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 *
5615 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005616 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5618 */
5619static xmlNodePtr
5620xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5621 xmlNodePtr child, xmlSchemaTypePtr type)
5622{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005624
Daniel Veillard4255d502002-04-16 15:50:10 +00005625 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 (IS_SCHEMA(child, "attributeGroup"))) {
5627 attr = NULL;
5628 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005629 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005630 } else if (IS_SCHEMA(child, "attributeGroup")) {
5631 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005632 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 }
5634 if (attr != NULL) {
5635 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005636 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5637 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5638 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005639 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 lastattr = attr;
5641 } else {
5642 lastattr->next = attr;
5643 lastattr = attr;
5644 }
5645 }
5646 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005648 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005649}
5650
5651/**
5652 * xmlSchemaParseAnnotation:
5653 * @ctxt: a schema validation context
5654 * @schema: the schema being built
5655 * @node: a subtree containing XML Schema informations
5656 *
5657 * parse a XML schema Attrribute declaration
5658 * *WARNING* this interface is highly subject to change
5659 *
William M. Bracke7091952004-05-11 15:09:58 +00005660 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 * 1 in case of success.
5662 */
5663static xmlSchemaAnnotPtr
5664xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5665 xmlNodePtr node)
5666{
5667 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005668 xmlNodePtr child = NULL;
5669 xmlAttrPtr attr;
5670 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 /*
5673 * INFO: S4S completed.
5674 */
5675 /*
5676 * id = ID
5677 * {any attributes with non-schema namespace . . .}>
5678 * Content: (appinfo | documentation)*
5679 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5681 return (NULL);
5682 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 attr = node->properties;
5684 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005685 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005687 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005688 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005689
5690 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5692 NULL, NULL, attr);
5693 }
5694 attr = attr->next;
5695 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005696 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 /*
5698 * And now for the children...
5699 */
5700 child = node->children;
5701 while (child != NULL) {
5702 if (IS_SCHEMA(child, "appinfo")) {
5703 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005704 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 * source = anyURI
5706 * {any attributes with non-schema namespace . . .}>
5707 * Content: ({any})*
5708 */
5709 attr = child->properties;
5710 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005711 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005713 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005715
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005716 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005717 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5718 NULL, NULL, attr);
5719 }
5720 attr = attr->next;
5721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005722 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5723 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 child = child->next;
5725 } else if (IS_SCHEMA(child, "documentation")) {
5726 /* TODO: make available the content of "documentation". */
5727 /*
5728 * source = anyURI
5729 * {any attributes with non-schema namespace . . .}>
5730 * Content: ({any})*
5731 */
5732 attr = child->properties;
5733 while (attr != NULL) {
5734 if (attr->ns == NULL) {
5735 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5738 NULL, NULL, attr);
5739 }
5740 } else {
5741 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5742 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5743 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005744
5745 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5747 NULL, NULL, attr);
5748 }
5749 }
5750 attr = attr->next;
5751 }
5752 /*
5753 * Attribute "xml:lang".
5754 */
5755 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5756 if (attr != NULL)
5757 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 child = child->next;
5760 } else {
5761 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005762 xmlSchemaPContentErr(ctxt,
5763 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5765 barked = 1;
5766 child = child->next;
5767 }
5768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 return (ret);
5771}
5772
5773/**
5774 * xmlSchemaParseFacet:
5775 * @ctxt: a schema validation context
5776 * @schema: the schema being built
5777 * @node: a subtree containing XML Schema informations
5778 *
5779 * parse a XML schema Facet declaration
5780 * *WARNING* this interface is highly subject to change
5781 *
5782 * Returns the new type structure or NULL in case of error
5783 */
5784static xmlSchemaFacetPtr
5785xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005787{
5788 xmlSchemaFacetPtr facet;
5789 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005790 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005791
5792 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5793 return (NULL);
5794
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005795 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 if (facet == NULL) {
5797 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5798 return (NULL);
5799 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005801 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5804 "Facet %s has no value\n", node->name, NULL);
5805 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 return (NULL);
5807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5830 } else if (IS_SCHEMA(node, "minLength")) {
5831 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5832 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5834 "Unknown facet type %s\n", node->name, NULL);
5835 xmlSchemaFreeFacet(facet);
5836 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005838 xmlSchemaPValAttrID(ctxt, NULL,
5839 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005841 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5842 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5843 const xmlChar *fixed;
5844
5845 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5846 if (fixed != NULL) {
5847 if (xmlStrEqual(fixed, BAD_CAST "true"))
5848 facet->fixed = 1;
5849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005850 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005851 child = node->children;
5852
5853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005854 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 }
5857 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5859 "Facet %s has unexpected child content\n",
5860 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 }
5862 return (facet);
5863}
5864
5865/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866 * xmlSchemaParseWildcardNs:
5867 * @ctxt: a schema parser context
5868 * @wildc: the wildcard, already created
5869 * @node: a subtree containing XML Schema informations
5870 *
5871 * Parses the attribute "processContents" and "namespace"
5872 * of a xsd:anyAttribute and xsd:any.
5873 * *WARNING* this interface is highly subject to change
5874 *
5875 * Returns 0 if everything goes fine, a positive error code
5876 * if something is not valid and -1 if an internal error occurs.
5877 */
5878static int
5879xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5880 xmlSchemaPtr schema,
5881 xmlSchemaWildcardPtr wildc,
5882 xmlNodePtr node)
5883{
5884 const xmlChar *pc, *ns, *dictnsItem;
5885 int ret = 0;
5886 xmlChar *nsItem;
5887 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5888 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889
Daniel Veillardc0826a72004-08-10 14:17:33 +00005890 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5891 if ((pc == NULL)
5892 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5894 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5895 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5896 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5897 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5898 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005900 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005901 NULL, node,
5902 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005903 NULL, NULL, NULL);
5904 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005905 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005906 }
5907 /*
5908 * Build the namespace constraints.
5909 */
5910 attr = xmlSchemaGetPropNode(node, "namespace");
5911 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005912 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 wildc->any = 1;
5914 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5915 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005916 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005917 return (-1);
5918 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005919 wildc->negNsSet->value = schema->targetNamespace;
5920 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 const xmlChar *end, *cur;
5922
5923 cur = ns;
5924 do {
5925 while (IS_BLANK_CH(*cur))
5926 cur++;
5927 end = cur;
5928 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5929 end++;
5930 if (end == cur)
5931 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005932 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5934 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005935 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005936 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005937 NULL, (xmlNodePtr) attr,
5938 NULL,
5939 "((##any | ##other) | List of (xs:anyURI | "
5940 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 nsItem, NULL, NULL, NULL);
5942 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5943 } else {
5944 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5945 dictnsItem = schema->targetNamespace;
5946 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5947 dictnsItem = NULL;
5948 } else {
5949 /*
5950 * Validate the item (anyURI).
5951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005952 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5954 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5955 }
5956 /*
5957 * Avoid dublicate namespaces.
5958 */
5959 tmp = wildc->nsSet;
5960 while (tmp != NULL) {
5961 if (dictnsItem == tmp->value)
5962 break;
5963 tmp = tmp->next;
5964 }
5965 if (tmp == NULL) {
5966 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5967 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005968 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 return (-1);
5970 }
5971 tmp->value = dictnsItem;
5972 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 wildc->nsSet = tmp;
5975 else
5976 lastNs->next = tmp;
5977 lastNs = tmp;
5978 }
5979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 xmlFree(nsItem);
5982 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005983 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 }
5985 return (ret);
5986}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005987
5988static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005989xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5990 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005991 xmlNodePtr node,
5992 int minOccurs,
5993 int maxOccurs) {
5994
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005995 if ((maxOccurs == 0) && ( minOccurs == 0))
5996 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 if (maxOccurs != UNBOUNDED) {
5998 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 * TODO: Maybe we should better not create the particle,
6000 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 * content model.
6002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006003 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 * 3.9.6 Schema Component Constraint: Particle Correct
6005 *
6006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006007 if (maxOccurs < 1) {
6008 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 * 2.2 {max occurs} must be greater than or equal to 1.
6010 */
6011 xmlSchemaPCustomAttrErr(ctxt,
6012 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006013 NULL, NULL,
6014 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006015 "The value must be greater than or equal to 1");
6016 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6017 } else if (minOccurs > maxOccurs) {
6018 /*
6019 * 2.1 {min occurs} must not be greater than {max occurs}.
6020 */
6021 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006022 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006023 NULL, NULL,
6024 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 "The value must not be greater than the value of 'maxOccurs'");
6026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006028 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006029 return (0);
6030}
6031
Daniel Veillardc0826a72004-08-10 14:17:33 +00006032/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 * xmlSchemaParseAny:
6034 * @ctxt: a schema validation context
6035 * @schema: the schema being built
6036 * @node: a subtree containing XML Schema informations
6037 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006038 * Parsea a XML schema <any> element. A particle and wildcard
6039 * will be created (except if minOccurs==maxOccurs==0, in this case
6040 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006041 * *WARNING* this interface is highly subject to change
6042 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006045static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006046xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6047 xmlNodePtr node)
6048{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006049 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 xmlSchemaWildcardPtr wild;
6052 int min, max;
6053 xmlAttrPtr attr;
6054 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006055
6056 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6057 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006058 /*
6059 * Check for illegal attributes.
6060 */
6061 attr = node->properties;
6062 while (attr != NULL) {
6063 if (attr->ns == NULL) {
6064 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6065 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6066 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6067 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6068 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006069 xmlSchemaPIllegalAttrErr(ctxt,
6070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006072 }
6073 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006074 xmlSchemaPIllegalAttrErr(ctxt,
6075 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6076 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006077 }
6078 attr = attr->next;
6079 }
6080 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6081 /*
6082 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006083 */
6084 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6085 "(xs:nonNegativeInteger | unbounded)");
6086 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6087 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006088 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6089 /*
6090 * Create & parse the wildcard.
6091 */
6092 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6093 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006094 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006095 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006096 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006098 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006102 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 }
6104 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaPContentErr(ctxt,
6106 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006107 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006108 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006110 /*
6111 * No component if minOccurs==maxOccurs==0.
6112 */
6113 if ((min == 0) && (max == 0)) {
6114 /* Don't free the wildcard, since it's already on the list. */
6115 return (NULL);
6116 }
6117 /*
6118 * Create the particle.
6119 */
6120 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6121 if (particle == NULL)
6122 return (NULL);
6123 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006124 wild->minOccurs = min;
6125 wild->maxOccurs = max;
6126 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006128 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006129}
6130
6131/**
6132 * xmlSchemaParseNotation:
6133 * @ctxt: a schema validation context
6134 * @schema: the schema being built
6135 * @node: a subtree containing XML Schema informations
6136 *
6137 * parse a XML schema Notation declaration
6138 *
6139 * Returns the new structure or NULL in case of error
6140 */
6141static xmlSchemaNotationPtr
6142xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006143 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006144{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006145 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 xmlSchemaNotationPtr ret;
6147 xmlNodePtr child = NULL;
6148
6149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6150 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006151 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006152 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6154 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006155 return (NULL);
6156 }
6157 ret = xmlSchemaAddNotation(ctxt, schema, name);
6158 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 return (NULL);
6160 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006161 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006162
6163 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6164 node, BAD_CAST "id");
6165
6166 if (IS_SCHEMA(child, "annotation")) {
6167 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6168 child = child->next;
6169 }
6170
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 child = node->children;
6172 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6174 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006175 }
6176 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006177 xmlSchemaPContentErr(ctxt,
6178 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006180 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 }
6182
6183 return (ret);
6184}
6185
6186/**
6187 * xmlSchemaParseAnyAttribute:
6188 * @ctxt: a schema validation context
6189 * @schema: the schema being built
6190 * @node: a subtree containing XML Schema informations
6191 *
6192 * parse a XML schema AnyAttrribute declaration
6193 * *WARNING* this interface is highly subject to change
6194 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006195 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006197static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006198xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6199 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006200{
Daniel Veillard3646d642004-06-02 19:19:14 +00006201 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006203 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006204
6205 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6206 return (NULL);
6207
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006208 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6209 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006210 if (ret == NULL) {
6211 return (NULL);
6212 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 /*
6214 * Check for illegal attributes.
6215 */
6216 attr = node->properties;
6217 while (attr != NULL) {
6218 if (attr->ns == NULL) {
6219 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6220 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6221 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 xmlSchemaPIllegalAttrErr(ctxt,
6223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6224 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006225 }
6226 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006227 xmlSchemaPIllegalAttrErr(ctxt,
6228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6229 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006230 }
6231 attr = attr->next;
6232 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006233 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6234 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006235 /*
6236 * Parse the namespace list.
6237 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006238 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006239 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 /*
6241 * And now for the children...
6242 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006243 child = node->children;
6244 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006245 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6246 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006247 }
6248 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006249 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006250 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006251 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006252 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 }
6254
6255 return (ret);
6256}
6257
6258
6259/**
6260 * xmlSchemaParseAttribute:
6261 * @ctxt: a schema validation context
6262 * @schema: the schema being built
6263 * @node: a subtree containing XML Schema informations
6264 *
6265 * parse a XML schema Attrribute declaration
6266 * *WARNING* this interface is highly subject to change
6267 *
William M. Bracke7091952004-05-11 15:09:58 +00006268 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006269 */
6270static xmlSchemaAttributePtr
6271xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006272 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006273{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006274 const xmlChar *name, *attrValue;
6275 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006276 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006277 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006278 xmlAttrPtr attr, nameAttr;
6279 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006280
6281 /*
6282 * Note that the w3c spec assumes the schema to be validated with schema
6283 * for schemas beforehand.
6284 *
6285 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006286 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006287
6288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6289 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006290 attr = xmlSchemaGetPropNode(node, "ref");
6291 nameAttr = xmlSchemaGetPropNode(node, "name");
6292
6293 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006297 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006298 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6299 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 "One of the attributes 'ref' or 'name' must be present");
6301 return (NULL);
6302 }
6303 if ((topLevel) || (attr == NULL)) {
6304 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006305 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6306 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006307 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006309 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 isRef = 1;
6311
Daniel Veillardc0826a72004-08-10 14:17:33 +00006312 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006313 char buf[50];
6314 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315
6316 /*
6317 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 */
6319 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6320 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6321 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006324 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006326 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327 if (ret == NULL) {
6328 if (repName != NULL)
6329 xmlFree(repName);
6330 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006331 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6333 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006335 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006336 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6337 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 /*
6339 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6340 */
6341 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6343 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 "ref", "name");
6345 /*
6346 * Check for illegal attributes.
6347 */
6348 attr = node->properties;
6349 while (attr != NULL) {
6350 if (attr->ns == NULL) {
6351 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6352 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006353 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 * 3.2.3 : 3.2
6355 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 xmlSchemaPIllegalAttrErr(ctxt,
6359 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006360 (xmlSchemaTypePtr) ret, attr);
6361 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6362 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6363 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6365 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006366 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006367 xmlSchemaPIllegalAttrErr(ctxt,
6368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6369 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 }
6371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372 xmlSchemaPIllegalAttrErr(ctxt,
6373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6374 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006375 }
6376 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006378 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006379 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006380
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 /*
6382 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006383 */
6384 if (xmlSchemaPValAttrNode(ctxt,
6385 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6387 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006388 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 /*
6390 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6391 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006392 /*
6393 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6394 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 */
6396 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006397 xmlSchemaPSimpleTypeErr(ctxt,
6398 XML_SCHEMAP_NO_XMLNS,
6399 NULL, (xmlNodePtr) nameAttr,
6400 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6401 "The value of type 'xs:NCName' must not match 'xmlns'",
6402 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006403 if (repName != NULL)
6404 xmlFree(repName);
6405 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006406 }
6407 /*
6408 * Evaluate the target namespace
6409 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006410 if (topLevel) {
6411 ns = schema->targetNamespace;
6412 } else {
6413 attr = xmlSchemaGetPropNode(node, "form");
6414 if (attr != NULL) {
6415 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6416 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6417 ns = schema->targetNamespace;
6418 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006419 xmlSchemaPSimpleTypeErr(ctxt,
6420 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6421 NULL, (xmlNodePtr) attr,
6422 NULL, "(qualified | unqualified)",
6423 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006424 }
6425 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 ns = schema->targetNamespace;
6427 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006428 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006429 if (ret == NULL) {
6430 if (repName != NULL)
6431 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006432 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006433 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 if (topLevel)
6437 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 /*
6439 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6440 * TODO: Move this to the component layer.
6441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006442 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006443 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 XML_SCHEMAP_NO_XSI,
6445 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006446 "The target namespace must not match '%s'",
6447 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 }
6449 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006450 * Check for illegal attributes.
6451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 attr = node->properties;
6453 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006454 if (attr->ns == NULL) {
6455 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6456 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6457 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6459 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006461 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6462 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006463 xmlSchemaPIllegalAttrErr(ctxt,
6464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6465 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006466 }
6467 }
6468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006469 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6470 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 }
6472 attr = attr->next;
6473 }
6474 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 node, "type", &ret->typeNs, &ret->typeName);
6476 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006477 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6478 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006479 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6483 if (ret->defValue != NULL)
6484 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006486 * Attribute "default".
6487 */
6488 attr = xmlSchemaGetPropNode(node, "default");
6489 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006492 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 */
6494 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6495 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6496 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6497 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006498 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 /*
6502 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 */
6504 attr = xmlSchemaGetPropNode(node, "use");
6505 if (attr != NULL) {
6506 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6507 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6508 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6509 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6510 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6511 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6512 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6513 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 xmlSchemaPSimpleTypeErr(ctxt,
6515 XML_SCHEMAP_INVALID_ATTR_USE,
6516 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6517 NULL, "(optional | prohibited | required)",
6518 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006519 } else
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006521 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 * 3.2.3 : 2
6523 * If default and use are both present, use must have
6524 * the actual value optional.
6525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6527 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006529 xmlSchemaPSimpleTypeErr(ctxt,
6530 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6531 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6532 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 /*
6538 * And now for the children...
6539 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006540 child = node->children;
6541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006542 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6543 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 * 3.2.3 : 3.2
6550 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 */
6553 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6554 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6555 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6558 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006559 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 }
6561 } else {
6562 if (IS_SCHEMA(child, "simpleType")) {
6563 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006565 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 */
6568 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6569 &repName, (xmlSchemaTypePtr) ret, node, child,
6570 "The attribute 'type' and the <simpleType> child "
6571 "are mutually exclusive", NULL);
6572 } else
6573 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6574 child = child->next;
6575 }
6576 if (child != NULL)
6577 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6578 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6579 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006580 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006581 /*
6582 * Cleanup.
6583 */
6584 if (repName != NULL)
6585 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006586 return (ret);
6587}
6588
6589/**
6590 * xmlSchemaParseAttributeGroup:
6591 * @ctxt: a schema validation context
6592 * @schema: the schema being built
6593 * @node: a subtree containing XML Schema informations
6594 *
6595 * parse a XML schema Attribute Group declaration
6596 * *WARNING* this interface is highly subject to change
6597 *
6598 * Returns the attribute group or NULL in case of error.
6599 */
6600static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006602 xmlSchemaPtr schema, xmlNodePtr node,
6603 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006604{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006608 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006609 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006610
6611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6612 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006613
6614 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006616 if ((topLevel) || (attr == NULL)) {
6617 /*
6618 * Parse as an attribute group definition.
6619 * Note that those are allowed at top level only.
6620 */
6621 if (nameAttr == NULL) {
6622 xmlSchemaPMissingAttrErr(ctxt,
6623 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006624 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006625 return (NULL);
6626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006627 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006628 * (xmlNodePtr) nameAttr);
6629 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006630 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006631 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006632 */
6633 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6636 return (NULL);
6637 }
6638 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6639 if (ret == NULL)
6640 return (NULL);
6641 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6642 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6643 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006644 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006645 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006646 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006647 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648
6649 /*
6650 * Parse as an attribute group definition reference.
6651 */
6652 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006653 xmlSchemaPMissingAttrErr(ctxt,
6654 XML_SCHEMAP_S4S_ATTR_MISSING,
6655 NULL, node, "ref", NULL);
6656 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006657 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006658 NULL, NULL, attr, &refNs,&ref);
6659
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006660 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 name = (const xmlChar *) buf;
6662 if (name == NULL) {
6663 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6664 "attribute group definition reference", node);
6665 return (NULL);
6666 }
6667 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6668 if (ret == NULL)
6669 return (NULL);
6670 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6671 ret->ref = ref;
6672 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006673 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006674 xmlSchemaCheckReference(ctxt, schema, node,
6675 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006677 /*
6678 * Check for illegal attributes.
6679 */
6680 attr = node->properties;
6681 while (attr != NULL) {
6682 if (attr->ns == NULL) {
6683 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6684 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006686 {
6687 xmlSchemaPIllegalAttrErr(ctxt,
6688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6689 NULL, NULL, attr);
6690 }
6691 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6692 xmlSchemaPIllegalAttrErr(ctxt,
6693 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6694 NULL, NULL, attr);
6695 }
6696 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697 }
6698 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006699 /*
6700 * And now for the children...
6701 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006703 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006706 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006710 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 if (IS_SCHEMA(child, "anyAttribute")) {
6712 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6713 child = child->next;
6714 }
6715 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006716 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006717 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6719 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006720 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006721 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006722 ctxt->container = oldcontainer;
6723 return (ret);
6724}
6725
6726/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006727 * xmlSchemaPValAttrFormDefault:
6728 * @value: the value
6729 * @flags: the flags to be modified
6730 * @flagQualified: the specific flag for "qualified"
6731 *
6732 * Returns 0 if the value is valid, 1 otherwise.
6733 */
6734static int
6735xmlSchemaPValAttrFormDefault(const xmlChar *value,
6736 int *flags,
6737 int flagQualified)
6738{
6739 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6740 if ((*flags & flagQualified) == 0)
6741 *flags |= flagQualified;
6742 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 return (1);
6744
William M. Brack2f2a6632004-08-20 23:09:47 +00006745 return (0);
6746}
6747
6748/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 * xmlSchemaPValAttrBlockFinal:
6750 * @value: the value
6751 * @flags: the flags to be modified
6752 * @flagAll: the specific flag for "#all"
6753 * @flagExtension: the specific flag for "extension"
6754 * @flagRestriction: the specific flag for "restriction"
6755 * @flagSubstitution: the specific flag for "substitution"
6756 * @flagList: the specific flag for "list"
6757 * @flagUnion: the specific flag for "union"
6758 *
6759 * Validates the value of the attribute "final" and "block". The value
6760 * is converted into the specified flag values and returned in @flags.
6761 *
6762 * Returns 0 if the value is valid, 1 otherwise.
6763 */
6764
6765static int
6766xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006767 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006768 int flagAll,
6769 int flagExtension,
6770 int flagRestriction,
6771 int flagSubstitution,
6772 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006773 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774{
6775 int ret = 0;
6776
6777 /*
6778 * TODO: This does not check for dublicate entries.
6779 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006780 if ((flags == NULL) || (value == NULL))
6781 return (-1);
6782 if (value[0] == 0)
6783 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 if (xmlStrEqual(value, BAD_CAST "#all")) {
6785 if (flagAll != -1)
6786 *flags |= flagAll;
6787 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (flagExtension != -1)
6789 *flags |= flagExtension;
6790 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006792 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006793 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006796 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006797 *flags |= flagUnion;
6798 }
6799 } else {
6800 const xmlChar *end, *cur = value;
6801 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 do {
6804 while (IS_BLANK_CH(*cur))
6805 cur++;
6806 end = cur;
6807 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6808 end++;
6809 if (end == cur)
6810 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006811 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 if (xmlStrEqual(item, BAD_CAST "extension")) {
6813 if (flagExtension != -1) {
6814 if ((*flags & flagExtension) == 0)
6815 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 ret = 1;
6818 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6819 if (flagRestriction != -1) {
6820 if ((*flags & flagRestriction) == 0)
6821 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006822 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 ret = 1;
6824 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6825 if (flagSubstitution != -1) {
6826 if ((*flags & flagSubstitution) == 0)
6827 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006828 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 ret = 1;
6830 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6831 if (flagList != -1) {
6832 if ((*flags & flagList) == 0)
6833 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6837 if (flagUnion != -1) {
6838 if ((*flags & flagUnion) == 0)
6839 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006840 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006842 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006843 ret = 1;
6844 if (item != NULL)
6845 xmlFree(item);
6846 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006847 } while ((ret == 0) && (*cur != 0));
6848 }
6849
Daniel Veillardc0826a72004-08-10 14:17:33 +00006850 return (ret);
6851}
6852
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006853static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006855 xmlSchemaIDCPtr idc,
6856 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006857 xmlAttrPtr attr,
6858 int isField)
6859{
6860 xmlNodePtr node;
6861
6862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006864 * Schema Component Constraint: Selector Value OK
6865 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 * in [XPath].
6868 */
6869 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006870 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006871 XML_SCHEMAP_INTERNAL,
6872 "Internal error: xmlSchemaCheckCSelectorXPath, "
6873 "the selector is not specified.\n", NULL, NULL);
6874 return (-1);
6875 }
6876 if (attr == NULL)
6877 node = idc->node;
6878 else
6879 node = (xmlNodePtr) attr;
6880 if (selector->xpath == NULL) {
6881 xmlSchemaPCustomErr(ctxt,
6882 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006883 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6884 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006885 "The XPath expression of the selector is not valid", NULL);
6886 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6887 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006888 const xmlChar **nsArray = NULL;
6889 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006890 /*
6891 * Compile the XPath expression.
6892 */
6893 /*
6894 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006895 * TODO: Call xmlPatterncompile with different options for selector/
6896 * field.
6897 */
6898 nsList = xmlGetNsList(attr->doc, attr->parent);
6899 /*
6900 * Build an array of prefixes and namespaces.
6901 */
6902 if (nsList != NULL) {
6903 int i, count = 0;
6904 xmlNsPtr ns;
6905
6906 for (i = 0; nsList[i] != NULL; i++)
6907 count++;
6908
6909 nsArray = (const xmlChar **) xmlMalloc(
6910 (count * 2 + 1) * sizeof(const xmlChar *));
6911 if (nsArray == NULL) {
6912 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6913 NULL);
6914 return (-1);
6915 }
6916 for (i = 0; i < count; i++) {
6917 ns = nsList[i];
6918 nsArray[2 * i] = nsList[i]->href;
6919 nsArray[2 * i + 1] = nsList[i]->prefix;
6920 }
6921 nsArray[count * 2] = NULL;
6922 xmlFree(nsList);
6923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006924 /*
6925 * TODO: Differentiate between "selector" and "field".
6926 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006927 if (isField)
6928 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006929 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006930 else
6931 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006932 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006933 if (nsArray != NULL)
6934 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006935
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006936 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006937 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006938 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006939 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6940 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006941 "The XPath expression '%s' could not be "
6942 "compiled", selector->xpath);
6943 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006944 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006945 }
6946 return (0);
6947}
6948
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006949#define ADD_ANNOTATION(annot) \
6950 xmlSchemaAnnotPtr cur = item->annot; \
6951 if (item->annot == NULL) { \
6952 item->annot = annot; \
6953 return (annot); \
6954 } \
6955 cur = item->annot; \
6956 if (cur->next != NULL) { \
6957 cur = cur->next; \
6958 } \
6959 cur->next = annot;
6960
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006961/**
6962 * xmlSchemaAssignAnnotation:
6963 * @item: the schema component
6964 * @annot: the annotation
6965 *
6966 * Adds the annotation to the given schema component.
6967 *
6968 * Returns the given annotaion.
6969 */
6970static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006971xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6972 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006973{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006974 if ((annItem == NULL) || (annot == NULL))
6975 return (NULL);
6976 switch (annItem->type) {
6977 case XML_SCHEMA_TYPE_ELEMENT: {
6978 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6979 ADD_ANNOTATION(annot)
6980 }
6981 break;
6982 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6983 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6984 ADD_ANNOTATION(annot)
6985 }
6986 break;
6987 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6988 case XML_SCHEMA_TYPE_ANY: {
6989 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6990 ADD_ANNOTATION(annot)
6991 }
6992 break;
6993 case XML_SCHEMA_TYPE_PARTICLE:
6994 case XML_SCHEMA_TYPE_IDC_KEY:
6995 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006996 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006997 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6998 ADD_ANNOTATION(annot)
6999 }
7000 break;
7001 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7002 xmlSchemaAttributeGroupPtr item =
7003 (xmlSchemaAttributeGroupPtr) annItem;
7004 ADD_ANNOTATION(annot)
7005 }
7006 break;
7007 case XML_SCHEMA_TYPE_NOTATION: {
7008 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7009 ADD_ANNOTATION(annot)
7010 }
7011 break;
7012 case XML_SCHEMA_FACET_MININCLUSIVE:
7013 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7014 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7015 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7016 case XML_SCHEMA_FACET_TOTALDIGITS:
7017 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7018 case XML_SCHEMA_FACET_PATTERN:
7019 case XML_SCHEMA_FACET_ENUMERATION:
7020 case XML_SCHEMA_FACET_WHITESPACE:
7021 case XML_SCHEMA_FACET_LENGTH:
7022 case XML_SCHEMA_FACET_MAXLENGTH:
7023 case XML_SCHEMA_FACET_MINLENGTH: {
7024 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007027 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007028 case XML_SCHEMA_TYPE_SIMPLE:
7029 case XML_SCHEMA_TYPE_COMPLEX: {
7030 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7031 ADD_ANNOTATION(annot)
7032 }
7033 break;
7034 case XML_SCHEMA_TYPE_GROUP: {
7035 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7036 ADD_ANNOTATION(annot)
7037 }
7038 break;
7039 case XML_SCHEMA_TYPE_SEQUENCE:
7040 case XML_SCHEMA_TYPE_CHOICE:
7041 case XML_SCHEMA_TYPE_ALL: {
7042 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7043 ADD_ANNOTATION(annot)
7044 }
7045 break;
7046 default:
7047 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007048 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007049 NULL, NULL, NULL,
7050 "Internal error: xmlSchemaAddAnnotation, "
7051 "The item is not a annotated schema component", NULL);
7052 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007053 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007054 return (annot);
7055}
7056
7057/**
7058 * xmlSchemaParseIDCSelectorAndField:
7059 * @ctxt: a schema validation context
7060 * @schema: the schema being built
7061 * @node: a subtree containing XML Schema informations
7062 *
7063 * Parses a XML Schema identity-contraint definition's
7064 * <selector> and <field> elements.
7065 *
7066 * Returns the parsed identity-constraint definition.
7067 */
7068static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007070 xmlSchemaPtr schema,
7071 xmlSchemaIDCPtr idc,
7072 xmlNodePtr node,
7073 int isField)
7074{
7075 xmlSchemaIDCSelectPtr item;
7076 xmlNodePtr child = NULL;
7077 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007078
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007079 /*
7080 * Check for illegal attributes.
7081 */
7082 attr = node->properties;
7083 while (attr != NULL) {
7084 if (attr->ns == NULL) {
7085 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7086 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007087 xmlSchemaPIllegalAttrErr(ctxt,
7088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7089 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 }
7091 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 xmlSchemaPIllegalAttrErr(ctxt,
7093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7094 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095 }
7096 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007098 /*
7099 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007101 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7102 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007103 xmlSchemaPErrMemory(ctxt,
7104 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 NULL);
7106 return (NULL);
7107 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007108 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 /*
7110 * Attribute "xpath" (mandatory).
7111 */
7112 attr = xmlSchemaGetPropNode(node, "xpath");
7113 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007114 xmlSchemaPMissingAttrErr(ctxt,
7115 XML_SCHEMAP_S4S_ATTR_MISSING,
7116 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007117 "name", NULL);
7118 } else {
7119 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7120 /*
7121 * URGENT TODO: "field"s have an other syntax than "selector"s.
7122 */
7123
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007124 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7125 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 xmlSchemaPErr(ctxt,
7127 (xmlNodePtr) attr,
7128 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007129 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007130 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007131 NULL, NULL);
7132 }
7133
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007134 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007135 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 /*
7137 * And now for the children...
7138 */
7139 child = node->children;
7140 if (IS_SCHEMA(child, "annotation")) {
7141 /*
7142 * Add the annotation to the parent IDC.
7143 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007145 xmlSchemaParseAnnotation(ctxt, schema, child));
7146 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007147 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007148 if (child != NULL) {
7149 xmlSchemaPContentErr(ctxt,
7150 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007151 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007152 NULL, "(annotation?)");
7153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007155 return (item);
7156}
7157
7158/**
7159 * xmlSchemaParseIDC:
7160 * @ctxt: a schema validation context
7161 * @schema: the schema being built
7162 * @node: a subtree containing XML Schema informations
7163 *
7164 * Parses a XML Schema identity-contraint definition.
7165 *
7166 * Returns the parsed identity-constraint definition.
7167 */
7168static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007169xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007170 xmlSchemaPtr schema,
7171 xmlNodePtr node,
7172 xmlSchemaTypeType idcCategory,
7173 const xmlChar *targetNamespace)
7174{
7175 xmlSchemaIDCPtr item = NULL;
7176 xmlNodePtr child = NULL;
7177 xmlAttrPtr attr;
7178 const xmlChar *name = NULL;
7179 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7180 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007182 /*
7183 * Check for illegal attributes.
7184 */
7185 attr = node->properties;
7186 while (attr != NULL) {
7187 if (attr->ns == NULL) {
7188 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7189 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7190 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7191 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007192 xmlSchemaPIllegalAttrErr(ctxt,
7193 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7194 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 }
7196 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007197 xmlSchemaPIllegalAttrErr(ctxt,
7198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7199 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007200 }
7201 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 /*
7204 * Attribute "name" (mandatory).
7205 */
7206 attr = xmlSchemaGetPropNode(node, "name");
7207 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007208 xmlSchemaPMissingAttrErr(ctxt,
7209 XML_SCHEMAP_S4S_ATTR_MISSING,
7210 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 "name", NULL);
7212 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007213 } else if (xmlSchemaPValAttrNode(ctxt,
7214 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7216 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007217 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007218 /*
7219 * Create the component.
7220 */
7221 if (schema->idcDef == NULL)
7222 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 return (NULL);
7225
7226 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7227 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 "allocating an identity-constraint definition", NULL);
7230 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 /*
7233 * Add the IDC to the list of IDCs on the schema component.
7234 */
7235 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007236 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007237 xmlSchemaPCustomErrExt(ctxt,
7238 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007239 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007240 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007242 name, targetNamespace, NULL);
7243 xmlFree(item);
7244 return (NULL);
7245 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007246 memset(item, 0, sizeof(xmlSchemaIDC));
7247 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007249 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007250 if (ctxt->assemble != NULL)
7251 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 /*
7253 * The target namespace of the parent element declaration.
7254 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007255 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007256 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7257 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007258 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7259 /*
7260 * Attribute "refer" (mandatory).
7261 */
7262 attr = xmlSchemaGetPropNode(node, "refer");
7263 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 xmlSchemaPMissingAttrErr(ctxt,
7265 XML_SCHEMAP_S4S_ATTR_MISSING,
7266 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007267 "refer", NULL);
7268 } else {
7269 /*
7270 * Create a reference item.
7271 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007272 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007273 NULL, NULL);
7274 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007275 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007276 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007277 NULL, NULL, attr,
7278 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007279 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007280 xmlSchemaCheckReference(ctxt, schema, node,
7281 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007282 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007283 }
7284 }
7285 /*
7286 * And now for the children...
7287 */
7288 child = node->children;
7289 if (IS_SCHEMA(child, "annotation")) {
7290 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7291 child = child->next;
7292 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007293 if (child == NULL) {
7294 xmlSchemaPContentErr(ctxt,
7295 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007296 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007297 "A child element is missing",
7298 "(annotation?, (selector, field+))");
7299 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007300 /*
7301 * Child element <selector>.
7302 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007303 if (IS_SCHEMA(child, "selector")) {
7304 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item, child, 0);
7306 child = child->next;
7307 /*
7308 * Child elements <field>.
7309 */
7310 if (IS_SCHEMA(child, "field")) {
7311 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007312 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007313 item, child, 1);
7314 if (field != NULL) {
7315 field->index = item->nbFields;
7316 item->nbFields++;
7317 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007319 else
7320 item->fields = field;
7321 lastField = field;
7322 }
7323 child = child->next;
7324 } while (IS_SCHEMA(child, "field"));
7325 } else {
7326 xmlSchemaPContentErr(ctxt,
7327 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007328 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007329 NULL, "(annotation?, (selector, field+))");
7330 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007331 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 if (child != NULL) {
7333 xmlSchemaPContentErr(ctxt,
7334 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007335 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007336 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007338
7339 return (item);
7340}
7341
Daniel Veillardc0826a72004-08-10 14:17:33 +00007342/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 * xmlSchemaParseElement:
7344 * @ctxt: a schema validation context
7345 * @schema: the schema being built
7346 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007347 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007348 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007349 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007350 * *WARNING* this interface is highly subject to change
7351 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007352 * Returns the element declaration or a particle; NULL in case
7353 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007355static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007356xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007357 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007360 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007362 xmlNodePtr child = NULL;
7363 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 int min, max, isRef = 0;
7365 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007366
7367 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7368 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007369
Daniel Veillard4255d502002-04-16 15:50:10 +00007370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007371 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007372 /*
7373 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007375 * robust.
7376 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007377 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007378 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007379 if ((topLevel) || (attr == NULL)) {
7380 if (nameAttr == NULL) {
7381 xmlSchemaPMissingAttrErr(ctxt,
7382 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007383 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007384 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007386 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007387 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007388
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007389 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007390 child = node->children;
7391 if (IS_SCHEMA(child, "annotation")) {
7392 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7393 child = child->next;
7394 }
7395 /*
7396 * Skip particle part if a global declaration.
7397 */
7398 if (topLevel)
7399 goto declaration_part;
7400 /*
7401 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007402 */
7403 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7404 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7405 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7407 if (particle == NULL)
7408 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007410 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7411
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007413 const xmlChar *refNs = NULL, *ref = NULL;
7414 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007417 */
7418 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421 /*
7422 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007423 */
7424 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007425 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007426 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007427 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007429 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007432 attr = node->properties;
7433 while (attr != NULL) {
7434 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007435 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7436 xmlStrEqual(attr->name, BAD_CAST "name") ||
7437 xmlStrEqual(attr->name, BAD_CAST "id") ||
7438 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7439 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7440 {
7441 attr = attr->next;
7442 continue;
7443 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007444 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007445 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 "Only the attributes 'minOccurs', 'maxOccurs' and "
7449 "'id' are allowed in addition to 'ref'");
7450 break;
7451 }
7452 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7453 xmlSchemaPIllegalAttrErr(ctxt,
7454 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007455 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 }
7457 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007458 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007459 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007460 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007461 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007462 if (child != NULL) {
7463 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, NULL, node, child, NULL, "(annotation?)");
7465 }
7466 if ((min == 0) && (max == 0))
7467 goto return_null;
7468 /*
7469 * Create the reference item.
7470 */
7471 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7472 ref, refNs);
7473 if (refer == NULL)
7474 goto return_null;
7475 particle->children = (xmlSchemaTreeItemPtr) refer;
7476 particle->annot = annot;
7477 /*
7478 * Add to assembled items; the reference need to be resolved.
7479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007480 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007481 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7482
7483 return ((xmlSchemaBasicItemPtr) particle);
7484 }
7485 /*
7486 * The declaration part ===============================================
7487 */
7488declaration_part:
7489 {
7490 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7491 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7492
7493 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007494 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007495 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007496 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007497 * Evaluate the target namespace.
7498 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007499 if (topLevel) {
7500 ns = schema->targetNamespace;
7501 } else {
7502 attr = xmlSchemaGetPropNode(node, "form");
7503 if (attr != NULL) {
7504 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7505 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007506 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007507 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007508 xmlSchemaPSimpleTypeErr(ctxt,
7509 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7510 NULL, (xmlNodePtr) attr,
7511 NULL, "(qualified | unqualified)",
7512 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007513 }
7514 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007515 ns = schema->targetNamespace;
7516 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007517 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007519 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007520 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007521 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7522 decl->node = node;
7523 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 * Check for illegal attributes.
7526 */
William M. Bracke7091952004-05-11 15:09:58 +00007527 attr = node->properties;
7528 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007529 if (attr->ns == NULL) {
7530 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7531 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007532 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7537 {
7538 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007539 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007541 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007542 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007543 xmlSchemaPIllegalAttrErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7545 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7548 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007549 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7550
7551 xmlSchemaPIllegalAttrErr(ctxt,
7552 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 }
7555 }
7556 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 xmlSchemaPIllegalAttrErr(ctxt,
7559 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007560 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007561 }
7562 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
William M. Bracke7091952004-05-11 15:09:58 +00007564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007565 * Extract/validate attributes.
7566 */
7567 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 * Process top attributes of global element declarations here.
7570 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007571 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7572 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7574 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7575 &(decl->substGroupNs), &(decl->substGroup));
7576 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 /*
7580 * Attribute "final".
7581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007582 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007584 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7585 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7586 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7587 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007589 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7590 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 -1,
7592 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7593 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007596 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7597 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 attrValue, NULL, NULL, NULL);
7599 }
7600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007601 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 /*
7603 * Attribute "block".
7604 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007605 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007607 /*
7608 * Apply default "block" values.
7609 */
7610 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7611 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7612 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7613 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7614 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7615 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7618 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 -1,
7620 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007621 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007622 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7623 xmlSchemaPSimpleTypeErr(ctxt,
7624 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007626 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 "restriction | substitution))", attrValue,
7628 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 }
7630 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007633 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007634
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 attr = xmlSchemaGetPropNode(node, "type");
7636 if (attr != NULL) {
7637 xmlSchemaPValAttrNodeQName(ctxt, schema,
7638 NULL, (xmlSchemaTypePtr) decl, attr,
7639 &(decl->namedTypeNs), &(decl->namedType));
7640 xmlSchemaCheckReference(ctxt, schema, node,
7641 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7642 }
7643 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7644 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 if (attr != NULL) {
7646 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007647 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007648 /*
7649 * 3.3.3 : 1
7650 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 */
7652 xmlSchemaPMutualExclAttrErr(ctxt,
7653 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007654 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 "default", "fixed");
7656 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007657 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7658 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 }
William M. Bracke7091952004-05-11 15:09:58 +00007660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007661 /*
7662 * And now for the children...
7663 */
7664 oldcontainer = ctxt->container;
7665 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007666 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 /*
7668 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007669 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007670 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007672 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 xmlSchemaPContentErr(ctxt,
7674 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007675 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007678 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007679 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007680 child = child->next;
7681 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 /*
7683 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007684 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007687 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 xmlSchemaPContentErr(ctxt,
7689 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007690 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007691 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007693 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007694 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007695 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007696 }
William M. Bracke7091952004-05-11 15:09:58 +00007697 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007699 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007700 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007701 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007702 } else if (IS_SCHEMA(child, "key")) {
7703 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007705 } else if (IS_SCHEMA(child, "keyref")) {
7706 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007707 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007708 }
7709 if (lastIDC != NULL)
7710 lastIDC->next = curIDC;
7711 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007712 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007713 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007714 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007715 }
7716 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 xmlSchemaPContentErr(ctxt,
7718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007719 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 NULL, "(annotation?, ((simpleType | complexType)?, "
7721 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007723 ctxt->container = oldcontainer;
7724 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007727 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007728 * different layer.
7729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007730 FREE_AND_NULL(des)
7731 if (topLevel)
7732 return ((xmlSchemaBasicItemPtr) decl);
7733 else {
7734 particle->children = (xmlSchemaTreeItemPtr) decl;
7735 return ((xmlSchemaBasicItemPtr) particle);
7736 }
7737
7738return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007739 FREE_AND_NULL(des);
7740 if (annot != NULL) {
7741 if (particle != NULL)
7742 particle->annot = NULL;
7743 if (decl != NULL)
7744 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007747 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007748}
7749
7750/**
7751 * xmlSchemaParseUnion:
7752 * @ctxt: a schema validation context
7753 * @schema: the schema being built
7754 * @node: a subtree containing XML Schema informations
7755 *
7756 * parse a XML schema Union definition
7757 * *WARNING* this interface is highly subject to change
7758 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 * Returns -1 in case of internal error, 0 in case of success and a positive
7760 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007761 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007762static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007763xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007764 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007767 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007768 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007769 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007770
7771 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007772 return (-1);
7773 /* Not a component, don't create it. */
7774 type = ctxt->ctxtType;
7775 /*
7776 * Mark the simple type as being of variety "union".
7777 */
7778 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007779 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007780 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7781 * then the ·simple ur-type definition·."
7782 */
7783 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007784 /*
7785 * Check for illegal attributes.
7786 */
7787 attr = node->properties;
7788 while (attr != NULL) {
7789 if (attr->ns == NULL) {
7790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7791 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007792 xmlSchemaPIllegalAttrErr(ctxt,
7793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007795 }
7796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007797 xmlSchemaPIllegalAttrErr(ctxt,
7798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007800 }
7801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007803 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007804 /*
7805 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007806 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007808 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007809 if (attr != NULL) {
7810 const xmlChar *end;
7811 xmlChar *tmp;
7812 const xmlChar *localName, *nsName;
7813 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7814 xmlSchemaQNameRefPtr ref;
7815
7816 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007817 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818 do {
7819 while (IS_BLANK_CH(*cur))
7820 cur++;
7821 end = cur;
7822 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7823 end++;
7824 if (end == cur)
7825 break;
7826 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007827 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7828 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007829 /*
7830 * Create the member type link.
7831 */
7832 link = (xmlSchemaTypeLinkPtr)
7833 xmlMalloc(sizeof(xmlSchemaTypeLink));
7834 if (link == NULL) {
7835 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7836 "allocating a type link", NULL);
7837 return (-1);
7838 }
7839 link->type = NULL;
7840 link->next = NULL;
7841 if (lastLink == NULL)
7842 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007843 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007844 lastLink->next = link;
7845 lastLink = link;
7846 /*
7847 * Create a reference item.
7848 */
7849 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7850 localName, nsName);
7851 if (ref == NULL) {
7852 FREE_AND_NULL(tmp)
7853 return (-1);
7854 }
7855 /*
7856 * Assign the reference to the link, it will be resolved
7857 * later during fixup of the union simple type.
7858 */
7859 link->type = (xmlSchemaTypePtr) ref;
7860 }
7861 FREE_AND_NULL(tmp)
7862 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007865 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007866 /*
7867 * And now for the children...
7868 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 child = node->children;
7870 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007871 /*
7872 * Add the annotation to the simple type ancestor.
7873 */
7874 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7875 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007876 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007877 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007878 if (IS_SCHEMA(child, "simpleType")) {
7879 xmlSchemaTypePtr subtype, last = NULL;
7880
7881 /*
7882 * Anchor the member types in the "subtypes" field of the
7883 * simple type.
7884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007885 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007886 subtype = (xmlSchemaTypePtr)
7887 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7888 if (subtype != NULL) {
7889 if (last == NULL) {
7890 type->subtypes = subtype;
7891 last = subtype;
7892 } else {
7893 last->next = subtype;
7894 last = subtype;
7895 }
7896 last->next = NULL;
7897 }
7898 child = child->next;
7899 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007900 }
7901 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007902 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007903 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007904 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007906 if ((attr == NULL) && (type->subtypes == NULL)) {
7907 /*
7908 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007909 * Either the memberTypes [attribute] of the <union> element must
7910 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007913 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7914 NULL, NULL, node,
7915 "Either the attribute 'memberTypes' or "
7916 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007918 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007919}
7920
7921/**
7922 * xmlSchemaParseList:
7923 * @ctxt: a schema validation context
7924 * @schema: the schema being built
7925 * @node: a subtree containing XML Schema informations
7926 *
7927 * parse a XML schema List definition
7928 * *WARNING* this interface is highly subject to change
7929 *
William M. Bracke7091952004-05-11 15:09:58 +00007930 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 * 1 in case of success.
7932 */
7933static xmlSchemaTypePtr
7934xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007935 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007936{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007937 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007938 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007939 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007940
7941 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7942 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007943 /* Not a component, don't create it. */
7944 type = ctxt->ctxtType;
7945 /*
7946 * Mark the type as being of variety "list".
7947 */
7948 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007949 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007950 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7951 * then the ·simple ur-type definition·."
7952 */
7953 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007954 /*
7955 * Check for illegal attributes.
7956 */
7957 attr = node->properties;
7958 while (attr != NULL) {
7959 if (attr->ns == NULL) {
7960 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7961 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 xmlSchemaPIllegalAttrErr(ctxt,
7963 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7964 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 }
7966 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007967 xmlSchemaPIllegalAttrErr(ctxt,
7968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7969 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007970 }
7971 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007973
7974 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7975
William M. Brack2f2a6632004-08-20 23:09:47 +00007976 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007977 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7978 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007979 */
7980 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 /*
7983 * And now for the children...
7984 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007985 child = node->children;
7986 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7988 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007989 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007992 /*
7993 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007994 * Either the itemType [attribute] or the <simpleType> [child] of
7995 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 */
7997 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007998 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007999 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008003 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008007 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 "Either the attribute 'itemType' or the <simpleType> child "
8012 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008013 }
8014 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 if ((type->ref == NULL) &&
8020 (type->subtypes == NULL) &&
8021 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008023 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008024 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008025 "Either the attribute 'itemType' or the <simpleType> child "
8026 "must be present", NULL);
8027 }
8028 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008029}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030
Daniel Veillard4255d502002-04-16 15:50:10 +00008031/**
8032 * xmlSchemaParseSimpleType:
8033 * @ctxt: a schema validation context
8034 * @schema: the schema being built
8035 * @node: a subtree containing XML Schema informations
8036 *
8037 * parse a XML schema Simple Type definition
8038 * *WARNING* this interface is highly subject to change
8039 *
William M. Bracke7091952004-05-11 15:09:58 +00008040 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008042 */
8043static xmlSchemaTypePtr
8044xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008045 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008046{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008047 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008048 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008050 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008051
8052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8053 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008054
Daniel Veillardc0826a72004-08-10 14:17:33 +00008055 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008056 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008058 xmlSchemaPMissingAttrErr(ctxt,
8059 XML_SCHEMAP_S4S_ATTR_MISSING,
8060 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 "name", NULL);
8062 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008063 } else {
8064 if (xmlSchemaPValAttrNode(ctxt,
8065 NULL, NULL, attr,
8066 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8067 return (NULL);
8068 /*
8069 * Skip built-in types.
8070 */
8071 if (ctxt->isS4S) {
8072 xmlSchemaTypePtr biType;
8073
8074 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8075 if (biType != NULL)
8076 return (biType);
8077 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008078 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008082 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083
Daniel Veillard01fa6152004-06-29 17:04:39 +00008084 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008085 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008086 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008087 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008088 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008089 if (type == NULL)
8090 return (NULL);
8091 type->node = node;
8092 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 /*
8095 * Check for illegal attributes.
8096 */
8097 attr = node->properties;
8098 while (attr != NULL) {
8099 if (attr->ns == NULL) {
8100 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008101 xmlSchemaPIllegalAttrErr(ctxt,
8102 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8103 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 xmlSchemaPIllegalAttrErr(ctxt,
8107 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8108 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008109 }
8110 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008111 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008112 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 /*
8114 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008115 *
8116 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008117 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008118 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008119 if (type == NULL)
8120 return (NULL);
8121 type->node = node;
8122 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8125 /*
8126 * Check for illegal attributes.
8127 */
8128 attr = node->properties;
8129 while (attr != NULL) {
8130 if (attr->ns == NULL) {
8131 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8132 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008133 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134 xmlSchemaPIllegalAttrErr(ctxt,
8135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8136 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 }
8138 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008139 xmlSchemaPIllegalAttrErr(ctxt,
8140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8141 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008142 }
8143 attr = attr->next;
8144 }
8145 /*
8146 * Attribute "final".
8147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008148 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008149 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8151 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8152 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8153 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8154 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8155 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 } else {
8157 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8159 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008160 XML_SCHEMAS_TYPE_FINAL_LIST,
8161 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8162
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008163 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008165 type, (xmlNodePtr) attr,
8166 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008167 attrValue, NULL, NULL, NULL);
8168 }
8169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008171 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008172 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008173 /*
8174 * And now for the children...
8175 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008176 oldCtxtType = ctxt->ctxtType;
8177 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 ctxt->ctxtType = type;
8179 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008180 child = node->children;
8181 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8183 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008185 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8187 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008188 "(annotation?, (restriction | list | union))");
8189 } else if (IS_SCHEMA(child, "restriction")) {
8190 xmlSchemaParseRestriction(ctxt, schema, child,
8191 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008192 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008194 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008195 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008197 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008199 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008200 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008201 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8202 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008203 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008205 ctxt->parentItem = oldParentItem;
8206 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008207
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 return (type);
8209}
8210
Daniel Veillard4255d502002-04-16 15:50:10 +00008211/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008212 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008213 * @ctxt: a schema validation context
8214 * @schema: the schema being built
8215 * @node: a subtree containing XML Schema informations
8216 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 * *WARNING* this interface is highly subject to change
8219 *
William M. Bracke7091952004-05-11 15:09:58 +00008220 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 * 1 in case of success.
8222 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223static xmlSchemaTreeItemPtr
8224xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8225 xmlSchemaPtr schema,
8226 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008227{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008230 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008231 const xmlChar *ref = NULL, *refNs = NULL;
8232 int min, max;
8233
8234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008235 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008236
8237 attr = xmlSchemaGetPropNode(node, "ref");
8238 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlSchemaPMissingAttrErr(ctxt,
8240 XML_SCHEMAP_S4S_ATTR_MISSING,
8241 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008242 "ref", NULL);
8243 return (NULL);
8244 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 }
8248 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008249 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 /*
8252 * Check for illegal attributes.
8253 */
8254 attr = node->properties;
8255 while (attr != NULL) {
8256 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8259 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8260 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261 xmlSchemaPIllegalAttrErr(ctxt,
8262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8263 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008264 }
8265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 xmlSchemaPIllegalAttrErr(ctxt,
8267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8268 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008269 }
8270 attr = attr->next;
8271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008272 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8274 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008275 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008276 /*
8277 * Create a reference item as the term; it will be substituted for
8278 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008279 */
8280 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008281 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8282 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8283 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8284 /*
8285 * And now for the children...
8286 */
8287 child = node->children;
8288 /* TODO: Is annotation even allowed for a model group reference? */
8289 if (IS_SCHEMA(child, "annotation")) {
8290 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292 */
8293 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8294 child = child->next;
8295 }
8296 if (child != NULL) {
8297 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008299 NULL, NULL, node, child, NULL,
8300 "(annotation?)");
8301 }
8302 /*
8303 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8304 */
8305 if ((min == 0) && (max == 0))
8306 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008307 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008308 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8309 return ((xmlSchemaTreeItemPtr) item);
8310}
8311
8312/**
8313 * xmlSchemaParseModelGroupDefinition:
8314 * @ctxt: a schema validation context
8315 * @schema: the schema being built
8316 * @node: a subtree containing XML Schema informations
8317 *
8318 * Parses a XML schema model group definition.
8319 * *WARNING* this interface is highly subject to change
8320 *
8321 * Returns -1 in case of error, 0 if the declaration is improper and
8322 * 1 in case of success.
8323 */
8324static xmlSchemaModelGroupDefPtr
8325xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8326 xmlSchemaPtr schema,
8327 xmlNodePtr node)
8328{
8329 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008330 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008331 xmlAttrPtr attr;
8332 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008333
8334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 return (NULL);
8336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008337 attr = xmlSchemaGetPropNode(node, "name");
8338 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008339 xmlSchemaPMissingAttrErr(ctxt,
8340 XML_SCHEMAP_S4S_ATTR_MISSING,
8341 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008342 "name", NULL);
8343 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008344 } else if (xmlSchemaPValAttrNode(ctxt,
8345 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008346 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8347 return (NULL);
8348 }
8349 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8350 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 /*
8353 * Check for illegal attributes.
8354 */
8355 attr = node->properties;
8356 while (attr != NULL) {
8357 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008358 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008359 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008360 xmlSchemaPIllegalAttrErr(ctxt,
8361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8362 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008363 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008365 xmlSchemaPIllegalAttrErr(ctxt,
8366 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8367 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008368 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369 attr = attr->next;
8370 }
8371 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8372 /*
8373 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008374 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008375 child = node->children;
8376 if (IS_SCHEMA(child, "annotation")) {
8377 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8378 child = child->next;
8379 }
8380 if (IS_SCHEMA(child, "all")) {
8381 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8382 XML_SCHEMA_TYPE_ALL, 0);
8383 child = child->next;
8384 } else if (IS_SCHEMA(child, "choice")) {
8385 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8386 XML_SCHEMA_TYPE_CHOICE, 0);
8387 child = child->next;
8388 } else if (IS_SCHEMA(child, "sequence")) {
8389 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8390 XML_SCHEMA_TYPE_SEQUENCE, 0);
8391 child = child->next;
8392 }
8393 if (child != NULL) {
8394 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8396 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008399
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008400 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008401}
8402
8403/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008404 * xmlSchemaCleanupDoc:
8405 * @ctxt: a schema validation context
8406 * @node: the root of the document.
8407 *
8408 * removes unwanted nodes in a schemas document tree
8409 */
8410static void
8411xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8412{
8413 xmlNodePtr delete, cur;
8414
8415 if ((ctxt == NULL) || (root == NULL)) return;
8416
8417 /*
8418 * Remove all the blank text nodes
8419 */
8420 delete = NULL;
8421 cur = root;
8422 while (cur != NULL) {
8423 if (delete != NULL) {
8424 xmlUnlinkNode(delete);
8425 xmlFreeNode(delete);
8426 delete = NULL;
8427 }
8428 if (cur->type == XML_TEXT_NODE) {
8429 if (IS_BLANK_NODE(cur)) {
8430 if (xmlNodeGetSpacePreserve(cur) != 1) {
8431 delete = cur;
8432 }
8433 }
8434 } else if ((cur->type != XML_ELEMENT_NODE) &&
8435 (cur->type != XML_CDATA_SECTION_NODE)) {
8436 delete = cur;
8437 goto skip_children;
8438 }
8439
8440 /*
8441 * Skip to next node
8442 */
8443 if (cur->children != NULL) {
8444 if ((cur->children->type != XML_ENTITY_DECL) &&
8445 (cur->children->type != XML_ENTITY_REF_NODE) &&
8446 (cur->children->type != XML_ENTITY_NODE)) {
8447 cur = cur->children;
8448 continue;
8449 }
8450 }
8451 skip_children:
8452 if (cur->next != NULL) {
8453 cur = cur->next;
8454 continue;
8455 }
8456
8457 do {
8458 cur = cur->parent;
8459 if (cur == NULL)
8460 break;
8461 if (cur == root) {
8462 cur = NULL;
8463 break;
8464 }
8465 if (cur->next != NULL) {
8466 cur = cur->next;
8467 break;
8468 }
8469 } while (cur != NULL);
8470 }
8471 if (delete != NULL) {
8472 xmlUnlinkNode(delete);
8473 xmlFreeNode(delete);
8474 delete = NULL;
8475 }
8476}
8477
William M. Brack2f2a6632004-08-20 23:09:47 +00008478
8479/**
8480 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008482 * @ctxt: a schema validation context
8483 * @schemaLocation: an URI defining where to find the imported schema
8484 *
8485 * import a XML schema
8486 * *WARNING* this interface is highly subject to change
8487 *
8488 * Returns -1 in case of error and 1 in case of success.
8489 */
8490#if 0
8491static xmlSchemaImportPtr
8492xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8493 const xmlChar *schemaLocation)
8494{
8495 xmlSchemaImportPtr import;
8496 xmlSchemaParserCtxtPtr newctxt;
8497
8498 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8499 if (newctxt == NULL) {
8500 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8501 NULL);
8502 return (NULL);
8503 }
8504 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8505 /* Keep the same dictionnary for parsing, really */
8506 xmlDictReference(ctxt->dict);
8507 newctxt->dict = ctxt->dict;
8508 newctxt->includes = 0;
8509 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8510
8511 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8512 ctxt->userData);
8513
8514 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8515 if (import == NULL) {
8516 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8517 NULL);
8518 xmlSchemaFreeParserCtxt(newctxt);
8519 return (NULL);
8520 }
8521
8522 memset(import, 0, sizeof(xmlSchemaImport));
8523 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8524 import->schema = xmlSchemaParse(newctxt);
8525
8526 if (import->schema == NULL) {
8527 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008528 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008529 "Failed to import schema from location \"%s\".\n",
8530 schemaLocation, NULL);
8531
8532 xmlSchemaFreeParserCtxt(newctxt);
8533 /* The schemaLocation is held by the dictionary.
8534 if (import->schemaLocation != NULL)
8535 xmlFree((xmlChar *)import->schemaLocation);
8536 */
8537 xmlFree(import);
8538 return NULL;
8539 }
8540
8541 xmlSchemaFreeParserCtxt(newctxt);
8542 return import;
8543}
8544#endif
8545
8546static void
8547xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8548{
8549 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8550 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8551
8552 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8553 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8554
8555 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8556 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8557 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8558 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8559 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8560 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8561 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8562 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8563
8564 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8565 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8566 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8567 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8568 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8569 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8570}
8571
8572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008573xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008574 xmlSchemaPtr schema,
8575 xmlNodePtr node)
8576{
8577 xmlAttrPtr attr;
8578 const xmlChar *val;
8579
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008580 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8581 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008583 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8584 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008586 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008589 if (attr != NULL) {
8590 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008592 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008594 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 "(qualified | unqualified)", val, NULL, NULL, NULL);
8597 }
8598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599
8600 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008601 if (attr != NULL) {
8602 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008608 "(qualified | unqualified)", val, NULL, NULL, NULL);
8609 }
8610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611
8612 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 if (attr != NULL) {
8614 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8615 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8616 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8617 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8618 -1,
8619 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8620 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8621 xmlSchemaPSimpleTypeErr(ctxt,
8622 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008624 "(#all | List of (extension | restriction | list | union))",
8625 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008627 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628
8629 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 if (attr != NULL) {
8631 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8632 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8633 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8634 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8635 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8636 xmlSchemaPSimpleTypeErr(ctxt,
8637 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008639 "(#all | List of (extension | restriction | substitution))",
8640 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008642 }
8643}
8644
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008645/**
8646 * xmlSchemaParseSchemaTopLevel:
8647 * @ctxt: a schema validation context
8648 * @schema: the schemas
8649 * @nodes: the list of top level nodes
8650 *
8651 * Returns the internal XML Schema structure built from the resource or
8652 * NULL in case of error
8653 */
8654static void
8655xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8656 xmlSchemaPtr schema, xmlNodePtr nodes)
8657{
8658 xmlNodePtr child;
8659 xmlSchemaAnnotPtr annot;
8660
8661 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8662 return;
8663
8664 child = nodes;
8665 while ((IS_SCHEMA(child, "include")) ||
8666 (IS_SCHEMA(child, "import")) ||
8667 (IS_SCHEMA(child, "redefine")) ||
8668 (IS_SCHEMA(child, "annotation"))) {
8669 if (IS_SCHEMA(child, "annotation")) {
8670 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8671 if (schema->annot == NULL)
8672 schema->annot = annot;
8673 else
8674 xmlSchemaFreeAnnot(annot);
8675 } else if (IS_SCHEMA(child, "import")) {
8676 xmlSchemaParseImport(ctxt, schema, child);
8677 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008678 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008680 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008681 } else if (IS_SCHEMA(child, "redefine")) {
8682 TODO
8683 }
8684 child = child->next;
8685 }
8686 while (child != NULL) {
8687 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008688 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008689 child = child->next;
8690 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008691 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008692 child = child->next;
8693 } else if (IS_SCHEMA(child, "element")) {
8694 xmlSchemaParseElement(ctxt, schema, child, 1);
8695 child = child->next;
8696 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008697 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008698 child = child->next;
8699 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008700 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701 child = child->next;
8702 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008703 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008704 child = child->next;
8705 } else if (IS_SCHEMA(child, "notation")) {
8706 xmlSchemaParseNotation(ctxt, schema, child);
8707 child = child->next;
8708 } else {
8709 xmlSchemaPErr2(ctxt, NULL, child,
8710 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008711 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008712 child->name, NULL);
8713 child = child->next;
8714 }
8715 while (IS_SCHEMA(child, "annotation")) {
8716 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8717 if (schema->annot == NULL)
8718 schema->annot = annot;
8719 else
8720 xmlSchemaFreeAnnot(annot);
8721 child = child->next;
8722 }
8723 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008724 ctxt->parentItem = NULL;
8725 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008726}
8727
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008728static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730 xmlHashTablePtr *imports,
8731 const xmlChar *nsName)
8732{
8733 xmlSchemaImportPtr ret;
8734
8735 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008736 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008737 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008739 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8740 NULL, NULL, (xmlNodePtr) ctxt->doc,
8741 "Internal error: failed to build the import table",
8742 NULL);
8743 return (NULL);
8744 }
8745 }
8746 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8747 if (ret == NULL) {
8748 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8749 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008751 memset(ret, 0, sizeof(xmlSchemaImport));
8752 if (nsName == NULL)
8753 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008754 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008755
8756 return (ret);
8757}
8758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759/**
8760 * xmlSchemaNewParserCtxtUseDict:
8761 * @URL: the location of the schema
8762 * @dict: the dictionary to be used
8763 *
8764 * Create an XML Schemas parse context for that file/resource expected
8765 * to contain an XML Schemas file.
8766 *
8767 * Returns the parser context or NULL in case of error
8768 */
8769static xmlSchemaParserCtxtPtr
8770xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8771{
8772 xmlSchemaParserCtxtPtr ret;
8773 /*
8774 if (URL == NULL)
8775 return (NULL);
8776 */
8777
8778 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8779 if (ret == NULL) {
8780 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8781 NULL);
8782 return (NULL);
8783 }
8784 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8785 ret->dict = dict;
8786 xmlDictReference(dict);
8787 if (URL != NULL)
8788 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8789 ret->includes = 0;
8790 return (ret);
8791}
8792
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008793static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8795{
8796 if (vctxt->pctxt == NULL) {
8797 if (vctxt->schema != NULL)
8798 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8799 else
8800 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8801 if (vctxt->pctxt == NULL) {
8802 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8803 "failed to create a temp. parser context");
8804 return (-1);
8805 }
8806 /* TODO: Pass user data. */
8807 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8808 }
8809 return (0);
8810}
8811
8812static int
8813xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008814 xmlSchemaPtr schema,
8815 xmlNodePtr node,
8816 const xmlChar *nsName,
8817 const xmlChar *location,
8818 xmlDocPtr *doc,
8819 const xmlChar **targetNamespace,
8820 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008821{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008822 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008823 xmlParserCtxtPtr parserCtxt;
8824 xmlSchemaImportPtr import;
8825 const xmlChar *ns;
8826 xmlNodePtr root;
8827
8828 /*
8829 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8830 * <xsi:noNamespaceSchemaLocation>.
8831 */
8832 *doc = NULL;
8833 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 * Given that the schemaLocation [attribute] is only a hint, it is open
8835 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008836 * namespace, regardless of the ·actual value· of schemaLocation, but
8837 * such a strategy risks missing useful information when new
8838 * schemaLocations are offered.
8839 *
8840 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8841 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8842 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008844 */
8845 if (location == NULL) {
8846 /*
8847 * Schema Document Location Strategy:
8848 *
8849 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850 * either as a resource which is an XML document or a <schema> element
8851 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008852 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 *
8855 * NOTE: Those stategies are not supported, so we will skip.
8856 */
8857 return (0);
8858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008859 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008860 ns = XML_SCHEMAS_NO_NAMESPACE;
8861 else
8862 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008865 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008866 /*
8867 * There was a valid resource for the specified namespace already
8868 * defined, so skip.
8869 * TODO: This might be changed someday to allow import of
8870 * components from multiple documents for a single target namespace.
8871 */
8872 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 }
8874 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8875 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8876 else {
8877 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8878 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008881 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008882 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 * 2 Based on the location URI, identify an existing schema document,
8884 * either as a resource which is an XML document or a <schema> element
8885 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008888 * web which is or contains or references a <schema> element;
8889 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8890 *
8891 */
8892 if ((absolute == 0) && (node != NULL)) {
8893 xmlChar *base, *URI;
8894
8895 base = xmlNodeGetBase(node->doc, node);
8896 if (base == NULL) {
8897 URI = xmlBuildURI(location, node->doc->URL);
8898 } else {
8899 URI = xmlBuildURI(location, base);
8900 xmlFree(base);
8901 }
8902 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008903 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904 xmlFree(URI);
8905 }
8906 }
8907 parserCtxt = xmlNewParserCtxt();
8908 if (parserCtxt == NULL) {
8909 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8910 "allocating a parser context", NULL);
8911 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008912 }
8913 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008914 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008916 xmlDictReference(parserCtxt->dict);
8917 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008918 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008919 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 * 2.1 The referent is (a fragment of) a resource which is an
8922 * XML document (see clause 1.1), which in turn corresponds to
8923 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008924 * set, which in turn corresponds to a valid schema.
8925 * TODO: What to do with the "fragment" stuff?
8926 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008927 * 2.2 The referent is a <schema> element information item in
8928 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 */
8933 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008934 xmlErrorPtr lerr;
8935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008936 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008937 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008939 * If the doc is NULL and the parser error is an IO error we
8940 * will assume that the resource could not be located or accessed.
8941 *
8942 * TODO: Try to find specific error codes to react only on
8943 * localisation failures.
8944 *
8945 * TODO, FIXME: Check the spec: is a namespace added to the imported
8946 * namespaces, even if the schemaLocation did not provide
8947 * a resource? I guess so, since omitting the "schemaLocation"
8948 * attribute, imports a namespace as well.
8949 */
8950 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 xmlFreeParserCtxt(parserCtxt);
8953 return(0);
8954 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008956 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFreeParserCtxt(parserCtxt);
8961 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8962 }
8963 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008964
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008965 root = xmlDocGetRootElement(*doc);
8966 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 xmlFreeDoc(*doc);
8973 *doc = NULL;
8974 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 }
8976
8977 xmlSchemaCleanupDoc(pctxt, root);
8978
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008979 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008981 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 xmlFreeDoc(*doc);
8986 *doc = NULL;
8987 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008988 }
8989 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 /*
8991 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 if (nsName == NULL) {
8994 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008996 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008997 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 "The XML schema to be imported is not expected "
8999 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 xmlFreeDoc(*doc);
9002 *doc = NULL;
9003 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9004 }
9005 } else {
9006 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009009 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009010 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 xmlFreeDoc(*doc);
9013 *doc = NULL;
9014 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9015 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009017 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 "The XML schema to be imported is expected to have a "
9020 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 "its target namespace of '%s'",
9022 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009023 xmlFreeDoc(*doc);
9024 *doc = NULL;
9025 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9026 }
9027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009028 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009029 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009030 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9031 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009032 xmlFreeDoc(*doc);
9033 *doc = NULL;
9034 return (-1);
9035 }
9036 import->schemaLocation = location;
9037 import->doc = *doc;
9038 return (0);
9039}
William M. Brack2f2a6632004-08-20 23:09:47 +00009040
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009041static void
9042xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9043 xmlSchemaPtr schema,
9044 const xmlChar *targetNamespace,
9045 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009046{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009047 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009048 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009049
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009050 /*
9051 * Save and reset the context & schema.
9052 */
9053 oldURL = pctxt->URL;
9054 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009055 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009056 oldLocImps = pctxt->localImports;
9057 pctxt->localImports = NULL;
9058 oldNumLocImps = pctxt->nbLocalImports;
9059 pctxt->nbLocalImports = 0;
9060 oldSizeLocImps = pctxt->sizeLocalImports;
9061 pctxt->sizeLocalImports = 0;
9062 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009063 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 xmlSchemaClearSchemaDefaults(schema);
9065 oldTNS = schema->targetNamespace;
9066 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009067 if ((targetNamespace != NULL) &&
9068 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9069 /*
9070 * We are parsing the schema for schema!
9071 */
9072 pctxt->isS4S = 1;
9073 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009074 /*
9075 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009077 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9078 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9079 /*
9080 * Restore the context & schema.
9081 */
9082 schema->flags = oldFlags;
9083 schema->targetNamespace = oldTNS;
9084 if (pctxt->localImports != NULL)
9085 xmlFree((xmlChar *) pctxt->localImports);
9086 pctxt->localImports = oldLocImps;
9087 pctxt->nbLocalImports = oldNumLocImps;
9088 pctxt->sizeLocalImports = oldSizeLocImps;
9089 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009090 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009091}
9092
William M. Brack2f2a6632004-08-20 23:09:47 +00009093/**
9094 * xmlSchemaParseImport:
9095 * @ctxt: a schema validation context
9096 * @schema: the schema being built
9097 * @node: a subtree containing XML Schema informations
9098 *
9099 * parse a XML schema Import definition
9100 * *WARNING* this interface is highly subject to change
9101 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102 * Returns 0 in case of success, a positive error code if
9103 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009104 */
9105static int
9106xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9107 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009108{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009109 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009110 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009111 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009113 xmlAttrPtr attr;
9114 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009115 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009116
9117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9118 return (-1);
9119
9120 /*
9121 * Check for illegal attributes.
9122 */
9123 attr = node->properties;
9124 while (attr != NULL) {
9125 if (attr->ns == NULL) {
9126 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9127 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9128 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 xmlSchemaPIllegalAttrErr(ctxt,
9130 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9131 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009132 }
9133 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009134 xmlSchemaPIllegalAttrErr(ctxt,
9135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9136 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009137 }
9138 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009139 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 /*
9141 * Extract and validate attributes.
9142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9144 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009145 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 xmlSchemaPSimpleTypeErr(ctxt,
9147 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9148 NULL, node,
9149 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009150 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9152 }
9153
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9155 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009156 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 xmlSchemaPSimpleTypeErr(ctxt,
9158 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9159 NULL, node,
9160 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009161 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009162 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009164 /*
9165 * And now for the children...
9166 */
9167 child = node->children;
9168 if (IS_SCHEMA(child, "annotation")) {
9169 /*
9170 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009171 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009172 */
9173 child = child->next;
9174 }
9175 if (child != NULL) {
9176 xmlSchemaPContentErr(ctxt,
9177 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9178 NULL, NULL, node, child, NULL,
9179 "(annotation?)");
9180 }
9181 /*
9182 * Apply additional constraints.
9183 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009184 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009185 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009186 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9187 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 * targetNamespace [attribute].
9189 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009190 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009191 xmlSchemaPCustomErr(ctxt,
9192 XML_SCHEMAP_SRC_IMPORT_1_1,
9193 NULL, NULL, node,
9194 "The value of the attribute 'namespace' must not match "
9195 "the target namespace '%s' of the importing schema",
9196 schema->targetNamespace);
9197 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9198 }
9199 } else {
9200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009201 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009202 * <schema> must have a targetNamespace [attribute].
9203 */
9204 if (schema->targetNamespace == NULL) {
9205 xmlSchemaPCustomErr(ctxt,
9206 XML_SCHEMAP_SRC_IMPORT_1_2,
9207 NULL, NULL, node,
9208 "The attribute 'namespace' must be existent if "
9209 "the importing schema has no target namespace",
9210 NULL);
9211 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9212 }
9213 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009214 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009215 * Add the namespace to the list of locally imported namespace.
9216 */
9217 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009218 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009219 sizeof(const xmlChar*));
9220 ctxt->sizeLocalImports = 10;
9221 ctxt->nbLocalImports = 0;
9222 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9223 ctxt->sizeLocalImports *= 2;
9224 ctxt->localImports = (const xmlChar **) xmlRealloc(
9225 (xmlChar **) ctxt->localImports,
9226 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9227 }
9228 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9229 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009230 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9233 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009234 schemaLocation, &doc, &targetNamespace, 0);
9235 if (ret != 0) {
9236 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009237 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009238 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009239 } else if (doc != NULL) {
9240 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9241 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009244 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009245}
9246
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009247/**
9248 * xmlSchemaParseInclude:
9249 * @ctxt: a schema validation context
9250 * @schema: the schema being built
9251 * @node: a subtree containing XML Schema informations
9252 *
9253 * parse a XML schema Include definition
9254 *
William M. Bracke7091952004-05-11 15:09:58 +00009255 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009256 * 1 in case of success.
9257 */
9258static int
9259xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9260 xmlNodePtr node)
9261{
9262 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009263 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009264 xmlDocPtr doc = NULL;
9265 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009266 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009267 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009269 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009270
9271
9272 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9273 return (-1);
9274
9275 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009276 * Check for illegal attributes.
9277 */
9278 attr = node->properties;
9279 while (attr != NULL) {
9280 if (attr->ns == NULL) {
9281 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9282 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009283 xmlSchemaPIllegalAttrErr(ctxt,
9284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9285 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009286 }
9287 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288 xmlSchemaPIllegalAttrErr(ctxt,
9289 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9290 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009291 }
9292 attr = attr->next;
9293 }
9294 /*
9295 * Extract and validate attributes.
9296 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009297 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 * Preliminary step, extract the URI-Reference for the include and
9300 * make an URI from the base.
9301 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009302 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9303 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009304 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009305 xmlChar *uri = NULL;
9306
9307 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9308 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009310 base = xmlNodeGetBase(node->doc, node);
9311 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009312 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009313 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009314 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 xmlFree(base);
9316 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009317 if (uri == NULL) {
9318 xmlSchemaPErr(ctxt,
9319 node,
9320 XML_SCHEMAP_INTERNAL,
9321 "Internal error: xmlSchemaParseInclude, "
9322 "could not build an URI from the schemaLocation.\n",
9323 NULL, NULL);
9324 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009325 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009326 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9327 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009328 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 xmlSchemaPMissingAttrErr(ctxt,
9330 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9331 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009332 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009334 /*
9335 * And now for the children...
9336 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009337 child = node->children;
9338 while (IS_SCHEMA(child, "annotation")) {
9339 /*
9340 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009341 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009342 */
9343 child = child->next;
9344 }
9345 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9348 NULL, NULL, node, child, NULL,
9349 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009350 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009351 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009352 * Report self-inclusion.
9353 */
9354 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9355 xmlSchemaPCustomErr(ctxt,
9356 XML_SCHEMAP_SRC_INCLUDE,
9357 NULL, NULL, node,
9358 "The schema document '%s' cannot include itself.",
9359 schemaLocation);
9360 return (XML_SCHEMAP_SRC_INCLUDE);
9361 }
9362 /*
9363 * Check if this one was already processed to avoid incorrect
9364 * duplicate component errors and infinite circular inclusion.
9365 */
9366 include = schema->includes;
9367 while (include != NULL) {
9368 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9369 targetNamespace = include->origTargetNamespace;
9370 if (targetNamespace == NULL) {
9371 /*
9372 * Chameleon include: skip only if it was build for
9373 * the targetNamespace of the including schema.
9374 */
9375 if (xmlStrEqual(schema->targetNamespace,
9376 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009377 goto check_targetNamespace;
9378 }
9379 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 goto check_targetNamespace;
9381 }
9382 }
9383 include = include->next;
9384 }
9385 /*
9386 * First step is to parse the input document into an DOM/Infoset
9387 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009388 */
9389 parserCtxt = xmlNewParserCtxt();
9390 if (parserCtxt == NULL) {
9391 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9392 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009393 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 }
9395
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009396 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9397 xmlDictFree(parserCtxt->dict);
9398 parserCtxt->dict = ctxt->dict;
9399 xmlDictReference(parserCtxt->dict);
9400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009401
9402 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009403 NULL, SCHEMAS_PARSE_OPTIONS);
9404 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009405 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009407 * TODO: It is not an error for the ·actual value· of the
9408 * schemaLocation [attribute] to fail to resolve it all, in which
9409 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009410 * So do we need a warning report here?
9411 */
9412 xmlSchemaPCustomErr(ctxt,
9413 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009414 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009415 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009416 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009417 }
9418
9419 /*
9420 * Then extract the root of the schema
9421 */
9422 root = xmlDocGetRootElement(doc);
9423 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009424 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009425 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009426 NULL, NULL, node,
9427 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009429 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009430 }
9431
9432 /*
9433 * Remove all the blank text nodes
9434 */
9435 xmlSchemaCleanupDoc(ctxt, root);
9436
9437 /*
9438 * Check the schemas top level element
9439 */
9440 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009441 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009443 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009445 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009446 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448
William M. Brack2f2a6632004-08-20 23:09:47 +00009449 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009451 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9452 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009453 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9454 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009455check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009456 if (targetNamespace != NULL) {
9457 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009458 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009459 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009460 NULL, NULL, node,
9461 "The target namespace of the included schema "
9462 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 "has no target namespace",
9464 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009465 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009466 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9467 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009469 NULL, NULL, node,
9470 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009471 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009472 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009475 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009476 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009477 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009478 } else
9479 wasConvertingNs = 1;
9480 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009481
9482 if (include != NULL)
9483 goto exit;
9484
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009485 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009486 * URGENT TODO: If the schema is a chameleon-include then copy the
9487 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009488 * of those components, do nothing otherwise.
9489 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009490 * for every destinct including targetNamespace; thus not performant at
9491 * the moment.
9492 * TODO: Check when the namespace in wildcards for chameleons needs
9493 * to be converted: before we built wildcard intersections or after.
9494 */
9495 /*
9496 * Register the include.
9497 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009498 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9499 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9501 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009502 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009503 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009504 include->next = schema->includes;
9505 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009506 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009507 * TODO: Use the resolved URI for the this location, since it might
9508 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009510 include->schemaLocation = schemaLocation;
9511 include->doc = doc;
9512 /*
9513 * In case of chameleons, the original target namespace will differ
9514 * from the resulting namespace.
9515 */
9516 include->origTargetNamespace = targetNamespace;
9517 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009518#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009519 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009520 xmlGenericError(xmlGenericErrorContext,
9521 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9522 " into TNS '%s'\n", schemaLocation,
9523 targetNamespace, schema->targetNamespace);
9524 else
9525 xmlGenericError(xmlGenericErrorContext,
9526 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9527 targetNamespace);
9528#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529 /*
9530 * Compile the included schema.
9531 */
9532 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9533
9534exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009535 /*
9536 * Remove the converting flag.
9537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009538 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009539 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009540 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009541 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009542
9543exit_invalid:
9544 if (doc != NULL) {
9545 if (include != NULL)
9546 include->doc = NULL;
9547 xmlFreeDoc(doc);
9548 }
9549 return (ctxt->err);
9550
9551exit_failure:
9552 if (doc != NULL) {
9553 if (include != NULL)
9554 include->doc = NULL;
9555 xmlFreeDoc(doc);
9556 }
9557 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009558}
9559
9560/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009561 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009562 * @ctxt: a schema validation context
9563 * @schema: the schema being built
9564 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009565 * @type: the "compositor" type
9566 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009567 *
9568 * parse a XML schema Sequence definition
9569 * *WARNING* this interface is highly subject to change
9570 *
William M. Bracke7091952004-05-11 15:09:58 +00009571 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009572 * 1 in case of success.
9573 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009574static xmlSchemaTreeItemPtr
9575xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9576 xmlNodePtr node, xmlSchemaTypeType type,
9577 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009578{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009579 xmlSchemaModelGroupPtr item;
9580 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009581 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009582 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009583 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009584 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009585
9586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009587 return (NULL);
9588 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009590 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9592 if (item == NULL)
9593 return (NULL);
9594
9595 if (withParticle) {
9596 if (type == XML_SCHEMA_TYPE_ALL) {
9597 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 } else {
9600 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009601 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9602 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9603 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009605 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9606 /*
9607 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009608 */
9609 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9610 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009611 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009612 particle->children = (xmlSchemaTreeItemPtr) item;
9613 /*
9614 * Check for illegal attributes.
9615 */
9616 attr = node->properties;
9617 while (attr != NULL) {
9618 if (attr->ns == NULL) {
9619 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9620 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9621 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009622 xmlSchemaPIllegalAttrErr(ctxt,
9623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9624 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009625 }
9626 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 xmlSchemaPIllegalAttrErr(ctxt,
9628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9629 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009630 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009631 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009633 } else {
9634 /*
9635 * Check for illegal attributes.
9636 */
9637 attr = node->properties;
9638 while (attr != NULL) {
9639 if (attr->ns == NULL) {
9640 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009641 xmlSchemaPIllegalAttrErr(ctxt,
9642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9643 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009644 }
9645 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 xmlSchemaPIllegalAttrErr(ctxt,
9647 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9648 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 }
9650 attr = attr->next;
9651 }
9652
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009654
William M. Brack2f2a6632004-08-20 23:09:47 +00009655 /*
9656 * Extract and validate attributes.
9657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 /*
9660 * And now for the children...
9661 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009662 child = node->children;
9663 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009664 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009665 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009666 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009667 oldcontainer = ctxt->container;
9668 ctxt->container = container;
9669 if (type == XML_SCHEMA_TYPE_ALL) {
9670 xmlSchemaParticlePtr part, last = NULL;
9671
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009673 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9674 schema, child, 0);
9675 if (part != NULL) {
9676 if (part->minOccurs > 1)
9677 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009679 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9680 if (part->maxOccurs > 1)
9681 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009683 "Invalid value for maxOccurs (must be 0 or 1)",
9684 NULL);
9685 if (last == NULL)
9686 item->children = (xmlSchemaTreeItemPtr) part;
9687 else
9688 last->next = (xmlSchemaTreeItemPtr) part;
9689 last = part;
9690 }
9691 child = child->next;
9692 }
9693 if (child != NULL) {
9694 xmlSchemaPContentErr(ctxt,
9695 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9696 NULL, NULL, node, child, NULL,
9697 "(annotation?, (annotation?, element*)");
9698 }
9699 } else {
9700 /* choice + sequence */
9701 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9702
9703 while ((IS_SCHEMA(child, "element")) ||
9704 (IS_SCHEMA(child, "group")) ||
9705 (IS_SCHEMA(child, "any")) ||
9706 (IS_SCHEMA(child, "choice")) ||
9707 (IS_SCHEMA(child, "sequence"))) {
9708
9709 if (IS_SCHEMA(child, "element")) {
9710 part = (xmlSchemaTreeItemPtr)
9711 xmlSchemaParseElement(ctxt, schema, child, 0);
9712 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009713 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9715 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009716 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009717 xmlSchemaParseAny(ctxt, schema, child);
9718 } else if (IS_SCHEMA(child, "choice")) {
9719 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9720 XML_SCHEMA_TYPE_CHOICE, 1);
9721 } else if (IS_SCHEMA(child, "sequence")) {
9722 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9723 XML_SCHEMA_TYPE_SEQUENCE, 1);
9724 }
9725 if (part != NULL) {
9726 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009727 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009728 else
9729 last->next = part;
9730 last = part;
9731 }
9732 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009733 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009734 if (child != NULL) {
9735 xmlSchemaPContentErr(ctxt,
9736 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9737 NULL, NULL, node, child, NULL,
9738 "(annotation?, (element | group | choice | sequence | any)*)");
9739 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009740 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009741 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009742 if (withParticle) {
9743 if ((min == 0) && (max == 0))
9744 return (NULL);
9745 else
9746 return ((xmlSchemaTreeItemPtr) particle);
9747 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009748 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009749}
9750
9751/**
9752 * xmlSchemaParseRestriction:
9753 * @ctxt: a schema validation context
9754 * @schema: the schema being built
9755 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009756 *
9757 * parse a XML schema Restriction definition
9758 * *WARNING* this interface is highly subject to change
9759 *
9760 * Returns the type definition or NULL in case of error
9761 */
9762static xmlSchemaTypePtr
9763xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009764 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009767 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009768 char buf[30];
9769 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009771
9772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9773 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009774 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009775 type = ctxt->ctxtType;
9776 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009777
9778 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009779 * TODO: Is the container needed at all? the anonymous
9780 * items inside should generate unique names already.
9781 */
9782 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009783 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009784 /*
9785 * Check for illegal attributes.
9786 */
9787 attr = node->properties;
9788 while (attr != NULL) {
9789 if (attr->ns == NULL) {
9790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9791 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009792 xmlSchemaPIllegalAttrErr(ctxt,
9793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009795 }
9796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009797 xmlSchemaPIllegalAttrErr(ctxt,
9798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009800 }
9801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009802 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009803 /*
9804 * Extract and validate attributes.
9805 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009806 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009807 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009808 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009810 /*
9811 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9812 * among its [children]), the simple type definition which is
9813 * the {content type} of the type definition ·resolved· to by
9814 * the ·actual value· of the base [attribute]"
9815 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009816 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009817 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009818 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009819 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009821 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009822 XML_SCHEMAP_S4S_ATTR_MISSING,
9823 type, node, "base", NULL);
9824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 /*
9826 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009827 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009828 child = node->children;
9829 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009830 /*
9831 * Add the annotation to the simple type ancestor.
9832 */
9833 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9834 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009835 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009836 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009837 oldcontainer = ctxt->container;
9838 ctxt->container = container;
9839 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9840 /*
9841 * Corresponds to <simpleType><restriction><simpleType>.
9842 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009843 if (IS_SCHEMA(child, "simpleType")) {
9844 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009845 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009846 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009847 * Either the base [attribute] or the simpleType [child] of the
9848 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009853 "The attribute 'base' and the <simpleType> child are "
9854 "mutually exclusive", NULL);
9855 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009856 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009857 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009860 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009861 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009862 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9863 NULL, NULL, node, child,
9864 "Either the attribute 'base' or a <simpleType> child "
9865 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009866 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009867 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9868 /*
9869 * Corresponds to <complexType><complexContent><restriction>...
9870 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009871 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 * Model groups <all>, <choice> and <sequence>.
9873 */
9874 if (IS_SCHEMA(child, "all")) {
9875 type->subtypes = (xmlSchemaTypePtr)
9876 xmlSchemaParseModelGroup(ctxt, schema, child,
9877 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009878 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 } else if (IS_SCHEMA(child, "choice")) {
9880 type->subtypes = (xmlSchemaTypePtr)
9881 xmlSchemaParseModelGroup(ctxt,
9882 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9883 child = child->next;
9884 } else if (IS_SCHEMA(child, "sequence")) {
9885 type->subtypes = (xmlSchemaTypePtr)
9886 xmlSchemaParseModelGroup(ctxt, schema, child,
9887 XML_SCHEMA_TYPE_SEQUENCE, 1);
9888 child = child->next;
9889 /*
9890 * Model group reference <group>.
9891 */
9892 } else if (IS_SCHEMA(child, "group")) {
9893 type->subtypes = (xmlSchemaTypePtr)
9894 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9895 child = child->next;
9896 }
9897 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009898 /*
9899 * Corresponds to <complexType><simpleContent><restriction>...
9900 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 * "1.1 the simple type definition corresponding to the <simpleType>
9902 * among the [children] of <restriction> if there is one;"
9903 */
9904 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009905 /*
9906 * We will store the to-be-restricted simple type in
9907 * type->contentTypeDef *temporarily*.
9908 */
9909 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009911 if ( type->contentTypeDef == NULL)
9912 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 child = child->next;
9914 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916
9917 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009918 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009919 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009920 /*
9921 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009922 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924
Daniel Veillard01fa6152004-06-29 17:04:39 +00009925 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009926 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009927 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009928 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9930 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009931 * *Single Facet Value*
9932 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009933 while ((IS_SCHEMA(child, "minInclusive")) ||
9934 (IS_SCHEMA(child, "minExclusive")) ||
9935 (IS_SCHEMA(child, "maxInclusive")) ||
9936 (IS_SCHEMA(child, "maxExclusive")) ||
9937 (IS_SCHEMA(child, "totalDigits")) ||
9938 (IS_SCHEMA(child, "fractionDigits")) ||
9939 (IS_SCHEMA(child, "pattern")) ||
9940 (IS_SCHEMA(child, "enumeration")) ||
9941 (IS_SCHEMA(child, "whiteSpace")) ||
9942 (IS_SCHEMA(child, "length")) ||
9943 (IS_SCHEMA(child, "maxLength")) ||
9944 (IS_SCHEMA(child, "minLength"))) {
9945 facet = xmlSchemaParseFacet(ctxt, schema, child);
9946 if (facet != NULL) {
9947 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009948 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009949 else
9950 lastfacet->next = facet;
9951 lastfacet = facet;
9952 lastfacet->next = NULL;
9953 }
9954 child = child->next;
9955 }
9956 /*
9957 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 */
9959 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 facet = type->facets;
9963 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009964 facetLink = (xmlSchemaFacetLinkPtr)
9965 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009966 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009967 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009968 xmlFree(facetLink);
9969 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009971 facetLink->facet = facet;
9972 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 if (lastFacetLink == NULL)
9974 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009975 else
9976 lastFacetLink->next = facetLink;
9977 lastFacetLink = facetLink;
9978 facet = facet->next;
9979 } while (facet != NULL);
9980 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009982 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9983 /*
9984 * Attribute uses/declarations.
9985 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009986 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009987 /*
9988 * Attribute wildcard.
9989 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009990 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009991 type->attributeWildcard =
9992 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009993 child = child->next;
9994 }
9995 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009996 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009997 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9998 xmlSchemaPContentErr(ctxt,
9999 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010000 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010001 "annotation?, (group | all | choice | sequence)?, "
10002 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 xmlSchemaPContentErr(ctxt,
10005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010007 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10008 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10009 "length | minLength | maxLength | enumeration | whiteSpace | "
10010 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10011 } else {
10012 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010013 xmlSchemaPContentErr(ctxt,
10014 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010015 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010016 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10017 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10018 "length | minLength | maxLength | enumeration | whiteSpace | "
10019 "pattern)*))");
10020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010021 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010022 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010023 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010024}
10025
10026/**
10027 * xmlSchemaParseExtension:
10028 * @ctxt: a schema validation context
10029 * @schema: the schema being built
10030 * @node: a subtree containing XML Schema informations
10031 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 * Parses an <extension>, which is found inside a
10033 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010034 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010035 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010036 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010037 */
10038static xmlSchemaTypePtr
10039xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010040 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010041{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010042 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010043 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 char buf[30];
10045 const xmlChar *oldcontainer, *container;
10046 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010047
10048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10049 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010050 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010051 type = ctxt->ctxtType;
10052 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010053
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10055 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10056 /*
10057 * Check for illegal attributes.
10058 */
10059 attr = node->properties;
10060 while (attr != NULL) {
10061 if (attr->ns == NULL) {
10062 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10063 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 xmlSchemaPIllegalAttrErr(ctxt,
10065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10066 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010067 }
10068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 xmlSchemaPIllegalAttrErr(ctxt,
10070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010072 }
10073 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010075
10076 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010078 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010080 */
10081 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010082 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10083 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010084 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010085 XML_SCHEMAP_S4S_ATTR_MISSING,
10086 NULL, node, "base", NULL);
10087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010088 /*
10089 * And now for the children...
10090 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 child = node->children;
10092 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010093 /*
10094 * Add the annotation to the type ancestor.
10095 */
10096 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10097 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010098 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010099 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 oldcontainer = ctxt->container;
10101 ctxt->container = container;
10102 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10103 /*
10104 * Corresponds to <complexType><complexContent><extension>... and:
10105 *
10106 * Model groups <all>, <choice>, <sequence> and <group>.
10107 */
10108 if (IS_SCHEMA(child, "all")) {
10109 type->subtypes = (xmlSchemaTypePtr)
10110 xmlSchemaParseModelGroup(ctxt, schema,
10111 child, XML_SCHEMA_TYPE_ALL, 1);
10112 child = child->next;
10113 } else if (IS_SCHEMA(child, "choice")) {
10114 type->subtypes = (xmlSchemaTypePtr)
10115 xmlSchemaParseModelGroup(ctxt, schema,
10116 child, XML_SCHEMA_TYPE_CHOICE, 1);
10117 child = child->next;
10118 } else if (IS_SCHEMA(child, "sequence")) {
10119 type->subtypes = (xmlSchemaTypePtr)
10120 xmlSchemaParseModelGroup(ctxt, schema,
10121 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10122 child = child->next;
10123 } else if (IS_SCHEMA(child, "group")) {
10124 type->subtypes = (xmlSchemaTypePtr)
10125 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10126 child = child->next;
10127 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010128 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010129 if (child != NULL) {
10130 /*
10131 * Attribute uses/declarations.
10132 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010133 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 /*
10135 * Attribute wildcard.
10136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010137 if (IS_SCHEMA(child, "anyAttribute")) {
10138 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010139 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10140 child = child->next;
10141 }
10142 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010143 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10145 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010146 xmlSchemaPContentErr(ctxt,
10147 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010148 NULL, NULL, node, child, NULL,
10149 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010150 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010151 } else {
10152 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010153 xmlSchemaPContentErr(ctxt,
10154 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010155 NULL, NULL, node, child, NULL,
10156 "(annotation?, ((attribute | attributeGroup)*, "
10157 "anyAttribute?))");
10158 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010159 }
10160 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010161 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010162}
10163
10164/**
10165 * xmlSchemaParseSimpleContent:
10166 * @ctxt: a schema validation context
10167 * @schema: the schema being built
10168 * @node: a subtree containing XML Schema informations
10169 *
10170 * parse a XML schema SimpleContent definition
10171 * *WARNING* this interface is highly subject to change
10172 *
10173 * Returns the type definition or NULL in case of error
10174 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010176xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10177 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010178{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010179 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010180 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010182
10183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 return (-1);
10185 /* Not a component, don't create it. */
10186 type = ctxt->ctxtType;
10187 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10188 /*
10189 * Check for illegal attributes.
10190 */
10191 attr = node->properties;
10192 while (attr != NULL) {
10193 if (attr->ns == NULL) {
10194 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010195 xmlSchemaPIllegalAttrErr(ctxt,
10196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10197 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010198 }
10199 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010200 xmlSchemaPIllegalAttrErr(ctxt,
10201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10202 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010203 }
10204 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010205 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010206
10207 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010208
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 /*
10210 * And now for the children...
10211 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 child = node->children;
10213 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010214 /*
10215 * Add the annotation to the complex type ancestor.
10216 */
10217 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10218 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010220 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010221 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010222 xmlSchemaParseRestriction(ctxt, schema, child,
10223 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010225 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 xmlSchemaParseExtension(ctxt, schema, child,
10227 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010229 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010230 if (child != NULL) {
10231 xmlSchemaPContentErr(ctxt,
10232 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010233 NULL, NULL, node, child, NULL,
10234 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010236 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010237}
10238
10239/**
10240 * xmlSchemaParseComplexContent:
10241 * @ctxt: a schema validation context
10242 * @schema: the schema being built
10243 * @node: a subtree containing XML Schema informations
10244 *
10245 * parse a XML schema ComplexContent definition
10246 * *WARNING* this interface is highly subject to change
10247 *
10248 * Returns the type definition or NULL in case of error
10249 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010250static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010251xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10252 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010253{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010255 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010256 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010257
10258 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010259 return (-1);
10260 /* Not a component, don't create it. */
10261 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010262 /*
10263 * Check for illegal attributes.
10264 */
10265 attr = node->properties;
10266 while (attr != NULL) {
10267 if (attr->ns == NULL) {
10268 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010269 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010270 {
10271 xmlSchemaPIllegalAttrErr(ctxt,
10272 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10273 NULL, NULL, attr);
10274 }
10275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10276 xmlSchemaPIllegalAttrErr(ctxt,
10277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10278 NULL, NULL, attr);
10279 }
10280 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010281 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010282
10283 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10284
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010285 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010286 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010287 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010288 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10289 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10290 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010291 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010292 child = node->children;
10293 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 /*
10295 * Add the annotation to the complex type ancestor.
10296 */
10297 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10298 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010300 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010301 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010302 xmlSchemaParseRestriction(ctxt, schema, child,
10303 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010305 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 xmlSchemaParseExtension(ctxt, schema, child,
10307 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010308 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010309 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010310 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010311 xmlSchemaPContentErr(ctxt,
10312 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10313 NULL, NULL, node, child,
10314 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010316 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010317}
10318
10319/**
10320 * xmlSchemaParseComplexType:
10321 * @ctxt: a schema validation context
10322 * @schema: the schema being built
10323 * @node: a subtree containing XML Schema informations
10324 *
10325 * parse a XML schema Complex Type definition
10326 * *WARNING* this interface is highly subject to change
10327 *
10328 * Returns the type definition or NULL in case of error
10329 */
10330static xmlSchemaTypePtr
10331xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010333{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010334 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010335 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010336 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010337 xmlAttrPtr attr;
10338 const xmlChar *attrValue;
10339 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010340 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010342
Daniel Veillard4255d502002-04-16 15:50:10 +000010343
10344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10345 return (NULL);
10346
Daniel Veillard01fa6152004-06-29 17:04:39 +000010347 ctxtType = ctxt->ctxtType;
10348
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 if (topLevel) {
10350 attr = xmlSchemaGetPropNode(node, "name");
10351 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010352 xmlSchemaPMissingAttrErr(ctxt,
10353 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010355 } else if (xmlSchemaPValAttrNode(ctxt,
10356 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010357 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10358 return (NULL);
10359 }
10360 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010361
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010362 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010363 /*
10364 * Parse as local complex type definition.
10365 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010366 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10368 if (type == NULL)
10369 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010370 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 type->node = node;
10372 type->type = XML_SCHEMA_TYPE_COMPLEX;
10373 /*
10374 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010375 */
10376 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010377 /*
10378 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010379 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010380 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010381 if (type == NULL)
10382 return (NULL);
10383 type->node = node;
10384 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010385 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010386 }
10387 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010388 /*
10389 * Handle attributes.
10390 */
10391 attr = node->properties;
10392 while (attr != NULL) {
10393 if (attr->ns == NULL) {
10394 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10395 /*
10396 * Attribute "id".
10397 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010398 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10399 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10401 /*
10402 * Attribute "mixed".
10403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010404 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010405 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010406 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10407 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 /*
10409 * Attributes of global complex type definitions.
10410 */
10411 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10412 /* Pass. */
10413 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10414 /*
10415 * Attribute "abstract".
10416 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10418 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10420 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10421 /*
10422 * Attribute "final".
10423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010424 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010425 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010426 if (xmlSchemaPValAttrBlockFinal(attrValue,
10427 &(type->flags),
10428 -1,
10429 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10430 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10431 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010432 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010433 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010434 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 type, (xmlNodePtr) attr, NULL,
10436 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010438 } else
10439 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010440 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10441 /*
10442 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 */
10444 attrValue = xmlSchemaGetNodeContent(ctxt,
10445 (xmlNodePtr) attr);
10446 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 -1,
10448 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 -1, -1, -1) != 0) {
10451 xmlSchemaPSimpleTypeErr(ctxt,
10452 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010453 type, (xmlNodePtr) attr, NULL,
10454 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010455 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010456 } else
10457 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010458 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 xmlSchemaPIllegalAttrErr(ctxt,
10460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 &des, type, attr);
10462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010463 } else {
10464 xmlSchemaPIllegalAttrErr(ctxt,
10465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010466 &des, type, attr);
10467 }
10468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010469 xmlSchemaPIllegalAttrErr(ctxt,
10470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10471 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010472 }
10473 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010475 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010476 /*
10477 * Apply default "block" values.
10478 */
10479 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10480 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10481 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10482 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010484 if (! final) {
10485 /*
10486 * Apply default "block" values.
10487 */
10488 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10489 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10490 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10491 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 /*
10494 * And now for the children...
10495 */
10496 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010497 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010498 child = node->children;
10499 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010500 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10501 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010502 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010503 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010504 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010505 /*
10506 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010507 * Specifying mixed='true' when the <simpleContent>
10508 * alternative is chosen has no effect
10509 */
William M. Bracke7091952004-05-11 15:09:58 +000010510 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10511 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010512 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010514 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010515 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10516 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010517 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010518 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010519 /*
10520 * SPEC
10521 * "...the third alternative (neither <simpleContent> nor
10522 * <complexContent>) is chosen. This case is understood as shorthand
10523 * for complex content restricting the ·ur-type definition·, and the
10524 * details of the mappings should be modified as necessary.
10525 */
10526 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10527 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010528 /*
10529 * Parse model groups.
10530 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010531 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010532 type->subtypes = (xmlSchemaTypePtr)
10533 xmlSchemaParseModelGroup(ctxt, schema, child,
10534 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010535 child = child->next;
10536 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010537 type->subtypes = (xmlSchemaTypePtr)
10538 xmlSchemaParseModelGroup(ctxt, schema, child,
10539 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010540 child = child->next;
10541 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010542 type->subtypes = (xmlSchemaTypePtr)
10543 xmlSchemaParseModelGroup(ctxt, schema, child,
10544 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010545 child = child->next;
10546 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010547 type->subtypes = (xmlSchemaTypePtr)
10548 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010549 child = child->next;
10550 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010551 /*
10552 * Parse attribute decls/refs.
10553 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010554 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010555 /*
10556 * Parse attribute wildcard.
10557 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010558 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010559 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10560 child = child->next;
10561 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010562 }
10563 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010564 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010565 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010566 &des, type, node, child,
10567 NULL, "(annotation?, (simpleContent | complexContent | "
10568 "((group | all | choice | sequence)?, ((attribute | "
10569 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010570 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010571 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010572 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010573 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 return (type);
10575}
10576
Daniel Veillard4255d502002-04-16 15:50:10 +000010577/**
10578 * xmlSchemaParseSchema:
10579 * @ctxt: a schema validation context
10580 * @node: a subtree containing XML Schema informations
10581 *
10582 * parse a XML schema definition from a node set
10583 * *WARNING* this interface is highly subject to change
10584 *
10585 * Returns the internal XML Schema structure built from the resource or
10586 * NULL in case of error
10587 */
10588static xmlSchemaPtr
10589xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10590{
10591 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010592 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010593 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010595
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010596 /*
10597 * This one is called by xmlSchemaParse only and is used if
10598 * the schema to be parsed was specified via the API; i.e. not
10599 * automatically by the validated instance document.
10600 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010601 if ((ctxt == NULL) || (node == NULL))
10602 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010603 nberrors = ctxt->nberrors;
10604 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010605 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010606 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010607 xmlSchemaImportPtr import;
10608
Daniel Veillard4255d502002-04-16 15:50:10 +000010609 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010610 if (schema == NULL)
10611 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010612 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010613 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010614 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010615 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10616 /*
10617 * TODO: Should we proceed with an invalid target namespace?
10618 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010619 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010620 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10621 /*
10622 * We are parsing the schema for schema!
10623 */
10624 ctxt->isS4S = 1;
10625 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010626 } else {
10627 schema->targetNamespace = NULL;
10628 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010629 /*
10630 * Add the current ns name and location to the import table;
10631 * this is needed to have a consistent mechanism, regardless
10632 * if all schemata are constructed dynamically fired by the
10633 * instance or if the schema to be used was specified via
10634 * the API.
10635 */
10636 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10637 schema->targetNamespace);
10638 if (import == NULL) {
10639 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10640 NULL, NULL, (xmlNodePtr) ctxt->doc,
10641 "Internal error: xmlSchemaParseSchema, "
10642 "failed to add an import entry", NULL);
10643 xmlSchemaFree(schema);
10644 schema = NULL;
10645 return (NULL);
10646 }
10647 import->schemaLocation = ctxt->URL;
10648 /*
10649 * NOTE: We won't set the doc here, otherwise it will be freed
10650 * if the import struct is freed.
10651 * import->doc = ctxt->doc;
10652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010653 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010654 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10655 } else {
10656 xmlDocPtr doc;
10657
10658 doc = node->doc;
10659
10660 if ((doc != NULL) && (doc->URL != NULL)) {
10661 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10662 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010663 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010664 } else {
10665 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10666 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010667 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010668 }
10669 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010670 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010671 if (ctxt->nberrors != 0) {
10672 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010673 xmlSchemaFree(schema);
10674 schema = NULL;
10675 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010676 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010677 if (schema != NULL)
10678 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010679 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010680#ifdef DEBUG
10681 if (schema == NULL)
10682 xmlGenericError(xmlGenericErrorContext,
10683 "xmlSchemaParse() failed\n");
10684#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010685 return (schema);
10686}
10687
10688/************************************************************************
10689 * *
10690 * Validating using Schemas *
10691 * *
10692 ************************************************************************/
10693
10694/************************************************************************
10695 * *
10696 * Reading/Writing Schemas *
10697 * *
10698 ************************************************************************/
10699
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010700#if 0 /* Will be enabled if it is clear what options are needed. */
10701/**
10702 * xmlSchemaParserCtxtSetOptions:
10703 * @ctxt: a schema parser context
10704 * @options: a combination of xmlSchemaParserOption
10705 *
10706 * Sets the options to be used during the parse.
10707 *
10708 * Returns 0 in case of success, -1 in case of an
10709 * API error.
10710 */
10711static int
10712xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10713 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010715{
10716 int i;
10717
10718 if (ctxt == NULL)
10719 return (-1);
10720 /*
10721 * WARNING: Change the start value if adding to the
10722 * xmlSchemaParseOption.
10723 */
10724 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10725 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010726 return (-1);
10727 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010728 }
10729 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010730 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010731}
10732
10733/**
10734 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010736 *
10737 * Returns the option combination of the parser context.
10738 */
10739static int
10740xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010741
10742{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010743 if (ctxt == NULL)
10744 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010745 else
10746 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010747}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010748#endif
10749
Daniel Veillard4255d502002-04-16 15:50:10 +000010750/**
10751 * xmlSchemaNewParserCtxt:
10752 * @URL: the location of the schema
10753 *
10754 * Create an XML Schemas parse context for that file/resource expected
10755 * to contain an XML Schemas file.
10756 *
10757 * Returns the parser context or NULL in case of error
10758 */
10759xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010760xmlSchemaNewParserCtxt(const char *URL)
10761{
Daniel Veillard4255d502002-04-16 15:50:10 +000010762 xmlSchemaParserCtxtPtr ret;
10763
10764 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010765 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010766
10767 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10768 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010769 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010770 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010771 return (NULL);
10772 }
10773 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010774 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010775 ret->dict = xmlDictCreate();
10776 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010777 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010778 return (ret);
10779}
10780
10781/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010782 * xmlSchemaNewMemParserCtxt:
10783 * @buffer: a pointer to a char array containing the schemas
10784 * @size: the size of the array
10785 *
10786 * Create an XML Schemas parse context for that memory buffer expected
10787 * to contain an XML Schemas file.
10788 *
10789 * Returns the parser context or NULL in case of error
10790 */
10791xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010792xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10793{
Daniel Veillard6045c902002-10-09 21:13:59 +000010794 xmlSchemaParserCtxtPtr ret;
10795
10796 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010797 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010798
10799 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10800 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010801 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010802 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010803 return (NULL);
10804 }
10805 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10806 ret->buffer = buffer;
10807 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010808 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010809 return (ret);
10810}
10811
10812/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010813 * xmlSchemaNewDocParserCtxt:
10814 * @doc: a preparsed document tree
10815 *
10816 * Create an XML Schemas parse context for that document.
10817 * NB. The document may be modified during the parsing process.
10818 *
10819 * Returns the parser context or NULL in case of error
10820 */
10821xmlSchemaParserCtxtPtr
10822xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10823{
10824 xmlSchemaParserCtxtPtr ret;
10825
10826 if (doc == NULL)
10827 return (NULL);
10828
10829 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10830 if (ret == NULL) {
10831 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10832 NULL);
10833 return (NULL);
10834 }
10835 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10836 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010837 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010838 /* The application has responsibility for the document */
10839 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010840
10841 return (ret);
10842}
10843
10844/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010845 * xmlSchemaFreeParserCtxt:
10846 * @ctxt: the schema parser context
10847 *
10848 * Free the resources associated to the schema parser context
10849 */
10850void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010851xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10852{
Daniel Veillard4255d502002-04-16 15:50:10 +000010853 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010854 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010855 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010856 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010857 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010858 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010859 xmlFree(ctxt->assemble);
10860 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010861 if (ctxt->vctxt != NULL) {
10862 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10863 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010864 if (ctxt->localImports != NULL)
10865 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010866 if (ctxt->substGroups != NULL)
10867 xmlHashFree(ctxt->substGroups,
10868 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010869 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010870 xmlFree(ctxt);
10871}
10872
10873/************************************************************************
10874 * *
10875 * Building the content models *
10876 * *
10877 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010878
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010879static void
10880xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010881 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010882{
10883 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010884 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010885 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010886 xmlSchemaSubstGroupPtr substGroup;
10887 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010888
10889 elemDecl = (xmlSchemaElementPtr) particle->children;
10890 /*
10891 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010892 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010893 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010894 end = xmlAutomataNewState(pctxt->am);
10895 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10896 if (substGroup == NULL) {
10897 xmlSchemaPErr(pctxt, GET_NODE(particle),
10898 XML_SCHEMAP_INTERNAL,
10899 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10900 "declaration is marked having a subst. group but none "
10901 "available.\n", elemDecl->name, NULL);
10902 return;
10903 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010904 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010905 /*
10906 * NOTE that we put the declaration in, even if it's abstract,
10907 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010908 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010909 xmlAutomataNewTransition2(pctxt->am,
10910 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010911 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10912 /*
10913 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010914 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010915 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010916 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10917 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010918 xmlAutomataNewTransition2(pctxt->am,
10919 start, NULL,
10920 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010921 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010922 }
10923 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010924 int counter;
10925 xmlAutomataStatePtr hop;
10926 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10927 UNBOUNDED : particle->maxOccurs - 1;
10928 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10929
10930 counter =
10931 xmlAutomataNewCounter(pctxt->am, minOccurs,
10932 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010933 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010934
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010935 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010936 xmlAutomataNewTransition2(pctxt->am,
10937 start, NULL,
10938 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010939 hop);
10940 /*
10941 * Add subst. group members.
10942 */
10943 for (i = 0; i < substGroup->members->nbItems; i++) {
10944 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10945 xmlAutomataNewEpsilon(pctxt->am,
10946 xmlAutomataNewTransition2(pctxt->am,
10947 start, NULL,
10948 member->name, member->targetNamespace, member),
10949 hop);
10950 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010951 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10952 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10953 }
10954 if (particle->minOccurs == 0)
10955 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010956 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010957}
10958
10959static void
10960xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10961 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010962{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010963 if (((xmlSchemaElementPtr) particle->children)->flags &
10964 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010965 /*
10966 * Substitution groups.
10967 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010968 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010969 } else {
10970 xmlSchemaElementPtr elemDecl;
10971 xmlAutomataStatePtr start;
10972
10973 elemDecl = (xmlSchemaElementPtr) particle->children;
10974
10975 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010976 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010977 if (particle->maxOccurs == 1) {
10978 start = ctxt->state;
10979 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10980 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10981 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10982 /* Special case. */
10983 start = ctxt->state;
10984 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10985 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010986 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010987 } else {
10988 int counter;
10989 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10990 UNBOUNDED : particle->maxOccurs - 1;
10991 int minOccurs = particle->minOccurs < 1 ?
10992 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010993
10994 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010995 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10996 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10997 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10998 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10999 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11000 NULL, counter);
11001 }
11002 if (particle->minOccurs == 0)
11003 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11004 }
11005}
11006
Daniel Veillard4255d502002-04-16 15:50:10 +000011007/**
11008 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011009 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011010 * @particle: the particle component
11011 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011012 *
11013 * Generate the automata sequence needed for that type
11014 */
11015static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011016xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011017 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011018 const xmlChar * name)
11019{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011020 if (particle == NULL) {
11021 xmlSchemaPErr(ctxt, NULL,
11022 XML_SCHEMAP_INTERNAL,
11023 "Internal error: xmlSchemaBuildAContentModel, "
11024 "particle is NULL.\n", NULL, NULL);
11025 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011026 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011027 if (particle->children == NULL) {
11028 xmlSchemaPErr(ctxt, GET_NODE(particle),
11029 XML_SCHEMAP_INTERNAL,
11030 "Internal error: xmlSchemaBuildAContentModel, "
11031 "no term on particle.\n", NULL, NULL);
11032 return;
11033 }
11034
11035 switch (particle->children->type) {
11036 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011037 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011038 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011039 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011040
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011041 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011042
Daniel Veillardc0826a72004-08-10 14:17:33 +000011043 start = ctxt->state;
11044 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011045
11046 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011047 if (wild->any == 1) {
11048 /*
11049 * We need to add both transitions:
11050 *
11051 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011052 */
11053 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011054 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011055 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011056 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11057 /*
11058 * 2. the {"*"} for elements in no namespace.
11059 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011060 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011062 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11064
11065 } else if (wild->nsSet != NULL) {
11066 ns = wild->nsSet;
11067 do {
11068 ctxt->state = start;
11069 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011070 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011071 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11072 ns = ns->next;
11073 } while (ns != NULL);
11074
11075 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011076
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011077 /*
11078 * Lead nodes with the negated namespace to the sink-state
11079 * {"*", "##other"}.
11080 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011081 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011082 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011083 /*
11084 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011085 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011086 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011087 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011088 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011089 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011091 } else {
11092 int counter;
11093 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011094 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011095 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011097 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011098
Daniel Veillardc0826a72004-08-10 14:17:33 +000011099 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011100 hop = xmlAutomataNewState(ctxt->am);
11101 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011102 ctxt->state =
11103 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011104 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011106 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011107 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011108 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011109 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011110 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011111 ns = wild->nsSet;
11112 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011113 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011114 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011115 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11117 ns = ns->next;
11118 } while (ns != NULL);
11119
11120 } else if (wild->negNsSet != NULL) {
11121 xmlAutomataStatePtr deadEnd;
11122
11123 deadEnd = xmlAutomataNewState(ctxt->am);
11124 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011125 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011126 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011127 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011129 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11131 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11132 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011133 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011134 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011135 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011136 ctxt->state = end;
11137 break;
11138 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011139 case XML_SCHEMA_TYPE_ELEMENT:
11140 xmlSchemaBuildContentModelForElement(ctxt, particle);
11141 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011142 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011143 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011144
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011145 /*
11146 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011147 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011148 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011149 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11150 sub = particle->children->children;
11151 while (sub != NULL) {
11152 xmlSchemaBuildAContentModel(ctxt,
11153 (xmlSchemaParticlePtr) sub, name);
11154 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011155 }
11156 } else {
11157 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011158
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011159 if (particle->maxOccurs >= UNBOUNDED) {
11160 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011161 xmlAutomataStatePtr tmp;
11162 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011163
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011164 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011165 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011166 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011167
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011168 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011169 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011170
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011171 sub = particle->children->children;
11172 while (sub != NULL) {
11173 xmlSchemaBuildAContentModel(ctxt,
11174 (xmlSchemaParticlePtr) sub, name);
11175 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011176 }
11177 tmp = ctxt->state;
11178 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11179 oldstate, counter);
11180 ctxt->state =
11181 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11182 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011183
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011184 } else {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011185 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11186 oldstate, NULL);
11187 oldstate = ctxt->state;
11188
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011189 sub = particle->children->children;
11190 while (sub != NULL) {
11191 xmlSchemaBuildAContentModel(ctxt,
11192 (xmlSchemaParticlePtr) sub, name);
11193 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011194 }
11195 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11196 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011197 /*
11198 * epsilon needed to block previous trans from
11199 * being allowed to enter back from another
11200 * construct
11201 */
11202 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11203 ctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011204 if (particle->minOccurs == 0) {
11205 xmlAutomataNewEpsilon(ctxt->am,
11206 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011207 }
11208 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011209 } else if ((particle->maxOccurs > 1)
11210 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011211 xmlAutomataStatePtr tmp;
11212 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011213
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011214 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011216 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011217
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011218 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011219 particle->minOccurs - 1,
11220 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011221
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011222 sub = particle->children->children;
11223 while (sub != NULL) {
11224 xmlSchemaBuildAContentModel(ctxt,
11225 (xmlSchemaParticlePtr) sub, name);
11226 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 }
11228 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 xmlAutomataNewCountedTrans(ctxt->am,
11230 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011231 ctxt->state =
11232 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11233 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011234 if (particle->minOccurs == 0) {
11235 xmlAutomataNewEpsilon(ctxt->am,
11236 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011237 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011238 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011239 sub = particle->children->children;
11240 while (sub != NULL) {
11241 xmlSchemaBuildAContentModel(ctxt,
11242 (xmlSchemaParticlePtr) sub, name);
11243 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011244 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011245 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11247 ctxt->state);
11248 }
11249 }
11250 }
11251 break;
11252 }
11253 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011255 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011256
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 start = ctxt->state;
11258 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011259
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011260 /*
11261 * iterate over the subtypes and remerge the end with an
11262 * epsilon transition
11263 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011264 if (particle->maxOccurs == 1) {
11265 sub = particle->children->children;
11266 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011267 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 xmlSchemaBuildAContentModel(ctxt,
11269 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011270 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011271 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011272 }
11273 } else {
11274 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011275 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011276 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11277 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011278 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011279 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011280
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 /*
11282 * use a counter to keep track of the number of transtions
11283 * which went through the choice.
11284 */
11285 counter =
Daniel Veillardafc05b62005-07-17 06:11:19 +000011286 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011287 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011288 base = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011289
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 sub = particle->children->children;
11291 while (sub != NULL) {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011292 ctxt->state = base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 xmlSchemaBuildAContentModel(ctxt,
11294 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011295 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011296 sub = sub->next;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011297/* DVDVDV */ }
11298 xmlAutomataNewEpsilon(ctxt->am, start, base);
11299 xmlAutomataNewCountedTrans(ctxt->am, hop, base, counter);
11300 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011301 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011302 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011303 xmlAutomataNewEpsilon(ctxt->am, start, end);
11304 }
11305 ctxt->state = end;
11306 break;
11307 }
11308 case XML_SCHEMA_TYPE_ALL:{
11309 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310 xmlSchemaParticlePtr sub;
11311 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011312 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011313
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011314 sub = (xmlSchemaParticlePtr) particle->children->children;
11315 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011316 break;
11317 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011318 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011319 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011320
11321 elemDecl = (xmlSchemaElementPtr) sub->children;
11322 if (elemDecl == NULL) {
11323 xmlSchemaPErr(ctxt, NULL,
11324 XML_SCHEMAP_INTERNAL,
11325 "Internal error: xmlSchemaBuildAContentModel, "
11326 "<element> particle a NULL term.\n", NULL, NULL);
11327 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011328 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011329 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011330 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011331 * {particles} of the group must be 0 or 1; this is
11332 * already ensured during the parse of the content of
11333 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011334 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 if ((sub->minOccurs == 1) &&
11336 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011337 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011338 ctxt->state,
11339 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011340 elemDecl->targetNamespace,
11341 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 } else if ((sub->minOccurs == 0) &&
11343 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011344
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011345 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011346 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011347 elemDecl->name,
11348 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011349 0,
11350 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011351 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011352 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011353 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011354 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011355 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011356 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011357 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011358 break;
11359 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 default:
11361 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 "Internal error: xmlSchemaBuildAContentModel, found "
11363 "unexpected term of type %d in content model of complex "
11364 "type '%s'.\n",
11365 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011366 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011367 }
11368}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011369
Daniel Veillard4255d502002-04-16 15:50:10 +000011370/**
11371 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011372 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011373 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011374 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011375 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011376 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011377 */
11378static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011379xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011380 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011381 const xmlChar * name)
11382{
Daniel Veillard4255d502002-04-16 15:50:10 +000011383 xmlAutomataStatePtr start;
11384
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011385 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11386 (type->contModel != NULL) ||
11387 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11388 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011389 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011390
11391#ifdef DEBUG_CONTENT
11392 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011393 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011394#endif
11395
Daniel Veillard4255d502002-04-16 15:50:10 +000011396 ctxt->am = xmlNewAutomata();
11397 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011398 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011399 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011400 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011401 }
11402 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011403 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011404 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011405 type->contModel = xmlAutomataCompile(ctxt->am);
11406 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011407 xmlSchemaPCustomErr(ctxt,
11408 XML_SCHEMAP_INTERNAL,
11409 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011410 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011411 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011412 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011413 XML_SCHEMAP_NOT_DETERMINISTIC,
11414 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011415 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011416 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011417 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011418#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011419 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011420 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011421 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011422#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011423 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011424 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011425 xmlFreeAutomata(ctxt->am);
11426 ctxt->am = NULL;
11427}
11428
11429/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011430 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011431 * @elem: the schema element context
11432 * @ctxt: the schema parser context
11433 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011434 * Resolves the references of an element declaration
11435 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011437 */
11438static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011439xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011440 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011441 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011442 const xmlChar * context ATTRIBUTE_UNUSED,
11443 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011444{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011445 if ((ctxt == NULL) || (elemDecl == NULL) ||
11446 ((elemDecl != NULL) &&
11447 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011448 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011449 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011450
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011451 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011452 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011453
11454 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011455 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011456 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011457 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011458 elemDecl->namedTypeNs);
11459 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011460 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011461 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011462 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011463 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011464 XML_SCHEMA_TYPE_BASIC, "type definition");
11465 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011466 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011468 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011469 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011470
Daniel Veillardc0826a72004-08-10 14:17:33 +000011471 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011472 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011473 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011474 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011475 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11476 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011477 if (substHead == NULL) {
11478 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011479 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011480 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011481 "substitutionGroup", elemDecl->substGroup,
11482 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011483 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011484 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011485 /*
11486 * Set the "substitution group affiliation".
11487 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011488 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011489 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011490 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011491 * (type definition)...otherwise the {type definition} of the
11492 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011493 * the substitutionGroup [attribute], if present
11494 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011495 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011496 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011497 }
11498 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011499 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11500 (elemDecl->substGroup == NULL))
11501 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011502}
11503
11504/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011505 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011506 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011507 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011508 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011509 * Checks and builds the "member type definitions" property of the union
11510 * simple type. This handles part (1), part (2) is done in
11511 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11512 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011513 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011514 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011515static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011516xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11517 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011518{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011519
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011520 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011521 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011522
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 /*
11524 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11525 * define the explicit members as the type definitions ·resolved·
11526 * to by the items in the ·actual value· of the memberTypes [attribute],
11527 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011528 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011529 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 /*
11531 * Resolve references.
11532 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011533 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011534 lastLink = NULL;
11535 while (link != NULL) {
11536 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011537
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11539 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11540
11541 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11542 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11543 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011544 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011545 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11546 /*
11547 * Remove the member type link.
11548 */
11549 if (lastLink == NULL)
11550 type->memberTypes = link->next;
11551 else
11552 lastLink->next = link->next;
11553 newLink = link;
11554 link = link->next;
11555 xmlFree(newLink);
11556 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011558 lastLink = link;
11559 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011560 }
11561 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011562 /*
11563 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011564 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011565 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011566 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011567 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11568 if (link == NULL) {
11569 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11570 return (-1);
11571 }
11572 link->type = memberType;
11573 link->next = NULL;
11574 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011575 type->memberTypes = link;
11576 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011577 lastLink->next = link;
11578 lastLink = link;
11579 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011580 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011581 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011582}
11583
Daniel Veillard4255d502002-04-16 15:50:10 +000011584/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011585 * xmlSchemaIsDerivedFromBuiltInType:
11586 * @ctxt: the schema parser context
11587 * @type: the type definition
11588 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011589 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011590 *
11591 * Returns 1 if the type has the given value type, or
11592 * is derived from such a type.
11593 */
William M. Brack803812b2004-06-03 02:11:24 +000011594static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011595xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011596{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011597 if (type == NULL)
11598 return (0);
11599 if (IS_COMPLEX_TYPE(type))
11600 return (0);
11601 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11602 if (type->builtInType == valType)
11603 return(1);
11604 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11605 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11606 return (0);
11607 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11608 } else
11609 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011610
11611 return (0);
11612}
11613
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011614#if 0
11615/**
11616 * xmlSchemaIsDerivedFromBuiltInType:
11617 * @ctxt: the schema parser context
11618 * @type: the type definition
11619 * @valType: the value type
11620 *
11621 *
11622 * Returns 1 if the type has the given value type, or
11623 * is derived from such a type.
11624 */
11625static int
11626xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11627{
11628 if (type == NULL)
11629 return (0);
11630 if (IS_COMPLEX_TYPE(type))
11631 return (0);
11632 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11633 if (type->builtInType == valType)
11634 return(1);
11635 return (0);
11636 } else
11637 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11638
11639 return (0);
11640}
11641#endif
11642
11643static xmlSchemaTypePtr
11644xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11645{
11646 if (type == NULL)
11647 return (NULL);
11648 if (IS_COMPLEX_TYPE(type))
11649 return (NULL);
11650 if (type->type == XML_SCHEMA_TYPE_BASIC)
11651 return(type);
11652 else
11653 return(xmlSchemaQueryBuiltInType(type->subtypes));
11654
11655 return (NULL);
11656}
11657
Daniel Veillard3646d642004-06-02 19:19:14 +000011658/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011659 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011660 * @type: the simpleType definition
11661 *
11662 * Returns the primitive type of the given type or
11663 * NULL in case of error.
11664 */
11665static xmlSchemaTypePtr
11666xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11667{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011668
Daniel Veillard01fa6152004-06-29 17:04:39 +000011669 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011670 /*
11671 * Note that anySimpleType is actually not a primitive type
11672 * but we need that here.
11673 */
11674 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11675 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011676 return (type);
11677 type = type->baseType;
11678 }
11679
11680 return (NULL);
11681}
11682
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011683#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011684/**
11685 * xmlSchemaGetBuiltInTypeAncestor:
11686 * @type: the simpleType definition
11687 *
11688 * Returns the primitive type of the given type or
11689 * NULL in case of error.
11690 */
11691static xmlSchemaTypePtr
11692xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11693{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011694 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011695 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011696 while (type != NULL) {
11697 if (type->type == XML_SCHEMA_TYPE_BASIC)
11698 return (type);
11699 type = type->baseType;
11700 }
11701
11702 return (NULL);
11703}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011704#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011705
Daniel Veillard01fa6152004-06-29 17:04:39 +000011706/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011707 * xmlSchemaBuildAttributeUsesOwned:
11708 * @ctxt: the schema parser context
11709 * @type: the complex type definition
11710 * @cur: the attribute declaration list
11711 * @lastUse: the top of the attribute use list
11712 *
11713 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011714 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011715 * xmlSchemaBuildAttributeValidation only.
11716 */
11717static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011718xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011719 xmlSchemaAttributePtr cur,
11720 xmlSchemaAttributeLinkPtr *uses,
11721 xmlSchemaAttributeLinkPtr *lastUse)
11722{
11723 xmlSchemaAttributeLinkPtr tmp;
11724 while (cur != NULL) {
11725 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011726 /*
11727 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11728 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011729 * <attributeGroup> [children], if any."
11730 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011731 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11732 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011733 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011734 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011735 }
11736 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011737 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011738 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011739 */
11740 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011741 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11742 if (tmp == NULL) {
11743 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11744 return (-1);
11745 }
11746 tmp->attr = cur;
11747 tmp->next = NULL;
11748 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 *uses = tmp;
11750 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011751 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011752 *lastUse = tmp;
11753 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011754 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011755 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011756 return (0);
11757}
11758
Daniel Veillard50355f02004-06-08 17:52:16 +000011759/**
11760 * xmlSchemaCloneWildcardNsConstraints:
11761 * @ctxt: the schema parser context
11762 * @dest: the destination wildcard
11763 * @source: the source wildcard
11764 *
11765 * Clones the namespace constraints of source
11766 * and assignes them to dest.
11767 * Returns -1 on internal error, 0 otherwise.
11768 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011769static int
11770xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11771 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011772 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011773{
11774 xmlSchemaWildcardNsPtr cur, tmp, last;
11775
11776 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011777 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011778 (*dest)->any = source->any;
11779 cur = source->nsSet;
11780 last = NULL;
11781 while (cur != NULL) {
11782 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11783 if (tmp == NULL)
11784 return(-1);
11785 tmp->value = cur->value;
11786 if (last == NULL)
11787 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011788 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011789 last->next = tmp;
11790 last = tmp;
11791 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011792 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011793 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011794 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011795 if (source->negNsSet != NULL) {
11796 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11797 if ((*dest)->negNsSet == NULL)
11798 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011800 } else
11801 (*dest)->negNsSet = NULL;
11802 return(0);
11803}
11804
Daniel Veillard50355f02004-06-08 17:52:16 +000011805/**
11806 * xmlSchemaUnionWildcards:
11807 * @ctxt: the schema parser context
11808 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011809 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011810 *
11811 * Unions the namespace constraints of the given wildcards.
11812 * @completeWild will hold the resulting union.
11813 * Returns a positive error code on failure, -1 in case of an
11814 * internal error, 0 otherwise.
11815 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011816static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011817xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011818 xmlSchemaWildcardPtr completeWild,
11819 xmlSchemaWildcardPtr curWild)
11820{
11821 xmlSchemaWildcardNsPtr cur, curB, tmp;
11822
11823 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011824 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011825 * value.
11826 */
11827 if ((completeWild->any == curWild->any) &&
11828 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11829 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011830
Daniel Veillard3646d642004-06-02 19:19:14 +000011831 if ((completeWild->negNsSet == NULL) ||
11832 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011833
Daniel Veillard3646d642004-06-02 19:19:14 +000011834 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011835 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011836
11837 /*
11838 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011839 */
11840 cur = completeWild->nsSet;
11841 while (cur != NULL) {
11842 found = 0;
11843 curB = curWild->nsSet;
11844 while (curB != NULL) {
11845 if (cur->value == curB->value) {
11846 found = 1;
11847 break;
11848 }
11849 curB = curB->next;
11850 }
11851 if (!found)
11852 break;
11853 cur = cur->next;
11854 }
11855 if (found)
11856 return(0);
11857 } else
11858 return(0);
11859 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011860 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011861 /*
11862 * 2 If either O1 or O2 is any, then any must be the value
11863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011864 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011865 if (completeWild->any == 0) {
11866 completeWild->any = 1;
11867 if (completeWild->nsSet != NULL) {
11868 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11869 completeWild->nsSet = NULL;
11870 }
11871 if (completeWild->negNsSet != NULL) {
11872 xmlFree(completeWild->negNsSet);
11873 completeWild->negNsSet = NULL;
11874 }
11875 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011876 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011877 }
11878 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011879 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011880 * then the union of those sets must be the value.
11881 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011882 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011883 int found;
11884 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011885
Daniel Veillard3646d642004-06-02 19:19:14 +000011886 cur = curWild->nsSet;
11887 start = completeWild->nsSet;
11888 while (cur != NULL) {
11889 found = 0;
11890 curB = start;
11891 while (curB != NULL) {
11892 if (cur->value == curB->value) {
11893 found = 1;
11894 break;
11895 }
11896 curB = curB->next;
11897 }
11898 if (!found) {
11899 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011900 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011901 return (-1);
11902 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011903 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011904 completeWild->nsSet = tmp;
11905 }
11906 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011907 }
11908
Daniel Veillard3646d642004-06-02 19:19:14 +000011909 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011910 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011911 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011912 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011913 * or ·absent·), then a pair of not and ·absent· must be the value.
11914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011916 (curWild->negNsSet != NULL) &&
11917 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11918 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011919
11920 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011921 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011922 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011923 * 5.
11924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011925 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011926 (completeWild->negNsSet->value != NULL) &&
11927 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011928 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011929 (curWild->negNsSet->value != NULL) &&
11930 (completeWild->nsSet != NULL))) {
11931
11932 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011933
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 if (completeWild->nsSet != NULL) {
11935 cur = completeWild->nsSet;
11936 curB = curWild->negNsSet;
11937 } else {
11938 cur = curWild->nsSet;
11939 curB = completeWild->negNsSet;
11940 }
11941 nsFound = 0;
11942 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011943 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011944 absentFound = 1;
11945 else if (cur->value == curB->value)
11946 nsFound = 1;
11947 if (nsFound && absentFound)
11948 break;
11949 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011950 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011951
11952 if (nsFound && absentFound) {
11953 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011954 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011955 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011956 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011957 completeWild->any = 1;
11958 if (completeWild->nsSet != NULL) {
11959 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11960 completeWild->nsSet = NULL;
11961 }
11962 if (completeWild->negNsSet != NULL) {
11963 xmlFree(completeWild->negNsSet);
11964 completeWild->negNsSet = NULL;
11965 }
11966 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967 /*
11968 * 5.2 If the set S includes the negated namespace name
11969 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011970 * be the value.
11971 */
11972 if (completeWild->nsSet != NULL) {
11973 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11974 completeWild->nsSet = NULL;
11975 }
11976 if (completeWild->negNsSet == NULL) {
11977 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11978 if (completeWild->negNsSet == NULL)
11979 return (-1);
11980 }
11981 completeWild->negNsSet->value = NULL;
11982 } else if ((!nsFound) && absentFound) {
11983 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011984 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011985 * namespace name, then the union is not expressible.
11986 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011987 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011988 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011989 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011991 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011992 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011993 /*
11994 * 5.4 If the set S does not include either the negated namespace
11995 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011996 * and a namespace name must be the value.
11997 */
11998 if (completeWild->negNsSet == NULL) {
11999 if (completeWild->nsSet != NULL) {
12000 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12001 completeWild->nsSet = NULL;
12002 }
12003 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12004 if (completeWild->negNsSet == NULL)
12005 return (-1);
12006 completeWild->negNsSet->value = curWild->negNsSet->value;
12007 }
12008 }
12009 return (0);
12010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012011 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012012 * 6.
12013 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012014 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012015 (completeWild->negNsSet->value == NULL) &&
12016 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012017 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012018 (curWild->negNsSet->value == NULL) &&
12019 (completeWild->nsSet != NULL))) {
12020
12021 if (completeWild->nsSet != NULL) {
12022 cur = completeWild->nsSet;
12023 } else {
12024 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012025 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012026 while (cur != NULL) {
12027 if (cur->value == NULL) {
12028 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012029 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012030 * value.
12031 */
12032 completeWild->any = 1;
12033 if (completeWild->nsSet != NULL) {
12034 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12035 completeWild->nsSet = NULL;
12036 }
12037 if (completeWild->negNsSet != NULL) {
12038 xmlFree(completeWild->negNsSet);
12039 completeWild->negNsSet = NULL;
12040 }
12041 return (0);
12042 }
12043 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012044 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012045 if (completeWild->negNsSet == NULL) {
12046 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012047 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012048 * and ·absent· must be the value.
12049 */
12050 if (completeWild->nsSet != NULL) {
12051 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12052 completeWild->nsSet = NULL;
12053 }
12054 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12055 if (completeWild->negNsSet == NULL)
12056 return (-1);
12057 completeWild->negNsSet->value = NULL;
12058 }
12059 return (0);
12060 }
12061 return (0);
12062
12063}
12064
Daniel Veillard50355f02004-06-08 17:52:16 +000012065/**
12066 * xmlSchemaIntersectWildcards:
12067 * @ctxt: the schema parser context
12068 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012069 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012070 *
12071 * Intersects the namespace constraints of the given wildcards.
12072 * @completeWild will hold the resulting intersection.
12073 * Returns a positive error code on failure, -1 in case of an
12074 * internal error, 0 otherwise.
12075 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012076static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012077xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012078 xmlSchemaWildcardPtr completeWild,
12079 xmlSchemaWildcardPtr curWild)
12080{
William M. Brack803812b2004-06-03 02:11:24 +000012081 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012082
12083 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012084 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012085 * value.
12086 */
12087 if ((completeWild->any == curWild->any) &&
12088 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12089 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012090
Daniel Veillard3646d642004-06-02 19:19:14 +000012091 if ((completeWild->negNsSet == NULL) ||
12092 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012093
Daniel Veillard3646d642004-06-02 19:19:14 +000012094 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012095 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012096
12097 /*
12098 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012099 */
12100 cur = completeWild->nsSet;
12101 while (cur != NULL) {
12102 found = 0;
12103 curB = curWild->nsSet;
12104 while (curB != NULL) {
12105 if (cur->value == curB->value) {
12106 found = 1;
12107 break;
12108 }
12109 curB = curB->next;
12110 }
12111 if (!found)
12112 break;
12113 cur = cur->next;
12114 }
12115 if (found)
12116 return(0);
12117 } else
12118 return(0);
12119 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012120 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012121 /*
12122 * 2 If either O1 or O2 is any, then the other must be the value.
12123 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012124 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012125 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012126 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012127 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012128 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012129 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012130 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12131 * name or ·absent·) and the other is a set of (namespace names or
12132 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012133 * the set, minus ·absent· if it was in the set, must be the value.
12134 */
12135 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12136 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12137 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012138
Daniel Veillard3646d642004-06-02 19:19:14 +000012139 if (completeWild->nsSet == NULL) {
12140 neg = completeWild->negNsSet->value;
12141 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12142 return(-1);
12143 } else
12144 neg = curWild->negNsSet->value;
12145 /*
12146 * Remove absent and negated.
12147 */
12148 prev = NULL;
12149 cur = completeWild->nsSet;
12150 while (cur != NULL) {
12151 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012152 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012153 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012154 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012155 prev->next = cur->next;
12156 xmlFree(cur);
12157 break;
12158 }
12159 prev = cur;
12160 cur = cur->next;
12161 }
12162 if (neg != NULL) {
12163 prev = NULL;
12164 cur = completeWild->nsSet;
12165 while (cur != NULL) {
12166 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012167 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012168 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012170 prev->next = cur->next;
12171 xmlFree(cur);
12172 break;
12173 }
12174 prev = cur;
12175 cur = cur->next;
12176 }
12177 }
12178
12179 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012180 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012181 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012183 * then the intersection of those sets must be the value.
12184 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012185 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012186 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012187
Daniel Veillard3646d642004-06-02 19:19:14 +000012188 cur = completeWild->nsSet;
12189 prev = NULL;
12190 while (cur != NULL) {
12191 found = 0;
12192 curB = curWild->nsSet;
12193 while (curB != NULL) {
12194 if (cur->value == curB->value) {
12195 found = 1;
12196 break;
12197 }
12198 curB = curB->next;
12199 }
12200 if (!found) {
12201 if (prev == NULL)
12202 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012203 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012204 prev->next = cur->next;
12205 tmp = cur->next;
12206 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012207 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012208 continue;
12209 }
12210 prev = cur;
12211 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012212 }
12213
Daniel Veillard3646d642004-06-02 19:19:14 +000012214 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012215 }
12216 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012217 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012218 */
12219 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012220 (curWild->negNsSet != NULL) &&
12221 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012222 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012223 (curWild->negNsSet->value != NULL)) {
12224
12225 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012226 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012227 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012228 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012229 }
12230 /*
12231 * 6 If the one is a negation of a namespace name and the other
12232 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012233 * of a namespace name must be the value.
12234 */
12235 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12236 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012237 (completeWild->negNsSet->value == NULL)) {
12238 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012239 }
12240 return(0);
12241}
12242
Daniel Veillard50355f02004-06-08 17:52:16 +000012243/**
12244 * xmlSchemaIsWildcardNsConstraintSubset:
12245 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012246 * @sub: the first wildcard
12247 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012248 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012249 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12250 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012251 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012252 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012253 */
12254static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012255xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12256 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012257{
Daniel Veillard50355f02004-06-08 17:52:16 +000012258 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012259 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012260 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012261 if (super->any)
12262 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012263 /*
12264 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12265 * 2.2 super must be a pair of not and the same value.
12266 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012267 if ((sub->negNsSet != NULL) &&
12268 (super->negNsSet != NULL) &&
12269 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012270 return (0);
12271 /*
12272 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012273 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012274 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012275 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012276 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012277 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012278 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012279 xmlSchemaWildcardNsPtr cur, curB;
12280 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012281
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012282 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012283 while (cur != NULL) {
12284 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012285 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012286 while (curB != NULL) {
12287 if (cur->value == curB->value) {
12288 found = 1;
12289 break;
12290 }
12291 curB = curB->next;
12292 }
12293 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012294 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012295 cur = cur->next;
12296 }
12297 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012298 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012299 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012300 xmlSchemaWildcardNsPtr cur;
12301 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012302 * 3.2.2 super must be a pair of not and a namespace name or
12303 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012304 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012305 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012306 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012307 if (cur->value == super->negNsSet->value)
12308 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012309 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012310 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012311 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012312 }
12313 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012314 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012315}
12316
12317/**
12318 * xmlSchemaBuildCompleteAttributeWildcard:
12319 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012320 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012321 * @completeWild: the resulting complete wildcard
12322 *
12323 * Returns -1 in case of an internal error, 0 otherwise.
12324 */
12325static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012326xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012327 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012328 xmlSchemaWildcardPtr *completeWild)
12329{
Daniel Veillard3646d642004-06-02 19:19:14 +000012330 while (attrs != NULL) {
12331 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12332 xmlSchemaAttributeGroupPtr group;
12333
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012334 group = (xmlSchemaAttributeGroupPtr) attrs;
12335 /*
12336 * Handle attribute group references.
12337 */
12338 if (group->ref != NULL) {
12339 if (group->refItem == NULL) {
12340 /*
12341 * TODO: Should we raise a warning here?
12342 */
12343 /*
12344 * The referenced attribute group definition could not
12345 * be resolved beforehand, so skip.
12346 */
12347 attrs = attrs->next;
12348 continue;
12349 } else
12350 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012351 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012352 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012353 * For every attribute group definition, an intersected wildcard
12354 * will be created (assumed that a wildcard exists on the
12355 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012356 * at all).
12357 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12358 * that the intersection will be performed only once.
12359 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012360 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12361 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012362 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012363 group->attributes, &group->attributeWildcard) == -1)
12364 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012365 }
12366 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012367 }
12368 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012369 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012370 /*
12371 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012372 *
12373 * Although the complete wildcard might not correspond to any
12374 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012375 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012376 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12377 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12378 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012379 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012380 completeWild, group->attributeWildcard) == -1)
12381 return (-1);
12382 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012383 (*completeWild)->node = group->attributeWildcard->node;
12384 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012385 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012386 }
12387 }
12388 attrs = attrs->next;
12389 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012390
12391 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012392}
12393
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012394static int
12395xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12396 int *fixed,
12397 const xmlChar **value,
12398 xmlSchemaValPtr *val)
12399{
12400 *fixed = 0;
12401 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012403 *val = NULL;
12404
12405 if (item->defValue == NULL)
12406 item = item->refDecl;
12407
12408 if (item == NULL)
12409 return (0);
12410
12411 if (item->defValue != NULL) {
12412 *value = item->defValue;
12413 if (val != 0)
12414 *val = item->defVal;
12415 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12416 *fixed = 1;
12417 return (1);
12418 }
12419 return (0);
12420}
Daniel Veillard3646d642004-06-02 19:19:14 +000012421/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012422 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012423 * @wild: the wildcard
12424 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012425 *
12426 * Validation Rule: Wildcard allows Namespace Name
12427 * (cvc-wildcard-namespace)
12428 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012429 *
12430 * Returns 1 if the given namespace matches the wildcard,
12431 * 0 otherwise.
12432 */
12433static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012434xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12435 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012436{
12437 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012438 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012439
12440 if (wild->any)
12441 return(1);
12442 else if (wild->nsSet != NULL) {
12443 xmlSchemaWildcardNsPtr cur;
12444
12445 cur = wild->nsSet;
12446 while (cur != NULL) {
12447 if (xmlStrEqual(cur->value, ns))
12448 return(1);
12449 cur = cur->next;
12450 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012451 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012452 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012453 return(1);
12454
Daniel Veillard3646d642004-06-02 19:19:14 +000012455 return(0);
12456}
12457
12458/**
12459 * xmlSchemaBuildAttributeValidation:
12460 * @ctxt: the schema parser context
12461 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012462 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012463 *
12464 * Builds the wildcard and the attribute uses on the given complex type.
12465 * Returns -1 if an internal error occurs, 0 otherwise.
12466 */
12467static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012468xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12469 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012470{
12471 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012472 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12473 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012474 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012475 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012476 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012477 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012478
Daniel Veillard01fa6152004-06-29 17:04:39 +000012479 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012480 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012481 * Complex Type Definition with complex content Schema Component.
12482 *
12483 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012484 * TODO: Add checks for absent referenced attribute declarations and
12485 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012486 */
12487 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012488 PERROR_INT("xmlSchemaBuildAttributeValidation",
12489 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012490 return (-1);
12491 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012492 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012493 PERROR_INT("xmlSchemaBuildAttributeValidation",
12494 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012495 return (-1);
12496 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012497 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012498 /*
12499 * Inherit the attribute uses of the base type.
12500 */
12501 /*
12502 * NOTE: It is allowed to "extend" the anyType complex type.
12503 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012504 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012505 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012506 for (cur = baseType->attributeUses; cur != NULL;
12507 cur = cur->next) {
12508 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012509 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12510 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012511 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012512 "building attribute uses of complexType", NULL);
12513 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012514 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012515 tmp->attr = cur->attr;
12516 tmp->next = NULL;
12517 if (type->attributeUses == NULL) {
12518 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012519 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012520 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012521 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012522 }
12523 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012524 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012525 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012526 /*
12527 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012528 */
12529 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12530 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012531 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012532 * NOTE: During the parse time, the wildcard is created on the complexType
12533 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012534 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012535 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012536 PERROR_INT("xmlSchemaBuildAttributeValidation",
12537 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012538 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012539 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012540
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012541 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12542 ((IS_ANYTYPE(baseType)) ||
12543 ((baseType != NULL) &&
12544 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12545 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012546 if (type->attributeWildcard != NULL) {
12547 /*
12548 * Union the complete wildcard with the base wildcard.
12549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012550 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012551 baseType->attributeWildcard) == -1)
12552 return (-1);
12553 } else {
12554 /*
12555 * Just inherit the wildcard.
12556 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012557 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012558 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012559 * wildcard is shared.
12560 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012561 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012562 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012563 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012564
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012565 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12566 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 /*
12568 * Derivation Valid (Restriction, Complex)
12569 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012570 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012571 if (baseType->attributeWildcard == NULL) {
12572 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012573 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012574 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012575 "The type has an attribute wildcard, "
12576 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012577 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012578 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012579 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012580 } else if (xmlSchemaCheckCOSNSSubset(
12581 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012582 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012584 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012585 NULL, type, NULL,
12586 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012587 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012588 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12589 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012590 return (1);
12591 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592 /* 4.3 Unless the {base type definition} is the ·ur-type
12593 * definition·, the complex type definition's {attribute
12594 * wildcard}'s {process contents} must be identical to or
12595 * stronger than the {base type definition}'s {attribute
12596 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012597 * than lax is stronger than skip.
12598 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012599 if ((! IS_ANYTYPE(baseType)) &&
12600 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012601 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012602 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012603 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012604 NULL, type, NULL,
12605 "The 'process contents' of the attribute wildcard is "
12606 "weaker than the one in the base type %s",
12607 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012608 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012609 return (1);
12610 }
12611 }
12612 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12613 /*
12614 * Derivation Valid (Extension)
12615 * At this point the type and the base have both, either
12616 * no wildcard or a wildcard.
12617 */
12618 if ((baseType->attributeWildcard != NULL) &&
12619 (baseType->attributeWildcard != type->attributeWildcard)) {
12620 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012621 if (xmlSchemaCheckCOSNSSubset(
12622 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012623 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012624 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625 NULL, type, NULL,
12626 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012627 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012628 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12629 FREE_AND_NULL(str)
12630 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012631 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012632 }
12633 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012634
Daniel Veillard3646d642004-06-02 19:19:14 +000012635 /*
12636 * Gather attribute uses defined by this type.
12637 */
12638 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012639 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012640 &uses, &lastUse) == -1) {
12641 return (-1);
12642 }
12643 }
12644 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012645 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012646 * not have identical {name}s and {target namespace}s."
12647 *
12648 * For "extension" this is done further down.
12649 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012650 if ((uses != NULL) && ((type->flags &
12651 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012652 cur = uses;
12653 while (cur != NULL) {
12654 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012655 while (tmp != NULL) {
12656 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012657 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012659 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12660
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012661 xmlSchemaPAttrUseErr(pctxt,
12662 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12663 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012664 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665 xmlSchemaFormatQName(&str,
12666 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12667 xmlSchemaGetAttrName(tmp->attr)));
12668 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012669 break;
12670 }
12671 tmp = tmp->next;
12672 }
12673 cur = cur->next;
12674 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012675 }
12676 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012677 /*
12678 * Derive by restriction.
12679 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012680 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012681 type->attributeUses = uses;
12682 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012683 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012684 const xmlChar *bEffValue;
12685 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012686
12687 cur = uses;
12688 while (cur != NULL) {
12689 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012690 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012691 base = type->attributeUses;
12692 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012693 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012694 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012695 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012696 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012697
12698 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012699
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012700 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012701 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12702 (base->attr->occurs ==
12703 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12704 /*
12705 * NOOP.
12706 */
12707 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012708 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12709 (base->attr->occurs ==
12710 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012711 /*
12712 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012713 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012714 xmlSchemaPAttrUseErr(pctxt,
12715 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12716 type, cur->attr,
12717 "The 'optional' use is inconsistent with a "
12718 "matching 'required' use of the base type",
12719 NULL);
12720 } else if ((cur->attr->occurs ==
12721 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12722 (base->attr->occurs ==
12723 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12724 /*
12725 * derivation-ok-restriction 3
12726 */
12727 xmlSchemaPCustomErr(pctxt,
12728 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12729 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012730 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012731 "attribute use '%s' of the base type is "
12732 "missing",
12733 xmlSchemaFormatQName(&str,
12734 xmlSchemaGetAttrTargetNsURI(base->attr),
12735 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012736 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 } else if (xmlSchemaCheckCOSSTDerivedOK(
12738 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12739
12740 /*
12741 * SPEC (2.1.2) "R's {attribute declaration}'s
12742 * {type definition} must be validly derived from
12743 * B's {type definition} given the empty set as
12744 * defined in Type Derivation OK (Simple) (§3.14.6)."
12745 */
12746 xmlSchemaPAttrUseErr(pctxt,
12747 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12748 type, cur->attr,
12749 "The attribute declaration's type "
12750 "definition is not validly derived from "
12751 "the corresponding definition in the "
12752 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012753 } else {
12754 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012755 * 2.1.3 [Definition:] Let the effective value
12756 * constraint of an attribute use be its {value
12757 * constraint}, if present, otherwise its {attribute
12758 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012759 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012760 xmlSchemaGetEffectiveValueConstraint(base->attr,
12761 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012762 /*
12763 * 2.1.3 ... one of the following must be true
12764 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012765 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012766 * ·absent· or default.
12767 */
12768 if ((bEffValue != NULL) &&
12769 (effFixed == 1)) {
12770 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012771
12772 xmlSchemaGetEffectiveValueConstraint(base->attr,
12773 &effFixed, &rEffValue, 0);
12774 /*
12775 * 2.1.3.2 R's ·effective value constraint· is
12776 * fixed with the same string as B's.
12777 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012778 */
12779 if ((effFixed == 0) ||
12780 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012781 xmlSchemaPAttrUseErr(pctxt,
12782 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12783 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012784 "The effective value constraint of the "
12785 "attribute use is inconsistent with "
12786 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012787 NULL);
12788 } else {
12789 /*
12790 * Override the attribute use.
12791 */
12792 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012793 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012794 } else
12795 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012796 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012797
Daniel Veillard3646d642004-06-02 19:19:14 +000012798 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012799 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012800 base = base->next;
12801 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012802
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012803 if ((!found) && (cur->attr->occurs !=
12804 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12805 /*
12806 * derivation-ok-restriction 2.2
12807 */
12808 if ((baseType->attributeWildcard == NULL) ||
12809 (xmlSchemaCheckCVCWildcardNamespace(
12810 baseType->attributeWildcard,
12811 cur->attr->targetNamespace) != 1)) {
12812 xmlSchemaPAttrUseErr(pctxt,
12813 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12814 type, cur->attr,
12815 "Neither a matching attribute use, "
12816 "nor a matching wildcard in the base type does exist",
12817 NULL);
12818 } else {
12819 /*
12820 * Add the attribute use.
12821 *
12822 * Note that this may lead to funny derivation error reports, if
12823 * multiple equal attribute uses exist; but this is not
12824 * allowed anyway, and it will be reported beforehand.
12825 */
12826 tmp = cur;
12827 if (prev != NULL)
12828 prev->next = cur->next;
12829 else
12830 uses = cur->next;
12831 cur = cur->next;
12832 tmp->next = NULL;
12833 if (type->attributeUses == NULL) {
12834 type->attributeUses = tmp;
12835 } else
12836 lastBaseUse->next = tmp;
12837 lastBaseUse = tmp;
12838
12839 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012840 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012841 }
12842 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012843 cur = cur->next;
12844 }
12845 if (uses != NULL)
12846 xmlSchemaFreeAttributeUseList(uses);
12847 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012848 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012849 /*
12850 * The spec allows only appending, and not other kinds of extensions.
12851 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012852 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012853 */
12854 if (uses != NULL) {
12855 if (type->attributeUses == NULL) {
12856 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012857 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012858 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012859 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012860 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012861 PERROR_INT("xmlSchemaBuildAttributeValidation",
12862 "no derivation method");
12863 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012864 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012865 /*
12866 * 3.4.6 -> Complex Type Definition Properties Correct
12867 */
12868 if (type->attributeUses != NULL) {
12869 cur = type->attributeUses;
12870 prev = NULL;
12871 while (cur != NULL) {
12872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012873 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012874 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012875 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012876 * Note that this was already done for "restriction" and types derived from
12877 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012878 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012879 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12880 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012881 while (tmp != NULL) {
12882 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012883 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012884 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012885 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012886
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012887 xmlSchemaPAttrUseErr(pctxt,
12888 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12889 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012890 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012891 break;
12892 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012893 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012894 }
12895 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012896 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012897 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012898 * not have {type definition}s which are or are derived from ID.
12899 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012900 if ((cur->attr->subtypes != NULL) &&
12901 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12902 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012903 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012904 xmlSchemaPAttrUseErr(pctxt,
12905 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12906 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012907 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012908 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012909 NULL);
12910 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012911 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012912 id = cur;
12913 }
12914 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012915 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012916 * stage is to be able to catch dublicate attribute uses. So we had to keep
12917 * prohibited uses in the list as well.
12918 */
12919 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12920 tmp = cur;
12921 if (prev == NULL)
12922 type->attributeUses = cur->next;
12923 else
12924 prev->next = cur->next;
12925 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012926 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012927 } else {
12928 prev = cur;
12929 cur = cur->next;
12930 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012931 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012932 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012933 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012934 * TODO: This check should be removed if we are 100% sure of
12935 * the base type attribute uses already being built.
12936 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012937 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012938 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012939 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012940 PERROR_INT("xmlSchemaBuildAttributeValidation",
12941 "attribute uses not builded on base type");
12942 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012943 return (0);
12944}
12945
12946/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012947 * xmlSchemaTypeFinalContains:
12948 * @schema: the schema
12949 * @type: the type definition
12950 * @final: the final
12951 *
12952 * Evaluates if a type definition contains the given "final".
12953 * This does take "finalDefault" into account as well.
12954 *
12955 * Returns 1 if the type does containt the given "final",
12956 * 0 otherwise.
12957 */
12958static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012959xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012960{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012961 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012962 return (0);
12963 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012964 return (1);
12965 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012967}
12968
12969/**
12970 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12971 * @type: the Union Simple Type
12972 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012973 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012974 * returns NULL otherwise.
12975 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012976static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012977xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12978{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012979 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012980 if (type->memberTypes != NULL)
12981 return (type->memberTypes);
12982 else
12983 type = type->baseType;
12984 }
12985 return (NULL);
12986}
12987
12988/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012989 * xmlSchemaGetParticleTotalRangeMin:
12990 * @particle: the particle
12991 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012992 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012993 * (all and sequence) + (choice)
12994 *
12995 * Returns the minimun Effective Total Range.
12996 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012997static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012998xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012999{
13000 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013001 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013002 return (0);
13003 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013004 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013005 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013006 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013007
13008 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013009 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013010 while (part != NULL) {
13011 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13012 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013013 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013014 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013015 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013016 if (cur == 0)
13017 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013018 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013019 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013020 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013021 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013022 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013023 } else {
13024 /* <all> and <sequence> */
13025 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013026 xmlSchemaParticlePtr part =
13027 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013028
13029 if (part == NULL)
13030 return (0);
13031 do {
13032 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13033 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013034 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013035 else
13036 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013037 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013038 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013039 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013040 }
13041}
13042
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013043/**
13044 * xmlSchemaGetParticleTotalRangeMax:
13045 * @particle: the particle
13046 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013047 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013048 * (all and sequence) + (choice)
13049 *
13050 * Returns the maximum Effective Total Range.
13051 */
13052static int
13053xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13054{
13055 if ((particle->children == NULL) ||
13056 (particle->children->children == NULL))
13057 return (0);
13058 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13059 int max = -1, cur;
13060 xmlSchemaParticlePtr part =
13061 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013062
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013063 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13064 if (part->children == NULL)
13065 continue;
13066 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13067 (part->children->type == XML_SCHEMA_TYPE_ANY))
13068 cur = part->maxOccurs;
13069 else
13070 cur = xmlSchemaGetParticleTotalRangeMax(part);
13071 if (cur == UNBOUNDED)
13072 return (UNBOUNDED);
13073 if ((max < cur) || (max == -1))
13074 max = cur;
13075 }
13076 /* TODO: Handle overflows? */
13077 return (particle->maxOccurs * max);
13078 } else {
13079 /* <all> and <sequence> */
13080 int sum = 0, cur;
13081 xmlSchemaParticlePtr part =
13082 (xmlSchemaParticlePtr) particle->children->children;
13083
13084 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13085 if (part->children == NULL)
13086 continue;
13087 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13088 (part->children->type == XML_SCHEMA_TYPE_ANY))
13089 cur = part->maxOccurs;
13090 else
13091 cur = xmlSchemaGetParticleTotalRangeMax(part);
13092 if (cur == UNBOUNDED)
13093 return (UNBOUNDED);
13094 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13095 return (UNBOUNDED);
13096 sum += cur;
13097 }
13098 /* TODO: Handle overflows? */
13099 return (particle->maxOccurs * sum);
13100 }
13101}
13102
13103/**
13104 * xmlSchemaIsParticleEmptiable:
13105 * @particle: the particle
13106 *
13107 * Schema Component Constraint: Particle Emptiable
13108 * Checks whether the given particle is emptiable.
13109 *
13110 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013111 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013112static int
13113xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13114{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013115 /*
13116 * SPEC (1) "Its {min occurs} is 0."
13117 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013118 if ((particle == NULL) || (particle->minOccurs == 0) ||
13119 (particle->children == NULL))
13120 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013121 /*
13122 * SPEC (2) "Its {term} is a group and the minimum part of the
13123 * effective total range of that group, [...] is 0."
13124 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013125 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013126 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013127 return (1);
13128 }
13129 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013130}
13131
13132/**
13133 * xmlSchemaCheckCOSSTDerivedOK:
13134 * @type: the derived simple type definition
13135 * @baseType: the base type definition
13136 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013137 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013138 * Type Derivation OK (Simple) (cos-st-derived-OK)
13139 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013140 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013141 * derived from @baseType.
13142 *
13143 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013144 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013145static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013146xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13147 xmlSchemaTypePtr baseType,
13148 int subset)
13149{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013150 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013151 * 1 They are the same type definition.
13152 * TODO: The identy check might have to be more complex than this.
13153 */
13154 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013155 return (0);
13156 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013157 * 2.1 restriction is not in the subset, or in the {final}
13158 * of its own {base type definition};
13159 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013160 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013161 (xmlSchemaTypeFinalContains(type->baseType,
13162 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13163 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013164 }
13165 /* 2.2 */
13166 if (type->baseType == baseType) {
13167 /*
13168 * 2.2.1 D's ·base type definition· is B.
13169 */
13170 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013171 }
13172 /*
13173 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13174 * and is validly derived from B given the subset, as defined by this
13175 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013176 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013177 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013178 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013179 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013180 return (0);
13181 }
13182 /*
13183 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 * definition·.
13185 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013186 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013187 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013188 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013189 }
13190 /*
13191 * 2.2.4 B's {variety} is union and D is validly derived from a type
13192 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013193 * defined by this constraint.
13194 *
13195 * NOTE: This seems not to involve built-in types, since there is no
13196 * built-in Union Simple Type.
13197 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013198 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013199 xmlSchemaTypeLinkPtr cur;
13200
13201 cur = baseType->memberTypes;
13202 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013203 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013204 return (0);
13205 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013206 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013208
Daniel Veillard01fa6152004-06-29 17:04:39 +000013209 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13210}
13211
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013212/**
13213 * xmlSchemaCheckTypeDefCircularInternal:
13214 * @pctxt: the schema parser context
13215 * @ctxtType: the type definition
13216 * @ancestor: an ancestor of @ctxtType
13217 *
13218 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013219 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013220 *
13221 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13222 * circular, 0 otherwise.
13223 */
13224static int
13225xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13226 xmlSchemaTypePtr ctxtType,
13227 xmlSchemaTypePtr ancestor)
13228{
13229 int ret;
13230
13231 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13232 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013233
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013234 if (ctxtType == ancestor) {
13235 xmlSchemaPCustomErr(pctxt,
13236 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13237 NULL, ctxtType, GET_NODE(ctxtType),
13238 "The definition is circular", NULL);
13239 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13240 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013241 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13242 /*
13243 * Avoid inifinite recursion on circular types not yet checked.
13244 */
13245 return (0);
13246 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013247 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13248 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13249 ancestor->baseType);
13250 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13251 return (ret);
13252}
13253
13254/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013255 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013256 * @item: the complex/simple type definition
13257 * @ctxt: the parser context
13258 * @name: the name
13259 *
13260 * Checks for circular type definitions.
13261 */
13262static void
13263xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013264 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013265 const xmlChar * name ATTRIBUTE_UNUSED)
13266{
13267 if ((item == NULL) ||
13268 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13269 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13270 return;
13271 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13272
13273}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013274
13275/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013276 * xmlSchemaResolveTypeDefs:
13277 * @item: the complex/simple type definition
13278 * @ctxt: the parser context
13279 * @name: the name
13280 *
13281 * Checks for circular type definitions.
13282 */
13283static void
13284xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013286 const xmlChar * name ATTRIBUTE_UNUSED)
13287{
13288 if (typeDef == NULL)
13289 return;
13290
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013291 /*
13292 * Resolve the base type.
13293 */
13294 if (typeDef->baseType == NULL) {
13295 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13296 typeDef->base, typeDef->baseNs);
13297 if (typeDef->baseType == NULL) {
13298 xmlSchemaPResCompAttrErr(ctxt,
13299 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013300 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013301 "base", typeDef->base, typeDef->baseNs,
13302 XML_SCHEMA_TYPE_SIMPLE, NULL);
13303 return;
13304 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013305 }
13306 if (IS_SIMPLE_TYPE(typeDef)) {
13307 if (VARIETY_UNION(typeDef)) {
13308 /*
13309 * Resolve the memberTypes.
13310 */
13311 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13312 return;
13313 } else if (VARIETY_LIST(typeDef)) {
13314 /*
13315 * Resolve the itemType.
13316 */
13317 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13318 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13319 typeDef->ref, typeDef->refNs);
13320 if ((typeDef->subtypes == NULL) ||
13321 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13322 typeDef->subtypes = NULL;
13323 xmlSchemaPResCompAttrErr(ctxt,
13324 XML_SCHEMAP_SRC_RESOLVE,
13325 typeDef, typeDef->node,
13326 "itemType", typeDef->ref, typeDef->refNs,
13327 XML_SCHEMA_TYPE_SIMPLE, NULL);
13328 }
13329 }
13330 return;
13331 }
13332 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013333}
13334
13335
13336
13337/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013338 * xmlSchemaCheckSTPropsCorrect:
13339 * @ctxt: the schema parser context
13340 * @type: the simple type definition
13341 *
13342 * Checks st-props-correct.
13343 *
13344 * Returns 0 if the properties are correct,
13345 * if not, a positive error code and -1 on internal
13346 * errors.
13347 */
13348static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013349xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013350 xmlSchemaTypePtr type)
13351{
13352 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13353 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013354 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013355
Daniel Veillardc0826a72004-08-10 14:17:33 +000013356 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013357 /*
13358 * Schema Component Constraint: Simple Type Definition Properties Correct
13359 *
13360 * NOTE: This is somehow redundant, since we actually built a simple type
13361 * to have all the needed information; this acts as an self test.
13362 */
13363 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13364 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013365 /* Base type: If the datatype has been ·derived· by ·restriction·
13366 * then the Simple Type Definition component from which it is ·derived·,
13367 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013368 */
13369 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013370 /*
13371 * TODO: Think about: "modulo the impact of Missing
13372 * Sub-components (§5.3)."
13373 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013374 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013375 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013376 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013377 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013378 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013379
Daniel Veillard01fa6152004-06-29 17:04:39 +000013380 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013381 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013382 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013383 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384 NULL, type, NULL,
13385 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013386 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013387 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013388 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13389 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013390 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13391 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13392 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013393 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013394 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013395 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013396 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013397 "the simple ur-type definition as base type, not '%s'",
13398 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013399 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13401 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013402 /*
13403 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013404 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013405 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13406 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013407 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013408 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013409 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013410 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13412 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013413 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013414
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013415 /*
13416 * 3 The {final} of the {base type definition} must not contain restriction.
13417 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013419 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13420 xmlSchemaPCustomErr(ctxt,
13421 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013422 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013423 "The 'final' of its base type '%s' must not contain "
13424 "'restriction'",
13425 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013426 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013427 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013429
13430 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013431 * 2 All simple type definitions must be derived ultimately from the ·simple
13432 * ur-type definition (so· circular definitions are disallowed). That is, it
13433 * must be possible to reach a built-in primitive datatype or the ·simple
13434 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013435 *
13436 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013438 return (0);
13439}
13440
13441/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013442 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 * @ctxt: the schema parser context
13444 * @type: the simple type definition
13445 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013446 * Schema Component Constraint:
13447 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13448
13449 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013450 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013451 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013453 * a positive error code otherwise.
13454 */
13455static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013456xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013457 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013458{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013459 xmlChar *str = NULL;
13460
Daniel Veillard01fa6152004-06-29 17:04:39 +000013461 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013462 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13463 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013464 return (-1);
13465 }
13466
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013467 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013469 /*
13470 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 */
13473 if (! VARIETY_ATOMIC(type->baseType)) {
13474 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013475 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013477 "The base type '%s' is not an atomic simple type",
13478 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013479 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13481 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013482 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013483 * restriction.
13484 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013485 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013487 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013489 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013491 "The final of its base type '%s' must not contain 'restriction'",
13492 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013493 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013494 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13495 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496
13497 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013498 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013499 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013500 * Primitive datatypes.
13501 */
13502 if (type->facets != NULL) {
13503 xmlSchemaFacetPtr facet;
13504 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 primitive = xmlSchemaGetPrimitiveType(type);
13507 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013508 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13509 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013510 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013512 facet = type->facets;
13513 do {
13514 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013515 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013516 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519 }
13520 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013524 }
13525 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013526 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13527 * of the {base type definition} (call this BF),then the DF's {value}
13528 * must be a valid restriction of BF's {value} as defined in
13529 * [XML Schemas: Datatypes]."
13530 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013531 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013532 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 xmlSchemaTypePtr itemType = NULL;
13536
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013537 itemType = type->subtypes;
13538 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013539 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13540 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013541 return (-1);
13542 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013543 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 * 2.1 The {item type definition} must have a {variety} of atomic or
13547 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 * must be atomic).
13549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013550 if ((! VARIETY_ATOMIC(itemType)) &&
13551 (! VARIETY_UNION(itemType))) {
13552 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013553 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013555 "The item type '%s' does not have a variety of atomic or union",
13556 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013559 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013560 xmlSchemaTypeLinkPtr member;
13561
13562 member = itemType->memberTypes;
13563 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564 if (! VARIETY_ATOMIC(member->type)) {
13565 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013566 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013568 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013569 "member type '%s' of this item type is not atomic",
13570 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013571 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013572 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13573 }
13574 member = member->next;
13575 }
13576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577
13578 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013579 xmlSchemaFacetPtr facet;
13580 /*
13581 * This is the case if we have: <simpleType><list ..
13582 */
13583 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013584 * 2.3.1
13585 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 * contain list.
13587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013588 if (xmlSchemaTypeFinalContains(itemType,
13589 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13590 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013592 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013593 "The final of its item type '%s' must not contain 'list'",
13594 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013595 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013596 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13597 }
13598 /*
13599 * 2.3.1.2 The {facets} must only contain the whiteSpace
13600 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013601 * OPTIMIZE TODO: the S4S already disallows any facet
13602 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013603 */
13604 if (type->facets != NULL) {
13605 facet = type->facets;
13606 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013607 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013608 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013610 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013611 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13612 }
13613 facet = facet->next;
13614 } while (facet != NULL);
13615 }
13616 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 * MAYBE TODO: (Hmm, not really) Datatypes states:
13618 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13619 * whose ·lexical space· allows space (such as string or anyURI)or
13620 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013621 * ·lexical space· allows space.
13622 */
13623 } else {
13624 /*
13625 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013626 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013627 */
13628 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013630 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13631 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013632 if (! VARIETY_LIST(type->baseType)) {
13633 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013634 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013635 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013636 "The base type '%s' must be a list type",
13637 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013639 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13640 }
13641 /*
13642 * 2.3.2.2 The {final} of the {base type definition} must not
13643 * contain restriction.
13644 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013646 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013647 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013648 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013649 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013650 "The 'final' of the base type '%s' must not contain 'restriction'",
13651 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013653 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13654 }
13655 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013656 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013657 * from the {base type definition}'s {item type definition} given
13658 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13659 */
13660 {
13661 xmlSchemaTypePtr baseItemType;
13662
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013663 baseItemType = type->baseType->subtypes;
13664 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013665 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13666 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013667 return (-1);
13668 }
13669 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13671 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013672 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013673 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013674 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013675 NULL, type, NULL,
13676 "The item type '%s' is not validly derived from "
13677 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013678 xmlSchemaGetComponentQName(&str, itemType),
13679 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13680 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013681
13682 FREE_AND_NULL(str)
13683 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013684 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013685 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13686 }
13687 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013688
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 if (type->facets != NULL) {
13690 xmlSchemaFacetPtr facet;
13691 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013692 /*
13693 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 * and enumeration facet components are allowed among the {facets}.
13695 */
13696 facet = type->facets;
13697 do {
13698 switch (facet->type) {
13699 case XML_SCHEMA_FACET_LENGTH:
13700 case XML_SCHEMA_FACET_MINLENGTH:
13701 case XML_SCHEMA_FACET_MAXLENGTH:
13702 case XML_SCHEMA_FACET_WHITESPACE:
13703 /*
13704 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013706 */
13707 case XML_SCHEMA_FACET_PATTERN:
13708 case XML_SCHEMA_FACET_ENUMERATION:
13709 break;
13710 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013713 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013714 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 * invalid facets.
13717 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013718 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013719 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013721 facet = facet->next;
13722 } while (facet != NULL);
13723 if (ok == 0)
13724 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13725 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013726 * SPEC (2.3.2.5) (same as 1.3.2)
13727 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013728 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013729 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013730 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013731 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013733 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013736 * atomic or list.
13737 */
13738 xmlSchemaTypeLinkPtr member;
13739
13740 member = type->memberTypes;
13741 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013742 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013743 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013744
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013745 if ((! VARIETY_ATOMIC(member->type)) &&
13746 (! VARIETY_LIST(member->type))) {
13747 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013749 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013750 "The member type '%s' is neither an atomic, nor a list type",
13751 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013752 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13754 }
13755 member = member->next;
13756 }
13757 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013758 * 3.3.1 If the {base type definition} is the ·simple ur-type
13759 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013761 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013762 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 * {final} which does not contain union.
13765 */
13766 member = type->memberTypes;
13767 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013769 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013770 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013772 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013773 "The 'final' of member type '%s' contains 'union'",
13774 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013775 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13777 }
13778 member = member->next;
13779 }
13780 /*
13781 * 3.3.1.2 The {facets} must be empty.
13782 */
13783 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013784 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013787 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13789 }
13790 } else {
13791 /*
13792 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013793 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795 if (! VARIETY_UNION(type->baseType)) {
13796 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013797 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013798 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013799 "The base type '%s' is not a union type",
13800 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013801 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013802 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13803 }
13804 /*
13805 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13806 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013808 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013809 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013811 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013812 "The 'final' of its base type '%s' must not contain 'restriction'",
13813 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013814 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013815 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13816 }
13817 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013818 * 3.3.2.3 The {member type definitions}, in order, must be validly
13819 * derived from the corresponding type definitions in the {base
13820 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013821 * as defined in Type Derivation OK (Simple) (§3.14.6).
13822 */
13823 {
13824 xmlSchemaTypeLinkPtr baseMember;
13825
13826 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013827 * OPTIMIZE: if the type is restricting, it has no local defined
13828 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013829 * thus a check for equality can be skipped.
13830 */
13831 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013832 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013833 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013834 * types of it's base type. This check seems not necessary with
13835 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013836 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013837 */
13838 if (type->memberTypes != NULL) {
13839 member = type->memberTypes;
13840 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013841 if ((member == NULL) && (baseMember != NULL)) {
13842 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13843 "different number of member types in base");
13844 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013845 while (member != NULL) {
13846 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013847 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13848 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013849 }
13850 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013851 (xmlSchemaCheckCOSSTDerivedOK(
13852 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013853 xmlChar *strBMT = NULL, *strBT = NULL;
13854
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013855 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013856 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13857 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013858 "The member type %s is not validly "
13859 "derived from its corresponding member "
13860 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013861 xmlSchemaGetComponentQName(&str, member->type),
13862 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13863 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013864 FREE_AND_NULL(str)
13865 FREE_AND_NULL(strBMT)
13866 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013867 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013868 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013869 member = member->next;
13870 baseMember = baseMember->next;
13871 }
13872 }
13873 }
13874 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013875 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013878 if (type->facets != NULL) {
13879 xmlSchemaFacetPtr facet;
13880 int ok = 1;
13881
13882 facet = type->facets;
13883 do {
13884 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13885 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013887 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013888 NULL, type, facet);
13889 ok = 0;
13890 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013891 facet = facet->next;
13892 } while (facet != NULL);
13893 if (ok == 0)
13894 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013895
Daniel Veillard01fa6152004-06-29 17:04:39 +000013896 }
13897 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013898 * SPEC (3.3.2.5) (same as 1.3.2)
13899 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013901 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 */
13903 }
13904 }
13905
13906 return (0);
13907}
13908
13909/**
13910 * xmlSchemaCheckSRCSimpleType:
13911 * @ctxt: the schema parser context
13912 * @type: the simple type definition
13913 *
13914 * Checks crc-simple-type constraints.
13915 *
13916 * Returns 0 if the constraints are satisfied,
13917 * if not a positive error code and -1 on internal
13918 * errors.
13919 */
13920static int
13921xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13922 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923{
13924 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013925 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013926 * must satisfy the conditions set out in Constraints on Simple Type
13927 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013928 */
13929 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13930 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13931 /*
13932 * TODO: Removed this, since it got annoying to get an
13933 * extra error report, if anything failed until now.
13934 * Enable this if needed.
13935 */
13936 /*
13937 xmlSchemaPErr(ctxt, type->node,
13938 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013939 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013940 "on simple type definitions.\n",
13941 type->name, NULL);
13942 */
13943 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13944 }
13945
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013946 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013948 * src-simple-type.2 If the <restriction> alternative is chosen,
13949 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013950 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013951 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013952 /*
13953 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013954 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013955 */
13956 } else if (VARIETY_LIST(type)) {
13957 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13958 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013959 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013960 *
13961 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013962 */
13963 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 xmlSchemaTypeLinkPtr member;
13965 xmlSchemaTypePtr ancestor, anySimpleType;
13966
13967 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13970 * the <union> alternative is chosen, there must not be any entries
13971 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013972 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013974 member = type->memberTypes;
13975 while (member != NULL) {
13976 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013977 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013978 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013979 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013980 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013981 NULL, type, NULL,
13982 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013983 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013984 }
13985 if (IS_NOT_TYPEFIXED(ancestor))
13986 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013987 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013988 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013989 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013990 * type as item type, which in turn has a list ST as member
13991 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013992 * was not yet performed.
13993 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013994 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013995
Daniel Veillard01fa6152004-06-29 17:04:39 +000013996 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013997 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013998 member = member->next;
13999 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014000 }
14001
14002 return (0);
14003}
14004
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014005static int
14006xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14007{
14008 if (ctxt->vctxt == NULL) {
14009 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14010 if (ctxt->vctxt == NULL) {
14011 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014012 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014013 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014014 "failed to create a temp. validation context.\n",
14015 NULL, NULL);
14016 return (-1);
14017 }
14018 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014019 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014020 }
14021 return (0);
14022}
14023
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014024static int
14025xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14026 xmlNodePtr node,
14027 xmlSchemaTypePtr type,
14028 const xmlChar *value,
14029 xmlSchemaValPtr *retVal,
14030 int fireErrors,
14031 int normalize,
14032 int isNormalized);
14033
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014034/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014035 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014036 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014037 * @type: the simple type definition
14038 * @value: the default value
14039 * @node: an optional node (the holder of the value)
14040 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041 * Schema Component Constraint: Element Default Valid (Immediate)
14042 * (cos-valid-default)
14043 * This will be used by the parser only. For the validator there's
14044 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014045 *
14046 * Returns 0 if the constraints are satisfied,
14047 * if not, a positive error code and -1 on internal
14048 * errors.
14049 */
14050static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014051xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14052 xmlNodePtr node,
14053 xmlSchemaTypePtr type,
14054 const xmlChar *value,
14055 xmlSchemaValPtr *val)
14056{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014057 int ret = 0;
14058
14059 /*
14060 * cos-valid-default:
14061 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014062 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014063 * definition the appropriate case among the following must be true:
14064 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014065 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014066 /*
14067 * Complex type.
14068 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014069 * SPEC (2.1) "its {content type} must be a simple type definition
14070 * or mixed."
14071 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014072 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014073 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014074 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014075 if ((! HAS_SIMPLE_CONTENT(type)) &&
14076 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14077 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014078 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014079 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014080 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014081 "For a string to be a valid default, the type definition "
14082 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014083 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014084 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14085 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014086 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014087 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014088 * 1 If the type definition is a simple type definition, then the string
14089 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014090 * Valid (§3.14.4).
14091 *
14092 * AND
14093 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014094 * 2.2.1 If the {content type} is a simple type definition, then the
14095 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014096 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014097 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014098 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014099 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14100 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014101 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014102 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14103 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014104 else
14105 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014106
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014107 if (ret < 0) {
14108 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14109 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014110 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014111
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014112 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014113}
14114
14115/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014116 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014117 * @ctxt: the schema parser context
14118 * @type: the complex type definition
14119 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014120 *.(4.6) Constraints on Complex Type Definition Schema Components
14121 * Schema Component Constraint:
14122 * Complex Type Definition Properties Correct (ct-props-correct)
14123 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014124 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014125 * Returns 0 if the constraints are satisfied, a positive
14126 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014127 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014128static int
14129xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14130 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014131{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014132 /*
14133 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14134 *
14135 * SPEC (1) "The values of the properties of a complex type definition must
14136 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014137 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014138 * Sub-components (§5.3)."
14139 */
14140 if ((type->baseType != NULL) &&
14141 (IS_SIMPLE_TYPE(type->baseType)) &&
14142 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14143 /*
14144 * SPEC (2) "If the {base type definition} is a simple type definition,
14145 * the {derivation method} must be extension."
14146 */
14147 xmlSchemaPCustomErr(pctxt,
14148 XML_SCHEMAP_SRC_CT_1,
14149 NULL, type, NULL,
14150 "If the base type is a simple type, the derivation method must be "
14151 "'extension'", NULL);
14152 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014153 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014154 /*
14155 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14156 * definition·. That is, it must be possible to reach the ·ur-type
14157 * definition by repeatedly following the {base type definition}."
14158 *
14159 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14160 *
14161 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014162 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014163 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14164 * must not have {type definition}s which are or are derived from ID."
14165 *
14166 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14167 */
14168 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014169}
14170
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014171static int
14172xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14173 xmlSchemaTypePtr typeB)
14174{
14175 /*
14176 * TODO: This should implement component-identity
14177 * in the future.
14178 */
14179 if ((typeA == NULL) || (typeB == NULL))
14180 return (0);
14181 return (typeA == typeB);
14182}
14183
14184/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014185 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014186 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014187 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014188 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014189 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014190 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014191 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014192 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14193 *
14194 * STATUS: completed
14195 *
14196 * Returns 0 if the constraints are satisfied, or 1
14197 * if not.
14198 */
14199static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014200xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014201 xmlSchemaTypePtr baseType,
14202 int set)
14203{
14204 int equal = xmlSchemaAreEqualTypes(type, baseType);
14205 /* TODO: Error codes. */
14206 /*
14207 * SPEC "For a complex type definition (call it D, for derived)
14208 * to be validly derived from a type definition (call this
14209 * B, for base) given a subset of {extension, restriction}
14210 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014211 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014212 if (! equal) {
14213 /*
14214 * SPEC (1) "If B and D are not the same type definition, then the
14215 * {derivation method} of D must not be in the subset."
14216 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014217 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014218 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014219 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014220 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014221 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014222 } else {
14223 /*
14224 * SPEC (2.1) "B and D must be the same type definition."
14225 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014226 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014227 }
14228 /*
14229 * SPEC (2.2) "B must be D's {base type definition}."
14230 */
14231 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014232 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014233 /*
14234 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14235 * definition·."
14236 */
14237 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014238 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014239
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014240 if (IS_COMPLEX_TYPE(type->baseType)) {
14241 /*
14242 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14243 * must be validly derived from B given the subset as defined by this
14244 * constraint."
14245 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014246 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014247 baseType, set));
14248 } else {
14249 /*
14250 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14251 * must be validly derived from B given the subset as defined in Type
14252 * Derivation OK (Simple) (§3.14.6).
14253 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014254 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14255 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256}
14257
14258/**
14259 * xmlSchemaCheckCOSDerivedOK:
14260 * @type: the derived simple type definition
14261 * @baseType: the base type definition
14262 *
14263 * Calls:
14264 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014265 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014266 * Checks wheter @type can be validly derived from @baseType.
14267 *
14268 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014269 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014270static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014271xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014272 xmlSchemaTypePtr baseType,
14273 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014274{
14275 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014276 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014277 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014278 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014279}
14280
William M. Brack2f2a6632004-08-20 23:09:47 +000014281/**
14282 * xmlSchemaCheckCOSCTExtends:
14283 * @ctxt: the schema parser context
14284 * @type: the complex type definition
14285 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014286 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014287 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014288 * Derivation Valid (Extension) (cos-ct-extends)
14289 *
14290 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014291 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014292 * (1.5)
14293 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014294 *
14295 * Returns 0 if the constraints are satisfied, a positive
14296 * error code if not and -1 if an internal error occured.
14297 */
14298static int
14299xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14300 xmlSchemaTypePtr type)
14301{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014302 xmlSchemaTypePtr base = type->baseType;
14303 /*
14304 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14305 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014306 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014307 /*
14308 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014309 * then all of the following must be true:"
14310 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014311 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14312 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014313 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014314 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014315 */
14316 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14317 xmlSchemaPCustomErr(ctxt,
14318 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14319 NULL, type, NULL,
14320 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014321 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014322 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14323 }
14324 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014325 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014326 * uses}
14327 * of the complex type definition itself, that is, for every attribute
14328 * use in the {attribute uses} of the {base type definition}, there
14329 * must be an attribute use in the {attribute uses} of the complex
14330 * type definition itself whose {attribute declaration} has the same
14331 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014332 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014333 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014334 * NOTE (1.2): This will be already satisfied by the way the attribute
14335 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14336 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014337 */
14338
14339 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014340 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14341 * definition must also have one, and the base type definition's
14342 * {attribute wildcard}'s {namespace constraint} must be a subset
14343 * of the complex type definition's {attribute wildcard}'s {namespace
14344 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014345 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014346 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014347 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014348 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014349 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014350 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014351 if ((type->contentTypeDef != NULL) &&
14352 (type->contentTypeDef == base->contentTypeDef)) {
14353 /*
14354 * SPEC (1.4.1) "The {content type} of the {base type definition}
14355 * and the {content type} of the complex type definition itself
14356 * must be the same simple type definition"
14357 * PASS
14358 */
14359 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14360 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14361 /*
14362 * SPEC (1.4.2) "The {content type} of both the {base type
14363 * definition} and the complex type definition itself must
14364 * be empty."
14365 * PASS
14366 */
14367 } else {
14368 /*
14369 * SPEC (1.4.3) "All of the following must be true:"
14370 */
14371 if (type->subtypes == NULL) {
14372 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014373 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014374 * definition itself must specify a particle.
14375 */
14376 xmlSchemaPCustomErr(ctxt,
14377 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14378 NULL, type, NULL,
14379 "The content type must specify a particle", NULL);
14380 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14381 }
14382 /*
14383 * SPEC (1.4.3.2) "One of the following must be true:"
14384 */
14385 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14386 /*
14387 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14388 * definition} must be empty.
14389 * PASS
14390 */
14391 } else {
14392 /*
14393 * SPEC (1.4.3.2.2) "All of the following must be true:"
14394 */
14395 if ((type->contentType != base->contentType) ||
14396 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14397 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14398 /*
14399 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14400 * or both must be element-only."
14401 */
14402 xmlSchemaPCustomErr(ctxt,
14403 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14404 NULL, type, NULL,
14405 "The content type of both, the type and its base "
14406 "type, must either 'mixed' or 'element-only'", NULL);
14407 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014408 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014409 /*
14410 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14411 * complex type definition must be a ·valid extension·
14412 * of the {base type definition}'s particle, as defined
14413 * in Particle Valid (Extension) (§3.9.6)."
14414 *
14415 * NOTE that we won't check "Particle Valid (Extension)",
14416 * since it is ensured by the derivation process in
14417 * xmlSchemaTypeFixup(). We need to implement this when heading
14418 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014419 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014420 }
14421 /*
14422 * TODO (1.5)
14423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014424 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014425 } else {
14426 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014427 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014428 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014429 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014430 if (type->contentTypeDef != base) {
14431 /*
14432 * SPEC (2.1) "The {content type} must be the same simple type
14433 * definition."
14434 */
14435 xmlSchemaPCustomErr(ctxt,
14436 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14437 NULL, type, NULL,
14438 "The content type must be the simple base type", NULL);
14439 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14440 }
14441 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14442 /*
14443 * SPEC (2.2) "The {final} of the {base type definition} must not
14444 * contain extension"
14445 * NOTE that this is the same as (1.1).
14446 */
14447 xmlSchemaPCustomErr(ctxt,
14448 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14449 NULL, type, NULL,
14450 "The 'final' of the base type definition "
14451 "contains 'extension'", NULL);
14452 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014453 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014454 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014455 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014456}
14457
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014458/**
14459 * xmlSchemaCheckDerivationOKRestriction:
14460 * @ctxt: the schema parser context
14461 * @type: the complex type definition
14462 *
14463 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014464 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014465 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14466 *
14467 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014468 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014469 * (5.4.2), (5.2.2.1)
14470 *
14471 * Returns 0 if the constraints are satisfied, a positive
14472 * error code if not and -1 if an internal error occured.
14473 */
14474static int
14475xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14476 xmlSchemaTypePtr type)
14477{
14478 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014479
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014480 /*
14481 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14482 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014483 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014484 base = type->baseType;
14485 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14486 /*
14487 * SPEC (1) "The {base type definition} must be a complex type
14488 * definition whose {final} does not contain restriction."
14489 */
14490 xmlSchemaPCustomErr(ctxt,
14491 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14492 NULL, type, NULL,
14493 "The 'final' of the base type definition "
14494 "contains 'restriction'", NULL);
14495 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14496 }
14497 /*
14498 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14499 *
14500 * SPEC (5) "One of the following must be true:"
14501 */
14502 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14503 /*
14504 * SPEC (5.1) "The {base type definition} must be the
14505 * ·ur-type definition·."
14506 * PASS
14507 */
14508 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14509 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14510 /*
14511 * SPEC (5.2.1) "The {content type} of the complex type definition
14512 * must be a simple type definition"
14513 *
14514 * SPEC (5.2.2) "One of the following must be true:"
14515 */
14516 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14517 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14518 /*
14519 * SPEC (5.2.2.1) "The {content type} of the {base type
14520 * definition} must be a simple type definition from which
14521 * the {content type} is validly derived given the empty
14522 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14523 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014524 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014525 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14526 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014527 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014528 /*
14529 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14530 * and have a particle which is ·emptiable· as defined in
14531 * Particle Emptiable (§3.9.6)."
14532 * PASS
14533 */
14534 } else {
14535 xmlSchemaPCustomErr(ctxt,
14536 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14537 NULL, type, NULL,
14538 "The content type of the base type must be either "
14539 "a simple type or 'mixed' and an emptiable particle", NULL);
14540 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14541 }
14542 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14543 /*
14544 * SPEC (5.3.1) "The {content type} of the complex type itself must
14545 * be empty"
14546 */
14547 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14548 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014549 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014550 * definition} must also be empty."
14551 * PASS
14552 */
14553 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14554 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14555 xmlSchemaIsParticleEmptiable(
14556 (xmlSchemaParticlePtr) base->subtypes)) {
14557 /*
14558 * SPEC (5.3.2.2) "The {content type} of the {base type
14559 * definition} must be elementOnly or mixed and have a particle
14560 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14561 * PASS
14562 */
14563 } else {
14564 xmlSchemaPCustomErr(ctxt,
14565 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14566 NULL, type, NULL,
14567 "The content type of the base type must be either "
14568 "empty or 'mixed' (or 'elements-only') and an emptiable "
14569 "particle", NULL);
14570 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14571 }
14572 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014573 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014574 /*
14575 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14576 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014577 */
14578 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14579 /*
14580 * SPEC (5.4.1.2) "The {content type} of the complex type
14581 * definition itself and of the {base type definition} must be
14582 * mixed"
14583 */
14584 xmlSchemaPCustomErr(ctxt,
14585 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14586 NULL, type, NULL,
14587 "If the content type is 'mixed', then the content type of the "
14588 "base type must also be 'mixed'", NULL);
14589 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14590 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014591 /*
14592 * SPEC (5.4.2) "The particle of the complex type definition itself
14593 * must be a ·valid restriction· of the particle of the {content
14594 * type} of the {base type definition} as defined in Particle Valid
14595 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014596 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014597 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014598 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014599 } else {
14600 xmlSchemaPCustomErr(ctxt,
14601 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14602 NULL, type, NULL,
14603 "The type is not a valid restriction of its base type", NULL);
14604 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14605 }
14606 return (0);
14607}
14608
14609/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014610 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014611 * @ctxt: the schema parser context
14612 * @type: the complex type definition
14613 *
14614 * (3.4.6) Constraints on Complex Type Definition Schema Components
14615 *
14616 * Returns 0 if the constraints are satisfied, a positive
14617 * error code if not and -1 if an internal error occured.
14618 */
14619static int
14620xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14621 xmlSchemaTypePtr type)
14622{
14623 int ret;
14624 /*
14625 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014626 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014627 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14628 if (ret != 0)
14629 return (ret);
14630 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14631 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14632 else
14633 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14634 return (ret);
14635}
14636
14637/**
14638 * xmlSchemaCheckSRCCT:
14639 * @ctxt: the schema parser context
14640 * @type: the complex type definition
14641 *
14642 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014643 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014644 * Complex Type Definition Representation OK (src-ct)
14645 *
14646 * Returns 0 if the constraints are satisfied, a positive
14647 * error code if not and -1 if an internal error occured.
14648 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014649static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014650xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014651 xmlSchemaTypePtr type)
14652{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014653 xmlSchemaTypePtr base;
14654 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014655
14656 /*
14657 * TODO: Adjust the error codes here, as I used
14658 * XML_SCHEMAP_SRC_CT_1 only yet.
14659 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014660 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014661 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014662 /*
14663 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014664 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014665 * must be a complex type definition;
14666 */
14667 if (! IS_COMPLEX_TYPE(base)) {
14668 xmlChar *str = NULL;
14669 xmlSchemaPCustomErr(ctxt,
14670 XML_SCHEMAP_SRC_CT_1,
14671 NULL, type, type->node,
14672 "If using <complexContent>, the base type is expected to be "
14673 "a complex type. The base type '%s' is a simple type",
14674 xmlSchemaFormatQName(&str, base->targetNamespace,
14675 base->name));
14676 FREE_AND_NULL(str)
14677 return (XML_SCHEMAP_SRC_CT_1);
14678 }
14679 } else {
14680 /*
14681 * SPEC
14682 * 2 If the <simpleContent> alternative is chosen, all of the
14683 * following must be true:
14684 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14685 * base [attribute] must be one of the following:
14686 */
14687 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014688 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014689 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14690 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014691 /*
14692 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014693 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014694 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014695 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014696 xmlSchemaPCustomErr(ctxt,
14697 XML_SCHEMAP_SRC_CT_1,
14698 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014699 "If using <simpleContent> and <restriction>, the base "
14700 "type must be a complex type. The base type '%s' is "
14701 "a simple type",
14702 xmlSchemaFormatQName(&str, base->targetNamespace,
14703 base->name));
14704 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014705 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014706 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014707 } else {
14708 /* Base type is a complex type. */
14709 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14710 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14711 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014712 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014713 * simple type definition;
14714 * PASS
14715 */
14716 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014717 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014718 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014719 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014720 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014721 type->name);
14722 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014723 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014724 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14725 (type->flags &
14726 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014727
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014728 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014729 * 2.1.2 only if the <restriction> alternative is also
14730 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014731 * is mixed and a particle emptiable.
14732 */
14733 if (! xmlSchemaIsParticleEmptiable(
14734 (xmlSchemaParticlePtr) base->subtypes)) {
14735 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014736 } else
14737 /*
14738 * Attention: at this point the <simpleType> child is in
14739 * ->contentTypeDef (put there during parsing).
14740 */
14741 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014742 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014743 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014744 * 2.2 If clause 2.1.2 above is satisfied, then there
14745 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014746 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014747 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014748 /* TODO: Change error code to ..._SRC_CT_2_2. */
14749 xmlSchemaPCustomErr(ctxt,
14750 XML_SCHEMAP_SRC_CT_1,
14751 NULL, type, NULL,
14752 "A <simpleType> is expected among the children "
14753 "of <restriction>, if <simpleContent> is used and "
14754 "the base type '%s' is a complex type",
14755 xmlSchemaFormatQName(&str, base->targetNamespace,
14756 base->name));
14757 FREE_AND_NULL(str)
14758 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014759 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014760 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014761 ret = XML_SCHEMAP_SRC_CT_1;
14762 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014763 }
14764 if (ret > 0) {
14765 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014766 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014767 xmlSchemaPCustomErr(ctxt,
14768 XML_SCHEMAP_SRC_CT_1,
14769 NULL, type, NULL,
14770 "If <simpleContent> and <restriction> is used, the "
14771 "base type must be a simple type or a complex type with "
14772 "mixed content and particle emptiable. The base type "
14773 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014774 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 base->name));
14776 } else {
14777 xmlSchemaPCustomErr(ctxt,
14778 XML_SCHEMAP_SRC_CT_1,
14779 NULL, type, NULL,
14780 "If <simpleContent> and <extension> is used, the "
14781 "base type must be a simple type. The base type '%s' "
14782 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014783 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014784 base->name));
14785 }
14786 FREE_AND_NULL(str)
14787 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014788 }
14789 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014790 * SPEC (3) "The corresponding complex type definition component must
14791 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014792 * Definition Schema Components (§3.4.6);"
14793 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014794 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014795 /*
14796 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014797 * above for {attribute wildcard} is satisfied, the intensional
14798 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014799 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014800 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014801 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014802 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014803}
William M. Brack2f2a6632004-08-20 23:09:47 +000014804
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014805#ifdef ENABLE_PARTICLE_RESTRICTION
14806/**
14807 * xmlSchemaCheckParticleRangeOK:
14808 * @ctxt: the schema parser context
14809 * @type: the complex type definition
14810 *
14811 * (3.9.6) Constraints on Particle Schema Components
14812 * Schema Component Constraint:
14813 * Occurrence Range OK (range-ok)
14814 *
14815 * STATUS: complete
14816 *
14817 * Returns 0 if the constraints are satisfied, a positive
14818 * error code if not and -1 if an internal error occured.
14819 */
14820static int
14821xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14822 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014823{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014824 if (rmin < bmin)
14825 return (1);
14826 if ((bmax != UNBOUNDED) &&
14827 (rmax > bmax))
14828 return (1);
14829 return (0);
14830}
14831
14832/**
14833 * xmlSchemaCheckRCaseNameAndTypeOK:
14834 * @ctxt: the schema parser context
14835 * @r: the restricting element declaration particle
14836 * @b: the base element declaration particle
14837 *
14838 * (3.9.6) Constraints on Particle Schema Components
14839 * Schema Component Constraint:
14840 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14841 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014842 *
14843 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014844 * MISSING (3.2.3)
14845 * CLARIFY: (3.2.2)
14846 *
14847 * Returns 0 if the constraints are satisfied, a positive
14848 * error code if not and -1 if an internal error occured.
14849 */
14850static int
14851xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14852 xmlSchemaParticlePtr r,
14853 xmlSchemaParticlePtr b)
14854{
14855 xmlSchemaElementPtr elemR, elemB;
14856
14857 /* TODO: Error codes (rcase-NameAndTypeOK). */
14858 elemR = (xmlSchemaElementPtr) r->children;
14859 elemB = (xmlSchemaElementPtr) b->children;
14860 /*
14861 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14862 * the same."
14863 */
14864 if ((elemR != elemB) &&
14865 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14866 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14867 return (1);
14868 /*
14869 * SPEC (2) "R's occurrence range is a valid restriction of B's
14870 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14871 */
14872 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14873 b->minOccurs, b->maxOccurs) != 0)
14874 return (1);
14875 /*
14876 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14877 * {scope} are global."
14878 */
14879 if (elemR == elemB)
14880 return (0);
14881 /*
14882 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14883 */
14884 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14885 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14886 return (1);
14887 /*
14888 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14889 * or is not fixed, or R's declaration's {value constraint} is fixed
14890 * with the same value."
14891 */
14892 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14893 ((elemR->value == NULL) ||
14894 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14895 /* TODO: Equality of the initial value or normalized or canonical? */
14896 (! xmlStrEqual(elemR->value, elemB->value))))
14897 return (1);
14898 /*
14899 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14900 * definitions} is a subset of B's declaration's {identity-constraint
14901 * definitions}, if any."
14902 */
14903 if (elemB->idcs != NULL) {
14904 /* TODO */
14905 }
14906 /*
14907 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14908 * superset of B's declaration's {disallowed substitutions}."
14909 */
14910 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14911 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14912 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14913 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14914 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14915 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14916 return (1);
14917 /*
14918 * SPEC (3.2.5) "R's {type definition} is validly derived given
14919 * {extension, list, union} from B's {type definition}"
14920 *
14921 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14922 * set, if the corresponding constraints handle "restriction" and
14923 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014924 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014925 */
14926 {
14927 int set = 0;
14928
14929 set |= SUBSET_EXTENSION;
14930 set |= SUBSET_LIST;
14931 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014932 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014933 elemB->subtypes, set) != 0)
14934 return (1);
14935 }
14936 return (0);
14937}
14938
14939/**
14940 * xmlSchemaCheckRCaseNSCompat:
14941 * @ctxt: the schema parser context
14942 * @r: the restricting element declaration particle
14943 * @b: the base wildcard particle
14944 *
14945 * (3.9.6) Constraints on Particle Schema Components
14946 * Schema Component Constraint:
14947 * Particle Derivation OK (Elt:Any -- NSCompat)
14948 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014949 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014950 * STATUS: complete
14951 *
14952 * Returns 0 if the constraints are satisfied, a positive
14953 * error code if not and -1 if an internal error occured.
14954 */
14955static int
14956xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14957 xmlSchemaParticlePtr r,
14958 xmlSchemaParticlePtr b)
14959{
14960 /* TODO:Error codes (rcase-NSCompat). */
14961 /*
14962 * SPEC "For an element declaration particle to be a ·valid restriction·
14963 * of a wildcard particle all of the following must be true:"
14964 *
14965 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14966 * with respect to the wildcard's {namespace constraint} as defined by
14967 * Wildcard allows Namespace Name (§3.10.4)."
14968 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014969 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014970 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14971 return (1);
14972 /*
14973 * SPEC (2) "R's occurrence range is a valid restriction of B's
14974 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14975 */
14976 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14977 b->minOccurs, b->maxOccurs) != 0)
14978 return (1);
14979
14980 return (0);
14981}
14982
14983/**
14984 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14985 * @ctxt: the schema parser context
14986 * @r: the restricting element declaration particle
14987 * @b: the base model group particle
14988 *
14989 * (3.9.6) Constraints on Particle Schema Components
14990 * Schema Component Constraint:
14991 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14992 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014993 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014994 * STATUS: TODO
14995 *
14996 * Returns 0 if the constraints are satisfied, a positive
14997 * error code if not and -1 if an internal error occured.
14998 */
14999static int
15000xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15001 xmlSchemaParticlePtr r,
15002 xmlSchemaParticlePtr b)
15003{
15004 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15005 TODO
15006 return (0);
15007}
15008
15009/**
15010 * xmlSchemaCheckRCaseNSSubset:
15011 * @ctxt: the schema parser context
15012 * @r: the restricting wildcard particle
15013 * @b: the base wildcard particle
15014 *
15015 * (3.9.6) Constraints on Particle Schema Components
15016 * Schema Component Constraint:
15017 * Particle Derivation OK (Any:Any -- NSSubset)
15018 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015019 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015020 * STATUS: complete
15021 *
15022 * Returns 0 if the constraints are satisfied, a positive
15023 * error code if not and -1 if an internal error occured.
15024 */
15025static int
15026xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15027 xmlSchemaParticlePtr r,
15028 xmlSchemaParticlePtr b,
15029 int isAnyTypeBase)
15030{
15031 /* TODO: Error codes (rcase-NSSubset). */
15032 /*
15033 * SPEC (1) "R's occurrence range is a valid restriction of B's
15034 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15035 */
15036 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15037 b->minOccurs, b->maxOccurs))
15038 return (1);
15039 /*
15040 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15041 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15042 */
15043 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15044 (xmlSchemaWildcardPtr) b->children))
15045 return (1);
15046 /*
15047 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15048 * definition·, R's {process contents} must be identical to or stronger
15049 * than B's {process contents}, where strict is stronger than lax is
15050 * stronger than skip."
15051 */
15052 if (! isAnyTypeBase) {
15053 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15054 ((xmlSchemaWildcardPtr) b->children)->processContents)
15055 return (1);
15056 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015057
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015058 return (0);
15059}
15060
15061/**
15062 * xmlSchemaCheckCOSParticleRestrict:
15063 * @ctxt: the schema parser context
15064 * @type: the complex type definition
15065 *
15066 * (3.9.6) Constraints on Particle Schema Components
15067 * Schema Component Constraint:
15068 * Particle Valid (Restriction) (cos-particle-restrict)
15069 *
15070 * STATUS: TODO
15071 *
15072 * Returns 0 if the constraints are satisfied, a positive
15073 * error code if not and -1 if an internal error occured.
15074 */
15075static int
15076xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15077 xmlSchemaParticlePtr r,
15078 xmlSchemaParticlePtr b)
15079{
15080 int ret = 0;
15081
15082 /*part = GET_PARTICLE(type);
15083 basePart = GET_PARTICLE(base);
15084 */
15085
15086 TODO
15087
15088 /*
15089 * SPEC (1) "They are the same particle."
15090 */
15091 if (r == b)
15092 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015093
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015094
15095 return (0);
15096}
15097
15098/**
15099 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15100 * @ctxt: the schema parser context
15101 * @r: the model group particle
15102 * @b: the base wildcard particle
15103 *
15104 * (3.9.6) Constraints on Particle Schema Components
15105 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015106 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015107 * NSRecurseCheckCardinality)
15108 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015109 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015110 * STATUS: TODO: subst-groups
15111 *
15112 * Returns 0 if the constraints are satisfied, a positive
15113 * error code if not and -1 if an internal error occured.
15114 */
15115static int
15116xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15117 xmlSchemaParticlePtr r,
15118 xmlSchemaParticlePtr b)
15119{
15120 xmlSchemaParticlePtr part;
15121 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15122 if ((r->children == NULL) || (r->children->children == NULL))
15123 return (-1);
15124 /*
15125 * SPEC "For a group particle to be a ·valid restriction· of a
15126 * wildcard particle..."
15127 *
15128 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015130 * Particle Valid (Restriction) (§3.9.6)."
15131 */
15132 part = (xmlSchemaParticlePtr) r->children->children;
15133 do {
15134 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15135 return (1);
15136 part = (xmlSchemaParticlePtr) part->next;
15137 } while (part != NULL);
15138 /*
15139 * SPEC (2) "The effective total range of the group [...] is a
15140 * valid restriction of B's occurrence range as defined by
15141 * Occurrence Range OK (§3.9.6)."
15142 */
15143 if (xmlSchemaCheckParticleRangeOK(
15144 xmlSchemaGetParticleTotalRangeMin(r),
15145 xmlSchemaGetParticleTotalRangeMax(r),
15146 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015147 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015148 return (0);
15149}
15150
15151/**
15152 * xmlSchemaCheckRCaseRecurse:
15153 * @ctxt: the schema parser context
15154 * @r: the <all> or <sequence> model group particle
15155 * @b: the base <all> or <sequence> model group particle
15156 *
15157 * (3.9.6) Constraints on Particle Schema Components
15158 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015159 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015160 Recurse)
15161 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015162 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015163 * STATUS: ?
15164 * TODO: subst-groups
15165 *
15166 * Returns 0 if the constraints are satisfied, a positive
15167 * error code if not and -1 if an internal error occured.
15168 */
15169static int
15170xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15171 xmlSchemaParticlePtr r,
15172 xmlSchemaParticlePtr b)
15173{
15174 /* xmlSchemaParticlePtr part; */
15175 /* TODO: Error codes (rcase-Recurse). */
15176 if ((r->children == NULL) || (b->children == NULL) ||
15177 (r->children->type != b->children->type))
15178 return (-1);
15179 /*
15180 * SPEC "For an all or sequence group particle to be a ·valid
15181 * restriction· of another group particle with the same {compositor}..."
15182 *
15183 * SPEC (1) "R's occurrence range is a valid restriction of B's
15184 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15185 */
15186 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15187 b->minOccurs, b->maxOccurs))
15188 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015189
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015190
15191 return (0);
15192}
15193
15194#endif
15195
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015196#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15197 xmlSchemaPCustomErrExt(pctxt, \
15198 XML_SCHEMAP_INVALID_FACET_VALUE, \
15199 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15200 "It is an error for both '%s' and '%s' to be specified on the "\
15201 "same type definition", \
15202 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15203 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15204
15205#define FACET_RESTR_ERR(fac1, msg) \
15206 xmlSchemaPCustomErr(pctxt, \
15207 XML_SCHEMAP_INVALID_FACET_VALUE, \
15208 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015209 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015210
15211#define FACET_RESTR_FIXED_ERR(fac) \
15212 xmlSchemaPCustomErr(pctxt, \
15213 XML_SCHEMAP_INVALID_FACET_VALUE, \
15214 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15215 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015216 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015217
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015218static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015219xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15220 xmlSchemaFacetPtr facet1,
15221 xmlSchemaFacetPtr facet2,
15222 int lessGreater,
15223 int orEqual,
15224 int ofBase)
15225{
15226 xmlChar *msg = NULL;
15227
15228 msg = xmlStrdup(BAD_CAST "'");
15229 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15230 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15231 if (lessGreater == 0)
15232 msg = xmlStrcat(msg, BAD_CAST " equal to");
15233 if (lessGreater == 1)
15234 msg = xmlStrcat(msg, BAD_CAST " greater than");
15235 else
15236 msg = xmlStrcat(msg, BAD_CAST " less than");
15237
15238 if (orEqual)
15239 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15240 msg = xmlStrcat(msg, BAD_CAST " '");
15241 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15242 if (ofBase)
15243 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15244 else
15245 msg = xmlStrcat(msg, BAD_CAST "'");
15246
15247 xmlSchemaPCustomErr(pctxt,
15248 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015249 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015250 (const char *) msg, NULL);
15251
15252 if (msg != NULL)
15253 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015254}
15255
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015256static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015257xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15258 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015259{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015260 xmlSchemaTypePtr base = type->baseType;
15261 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015262 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015263 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15264 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15265 fmininc = NULL, fmaxinc = NULL,
15266 fminexc = NULL, fmaxexc = NULL,
15267 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15268 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15269 bfmininc = NULL, bfmaxinc = NULL,
15270 bfminexc = NULL, bfmaxexc = NULL;
15271 int res, err = 0, fixedErr;
15272 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015273 * 3 The {facets} of R are the union of S and the {facets}
15274 * of B, eliminating duplicates. To eliminate duplicates,
15275 * when a facet of the same kind occurs in both S and the
15276 * {facets} of B, the one in the {facets} of B is not
15277 * included, with the exception of enumeration and pattern
15278 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015279 * are allowed.
15280 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015281
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015282 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15283 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015284
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285 last = type->facetSet;
15286 if (last != NULL)
15287 while (last->next != NULL)
15288 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015289
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015290 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15291 facet = cur->facet;
15292 switch (facet->type) {
15293 case XML_SCHEMA_FACET_LENGTH:
15294 flength = facet; break;
15295 case XML_SCHEMA_FACET_MINLENGTH:
15296 fminlen = facet; break;
15297 case XML_SCHEMA_FACET_MININCLUSIVE:
15298 fmininc = facet; break;
15299 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15300 fminexc = facet; break;
15301 case XML_SCHEMA_FACET_MAXLENGTH:
15302 fmaxlen = facet; break;
15303 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15304 fmaxinc = facet; break;
15305 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15306 fmaxexc = facet; break;
15307 case XML_SCHEMA_FACET_TOTALDIGITS:
15308 ftotdig = facet; break;
15309 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15310 ffracdig = facet; break;
15311 default:
15312 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015313 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015314 }
15315 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15316 facet = cur->facet;
15317 switch (facet->type) {
15318 case XML_SCHEMA_FACET_LENGTH:
15319 bflength = facet; break;
15320 case XML_SCHEMA_FACET_MINLENGTH:
15321 bfminlen = facet; break;
15322 case XML_SCHEMA_FACET_MININCLUSIVE:
15323 bfmininc = facet; break;
15324 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15325 bfminexc = facet; break;
15326 case XML_SCHEMA_FACET_MAXLENGTH:
15327 bfmaxlen = facet; break;
15328 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15329 bfmaxinc = facet; break;
15330 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15331 bfmaxexc = facet; break;
15332 case XML_SCHEMA_FACET_TOTALDIGITS:
15333 bftotdig = facet; break;
15334 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15335 bffracdig = facet; break;
15336 default:
15337 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015338 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015339 }
15340 err = 0;
15341 /*
15342 * length and minLength or maxLength (2.2) + (3.2)
15343 */
15344 if (flength && (fminlen || fmaxlen)) {
15345 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15346 "either of 'minLength' or 'maxLength' to be specified on "
15347 "the same type definition")
15348 }
15349 /*
15350 * Mutual exclusions in the same derivation step.
15351 */
15352 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015353 /*
15354 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015355 */
15356 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15357 }
15358 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015359 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015360 * SCC "minInclusive and minExclusive"
15361 */
15362 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015363 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015364
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015365 if (flength && bflength) {
15366 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015367 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015368 * The values have to be equal.
15369 */
15370 res = xmlSchemaCompareValues(flength->val, bflength->val);
15371 if (res == -2)
15372 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015373 if (res != 0)
15374 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15375 if ((res != 0) && (bflength->fixed)) {
15376 FACET_RESTR_FIXED_ERR(flength)
15377 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015378
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015379 }
15380 if (fminlen && bfminlen) {
15381 /*
15382 * SCC "minLength valid restriction"
15383 * minLength >= BASE minLength
15384 */
15385 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15386 if (res == -2)
15387 goto internal_error;
15388 if (res == -1)
15389 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15390 if ((res != 0) && (bfminlen->fixed)) {
15391 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015392 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015393 }
15394 if (fmaxlen && bfmaxlen) {
15395 /*
15396 * SCC "maxLength valid restriction"
15397 * maxLength <= BASE minLength
15398 */
15399 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15400 if (res == -2)
15401 goto internal_error;
15402 if (res == 1)
15403 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15404 if ((res != 0) && (bfmaxlen->fixed)) {
15405 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015406 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015407 }
15408 /*
15409 * SCC "length and minLength or maxLength"
15410 */
15411 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015412 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015413 if (flength) {
15414 if (! fminlen)
15415 flength = bflength;
15416 if (fminlen) {
15417 /* (1.1) length >= minLength */
15418 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15419 if (res == -2)
15420 goto internal_error;
15421 if (res == -1)
15422 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15423 }
15424 if (! fmaxlen)
15425 fmaxlen = bfmaxlen;
15426 if (fmaxlen) {
15427 /* (2.1) length <= maxLength */
15428 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15429 if (res == -2)
15430 goto internal_error;
15431 if (res == 1)
15432 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15433 }
15434 }
15435 if (fmaxinc) {
15436 /*
15437 * "maxInclusive"
15438 */
15439 if (fmininc) {
15440 /* SCC "maxInclusive >= minInclusive" */
15441 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15442 if (res == -2)
15443 goto internal_error;
15444 if (res == -1) {
15445 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15446 }
15447 }
15448 /*
15449 * SCC "maxInclusive valid restriction"
15450 */
15451 if (bfmaxinc) {
15452 /* maxInclusive <= BASE maxInclusive */
15453 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15454 if (res == -2)
15455 goto internal_error;
15456 if (res == 1)
15457 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15458 if ((res != 0) && (bfmaxinc->fixed)) {
15459 FACET_RESTR_FIXED_ERR(fmaxinc)
15460 }
15461 }
15462 if (bfmaxexc) {
15463 /* maxInclusive < BASE maxExclusive */
15464 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15465 if (res == -2)
15466 goto internal_error;
15467 if (res != -1) {
15468 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15469 }
15470 }
15471 if (bfmininc) {
15472 /* maxInclusive >= BASE minInclusive */
15473 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15474 if (res == -2)
15475 goto internal_error;
15476 if (res == -1) {
15477 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15478 }
15479 }
15480 if (bfminexc) {
15481 /* maxInclusive > BASE minExclusive */
15482 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15483 if (res == -2)
15484 goto internal_error;
15485 if (res != 1) {
15486 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15487 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015488 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015489 }
15490 if (fmaxexc) {
15491 /*
15492 * "maxExclusive >= minExclusive"
15493 */
15494 if (fminexc) {
15495 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15496 if (res == -2)
15497 goto internal_error;
15498 if (res == -1) {
15499 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15500 }
15501 }
15502 /*
15503 * "maxExclusive valid restriction"
15504 */
15505 if (bfmaxexc) {
15506 /* maxExclusive <= BASE maxExclusive */
15507 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15508 if (res == -2)
15509 goto internal_error;
15510 if (res == 1) {
15511 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15512 }
15513 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015514 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015515 }
15516 }
15517 if (bfmaxinc) {
15518 /* maxExclusive <= BASE maxInclusive */
15519 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15520 if (res == -2)
15521 goto internal_error;
15522 if (res == 1) {
15523 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15524 }
15525 }
15526 if (bfmininc) {
15527 /* maxExclusive > BASE minInclusive */
15528 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15529 if (res == -2)
15530 goto internal_error;
15531 if (res != 1) {
15532 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15533 }
15534 }
15535 if (bfminexc) {
15536 /* maxExclusive > BASE minExclusive */
15537 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15538 if (res == -2)
15539 goto internal_error;
15540 if (res != 1) {
15541 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15542 }
15543 }
15544 }
15545 if (fminexc) {
15546 /*
15547 * "minExclusive < maxInclusive"
15548 */
15549 if (fmaxinc) {
15550 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15551 if (res == -2)
15552 goto internal_error;
15553 if (res != -1) {
15554 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15555 }
15556 }
15557 /*
15558 * "minExclusive valid restriction"
15559 */
15560 if (bfminexc) {
15561 /* minExclusive >= BASE minExclusive */
15562 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15563 if (res == -2)
15564 goto internal_error;
15565 if (res == -1) {
15566 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15567 }
15568 if ((res != 0) && (bfminexc->fixed)) {
15569 FACET_RESTR_FIXED_ERR(fminexc)
15570 }
15571 }
15572 if (bfmaxinc) {
15573 /* minExclusive <= BASE maxInclusive */
15574 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15575 if (res == -2)
15576 goto internal_error;
15577 if (res == 1) {
15578 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15579 }
15580 }
15581 if (bfmininc) {
15582 /* minExclusive >= BASE minInclusive */
15583 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15584 if (res == -2)
15585 goto internal_error;
15586 if (res == -1) {
15587 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15588 }
15589 }
15590 if (bfmaxexc) {
15591 /* minExclusive < BASE maxExclusive */
15592 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15593 if (res == -2)
15594 goto internal_error;
15595 if (res != -1) {
15596 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15597 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015598 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015599 }
15600 if (fmininc) {
15601 /*
15602 * "minInclusive < maxExclusive"
15603 */
15604 if (fmaxexc) {
15605 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15606 if (res == -2)
15607 goto internal_error;
15608 if (res != -1) {
15609 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15610 }
15611 }
15612 /*
15613 * "minExclusive valid restriction"
15614 */
15615 if (bfmininc) {
15616 /* minInclusive >= BASE minInclusive */
15617 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15618 if (res == -2)
15619 goto internal_error;
15620 if (res == -1) {
15621 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15622 }
15623 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015624 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015625 }
15626 }
15627 if (bfmaxinc) {
15628 /* minInclusive <= BASE maxInclusive */
15629 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15630 if (res == -2)
15631 goto internal_error;
15632 if (res == -1) {
15633 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15634 }
15635 }
15636 if (bfminexc) {
15637 /* minInclusive > BASE minExclusive */
15638 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15639 if (res == -2)
15640 goto internal_error;
15641 if (res != 1)
15642 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15643 }
15644 if (bfmaxexc) {
15645 /* minInclusive < BASE maxExclusive */
15646 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15647 if (res == -2)
15648 goto internal_error;
15649 if (res != -1)
15650 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15651 }
15652 }
15653 if (ftotdig && bftotdig) {
15654 /*
15655 * SCC " totalDigits valid restriction"
15656 * totalDigits <= BASE totalDigits
15657 */
15658 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15659 if (res == -2)
15660 goto internal_error;
15661 if (res == 1)
15662 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15663 -1, 1, 1);
15664 if ((res != 0) && (bftotdig->fixed)) {
15665 FACET_RESTR_FIXED_ERR(ftotdig)
15666 }
15667 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015668 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015669 /*
15670 * SCC "fractionDigits valid restriction"
15671 * fractionDigits <= BASE fractionDigits
15672 */
15673 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15674 if (res == -2)
15675 goto internal_error;
15676 if (res == 1)
15677 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15678 -1, 1, 1);
15679 if ((res != 0) && (bffracdig->fixed)) {
15680 FACET_RESTR_FIXED_ERR(ffracdig)
15681 }
15682 }
15683 /*
15684 * SCC "fractionDigits less than or equal to totalDigits"
15685 */
15686 if (! ftotdig)
15687 ftotdig = bftotdig;
15688 if (! ffracdig)
15689 ffracdig = bffracdig;
15690 if (ftotdig && ffracdig) {
15691 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15692 if (res == -2)
15693 goto internal_error;
15694 if (res == 1)
15695 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15696 -1, 1, 0);
15697 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015698 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015699 * *Enumerations* won' be added here, since only the first set
15700 * of enumerations in the ancestor-or-self axis is used
15701 * for validation, plus we need to use the base type of those
15702 * enumerations for whitespace.
15703 *
15704 * *Patterns*: won't be add here, since they are ORed at
15705 * type level and ANDed at ancestor level. This will
15706 * happed during validation by walking the base axis
15707 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015708 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015709 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15710 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015711 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015712 * Special handling of enumerations and patterns.
15713 * TODO: hmm, they should not appear in the set, so remove this.
15714 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015715 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015716 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015717 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015718 /*
15719 * Search for a duplicate facet in the current type.
15720 */
15721 link = type->facetSet;
15722 err = 0;
15723 fixedErr = 0;
15724 while (link != NULL) {
15725 facet = link->facet;
15726 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015727 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015728 case XML_SCHEMA_FACET_WHITESPACE:
15729 /*
15730 * The whitespace must be stronger.
15731 */
15732 if (facet->whitespace < bfacet->whitespace) {
15733 FACET_RESTR_ERR(flength,
15734 "The 'whitespace' value has to be equal to "
15735 "or stronger than the 'whitespace' value of "
15736 "the base type")
15737 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015738 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015739 (facet->whitespace != bfacet->whitespace)) {
15740 FACET_RESTR_FIXED_ERR(facet)
15741 }
15742 break;
15743 default:
15744 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015745 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746 /* Duplicate found. */
15747 break;
15748 }
15749 link = link->next;
15750 }
15751 /*
15752 * If no duplicate was found: add the base types's facet
15753 * to the set.
15754 */
15755 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015756 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015757 xmlMalloc(sizeof(xmlSchemaFacetLink));
15758 if (link == NULL) {
15759 xmlSchemaPErrMemory(pctxt,
15760 "deriving facets, creating a facet link", NULL);
15761 return (-1);
15762 }
15763 link->facet = cur->facet;
15764 link->next = NULL;
15765 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015766 type->facetSet = link;
15767 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015768 last->next = link;
15769 last = link;
15770 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015771
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015772 }
15773
15774 return (0);
15775internal_error:
15776 xmlSchemaPCustomErr(pctxt,
15777 XML_SCHEMAP_INVALID_FACET_VALUE,
15778 NULL, type, NULL,
15779 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15780 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015781}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015782
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015783static int
15784xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15785 xmlSchemaTypePtr type)
15786{
15787 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15788 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 * The actual value is then formed by replacing any union type
15790 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015791 * {member type definitions}, in order.
15792 */
15793 link = type->memberTypes;
15794 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015795
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015796 if (IS_NOT_TYPEFIXED(link->type))
15797 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15798
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015799 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015800 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015801 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015802 link->type = subLink->type;
15803 if (subLink->next != NULL) {
15804 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015805 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015806 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015807 while (subLink != NULL) {
15808 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015809 xmlMalloc(sizeof(xmlSchemaTypeLink));
15810 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015811 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015812 NULL);
15813 return (-1);
15814 }
15815 newLink->type = subLink->type;
15816 prevLink->next = newLink;
15817 prevLink = newLink;
15818 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015819
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015820 subLink = subLink->next;
15821 }
15822 }
15823 }
15824 }
15825 link = link->next;
15826 }
15827 return (0);
15828}
15829
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015830static void
15831xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15832{
15833 int has = 0, needVal = 0, normVal = 0;
15834
15835 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15836 if (has) {
15837 needVal = (type->baseType->flags &
15838 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15839 normVal = (type->baseType->flags &
15840 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15841 }
15842 if (type->facets != NULL) {
15843 xmlSchemaFacetPtr fac;
15844
15845 for (fac = type->facets; fac != NULL; fac = fac->next) {
15846 switch (fac->type) {
15847 case XML_SCHEMA_FACET_WHITESPACE:
15848 break;
15849 case XML_SCHEMA_FACET_PATTERN:
15850 normVal = 1;
15851 has = 1;
15852 break;
15853 case XML_SCHEMA_FACET_ENUMERATION:
15854 needVal = 1;
15855 normVal = 1;
15856 has = 1;
15857 break;
15858 default:
15859 has = 1;
15860 break;
15861 }
15862 }
15863 }
15864 if (normVal)
15865 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15866 if (needVal)
15867 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15868 if (has)
15869 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15870
15871 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15872 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15873 /*
15874 * OPTIMIZE VAL TODO: Some facets need a computed value.
15875 */
15876 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15877 (prim->builtInType != XML_SCHEMAS_STRING)) {
15878 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15879 }
15880 }
15881}
15882
15883static int
15884xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15885{
15886
15887
15888 /*
15889 * Evaluate the whitespace-facet value.
15890 */
15891 if (VARIETY_LIST(type)) {
15892 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15893 return (0);
15894 } else if (VARIETY_UNION(type))
15895 return (0);
15896
15897 if (type->facetSet != NULL) {
15898 xmlSchemaFacetLinkPtr lin;
15899
15900 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15901 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15902 switch (lin->facet->whitespace) {
15903 case XML_SCHEMAS_FACET_PRESERVE:
15904 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15905 break;
15906 case XML_SCHEMAS_FACET_REPLACE:
15907 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15908 break;
15909 case XML_SCHEMAS_FACET_COLLAPSE:
15910 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15911 break;
15912 default:
15913 return (-1);
15914 }
15915 return (0);
15916 }
15917 }
15918 }
15919 /*
15920 * For all ·atomic· datatypes other than string (and types ·derived·
15921 * by ·restriction· from it) the value of whiteSpace is fixed to
15922 * collapse
15923 */
15924 {
15925 xmlSchemaTypePtr anc;
15926
15927 for (anc = type->baseType; anc != NULL &&
15928 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15929 anc = anc->baseType) {
15930
15931 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15932 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15933 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15934
15935 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15936 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15937 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15938
15939 } else
15940 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15941 break;
15942 }
15943 }
15944 return (0);
15945 }
15946 return (0);
15947}
15948
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015949/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015950 * xmlSchemaTypeFixup:
15951 * @typeDecl: the schema type definition
15952 * @ctxt: the schema parser context
15953 *
15954 * Fixes the content model of the type.
15955 */
15956static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015957xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015958 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015959{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015960 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015961 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015962 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15963 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015964 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 if (! IS_NOT_TYPEFIXED(type))
15966 return;
15967 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015968 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015969 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015970
15971 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015972 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015973 XML_SCHEMAP_INTERNAL,
15974 NULL, type, NULL,
15975 "Internal error: xmlSchemaTypeFixup, "
15976 "baseType is missing on '%s'", type->name);
15977 return;
15978 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015979
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015980 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015981 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015983 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015984 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015985 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015986 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015987 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015988 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15989 /*
15990 * Skip fixup if the base type is invalid.
15991 * TODO: Generate a warning!
15992 */
15993 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015994 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015995 /*
15996 * This basically checks if the base type can be derived.
15997 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015998 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015999 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16000 return;
16001 }
16002 /*
16003 * Fixup the content type.
16004 */
16005 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16006 /*
16007 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016008 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016009 if ((IS_COMPLEX_TYPE(baseType)) &&
16010 (baseType->contentTypeDef != NULL) &&
16011 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016012 xmlSchemaTypePtr contentBase, content;
16013 char buf[30];
16014 const xmlChar *tmpname;
16015 /*
16016 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016017 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016018 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016019 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016020 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016021 * SPEC (1.1) "the simple type definition corresponding to the
16022 * <simpleType> among the [children] of <restriction> if there
16023 * is one;"
16024 * Note that this "<simpleType> among the [children]" was put
16025 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016026 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016027 contentBase = type->contentTypeDef;
16028 type->contentTypeDef = NULL;
16029 } else {
16030 /*
16031 * (1.2) "...otherwise (<restriction> has no <simpleType>
16032 * among its [children]), the simple type definition which
16033 * is the {content type} of the ... base type."
16034 */
16035 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016036 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016037 /*
16038 * SPEC
16039 * "... a simple type definition which restricts the simple
16040 * type definition identified in clause 1.1 or clause 1.2
16041 * with a set of facet components"
16042 *
16043 * Create the anonymous simple type, which will be the content
16044 * type of the complex type.
16045 */
16046 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16047 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16048 content = xmlSchemaAddType(pctxt,
16049 pctxt->schema, tmpname, tmpname, type->node);
16050 if (content == NULL)
16051 return;
16052 /*
16053 * We will use the same node as for the <complexType>
16054 * to have it somehow anchored in the schema doc.
16055 */
16056 content->node = type->node;
16057 content->type = XML_SCHEMA_TYPE_SIMPLE;
16058 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16059 content->baseType = contentBase;
16060 /*
16061 * Move the facets, previously anchored on the complexType.
16062 */
16063 content->facets = type->facets;
16064 type->facets = NULL;
16065 content->facetSet = type->facetSet;
16066 type->facetSet = NULL;
16067
16068 type->contentTypeDef = content;
16069 if (IS_NOT_TYPEFIXED(contentBase))
16070 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16071 xmlSchemaTypeFixup(content, pctxt, NULL);
16072
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016073 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16074 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16075 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16076 /*
16077 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16078 * an emptiable particle, then a simple type definition which
16079 * restricts the <restriction>'s <simpleType> child.
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 (type->contentTypeDef->baseType == NULL)) {
16083 /*
16084 * TODO: Check if this ever happens.
16085 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016086 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016087 XML_SCHEMAP_INTERNAL,
16088 NULL, type, NULL,
16089 "Internal error: xmlSchemaTypeFixup, "
16090 "complex type '%s': the <simpleContent><restriction> "
16091 "is missing a <simpleType> child, but was not catched "
16092 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016094 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16095 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16096 /*
16097 * SPEC (3) If <extension> + base is <complexType> with
16098 * <simpleType> content, "...then the {content type} of that
16099 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016100 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016101 if (baseType->contentTypeDef == NULL) {
16102 /*
16103 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16104 * should have catched this already.
16105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016106 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016107 XML_SCHEMAP_INTERNAL,
16108 NULL, type, NULL,
16109 "Internal error: xmlSchemaTypeFixup, "
16110 "complex type '%s': the <extension>ed base type is "
16111 "a complex type with no simple content type",
16112 type->name);
16113 }
16114 type->contentTypeDef = baseType->contentTypeDef;
16115 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16116 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16117 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016118 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016119 * "... then that simple type definition"
16120 */
16121 type->contentTypeDef = baseType;
16122 } else {
16123 /*
16124 * TODO: Check if this ever happens.
16125 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016126 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016127 XML_SCHEMAP_INTERNAL,
16128 NULL, type, NULL,
16129 "Internal error: xmlSchemaTypeFixup, "
16130 "complex type '%s' with <simpleContent>: unhandled "
16131 "derivation case", type->name);
16132 }
16133 } else {
16134 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016135 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016136 (xmlSchemaParticlePtr) type->subtypes;
16137 /*
16138 * Corresponds to <complexType><complexContent>...
16139 *
16140 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016141 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016142 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016143 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016144 * Compute the "effective content":
16145 * (2.1.1) + (2.1.2) + (2.1.3)
16146 */
16147 if ((particle == NULL) ||
16148 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16149 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16150 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16151 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16152 (particle->minOccurs == 0))) &&
16153 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016154 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016155 /*
16156 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16157 * a particle whose properties are as follows:..."
16158 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016159 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016160 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16161 * NOTE that we sill assign it the <complexType> node to
16162 * somehow anchor it in the doc.
16163 */
16164 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016165 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016166 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016167 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016168 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016169 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016170 type->node, 1, 1);
16171 if (particle == NULL)
16172 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016173 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016174 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016175 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016177 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016178 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16179 if (particle->children == NULL)
16180 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016181
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016182 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016183 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016184 dummySequence = 1;
16185 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16186 } else {
16187 /*
16188 * SPEC (2.1.5) "otherwise empty"
16189 */
16190 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016191 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016192 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016193 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016194 * SPEC (2.2) "otherwise the particle corresponding to the
16195 * <all>, <choice>, <group> or <sequence> among the
16196 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016197 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016198 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16199 }
16200 /*
16201 * Compute the "content type".
16202 */
16203 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016204 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016205 * SPEC (3.1) "If <restriction>..."
16206 * (3.1.1) + (3.1.2) */
16207 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16208 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16209 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16210 }
16211 } else {
16212 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016213 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016214 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016215 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16216 /*
16217 * SPEC (3.2.1)
16218 */
16219 type->contentType = baseType->contentType;
16220 type->subtypes = baseType->subtypes;
16221 /*
16222 * NOTE that the effective mixed is ignored here.
16223 */
16224 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16225 /*
16226 * SPEC (3.2.2)
16227 */
16228 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16229 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16230 } else {
16231 /*
16232 * SPEC (3.2.3)
16233 */
16234 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16235 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16236 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016237 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016238 * {particles} are..."
16239 */
16240 if (! dummySequence) {
16241 xmlSchemaTreeItemPtr effectiveContent =
16242 (xmlSchemaTreeItemPtr) type->subtypes;
16243 /*
16244 * Create the particle.
16245 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016246 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 type->node, 1, 1);
16248 if (particle == NULL)
16249 return;
16250 /*
16251 * Create the "sequence" model group.
16252 */
16253 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016254 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016255 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16256 if (particle->children == NULL)
16257 return;
16258 type->subtypes = (xmlSchemaTypePtr) particle;
16259 /*
16260 * SPEC "the particle of the {content type} of
16261 * the ... base ..."
16262 * Create a duplicate of the base type's particle
16263 * and assign its "term" to it.
16264 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016265 particle->children->children =
16266 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16267 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016268 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016269 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016270 if (particle->children->children == NULL)
16271 return;
16272 particle = (xmlSchemaParticlePtr)
16273 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016274 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016275 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16276 /*
16277 * SPEC "followed by the ·effective content·."
16278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016279 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016280 } else {
16281 /*
16282 * This is the case when there is already an empty
16283 * <sequence> with minOccurs==maxOccurs==1.
16284 * Just add the base types's content type.
16285 * NOTE that, although we miss to add an intermediate
16286 * <sequence>, this should produce no difference to
16287 * neither the regex compilation of the content model,
16288 * nor to the complex type contraints.
16289 */
16290 particle->children->children =
16291 (xmlSchemaTreeItemPtr) baseType->subtypes;
16292 }
16293 }
16294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016295 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016296 /*
16297 * Apply the complex type component constraints; this will not
16298 * check attributes, since this is done in
16299 * xmlSchemaBuildAttributeValidation().
16300 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016301 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16302 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016303 /*
16304 * Inherit & check constraints for attributes.
16305 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016306 xmlSchemaBuildAttributeValidation(pctxt, type);
16307 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016308 /*
16309 * Simple Type Definition Schema Component
16310 */
16311 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016312 if (VARIETY_LIST(type)) {
16313 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016314 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016315 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016316 if (type->subtypes == NULL) {
16317 /*
16318 * This one is really needed, so get out.
16319 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016320 PERROR_INT("xmlSchemaTypeFixup",
16321 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016322 return;
16323 }
16324 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016325 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16326 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016327 /*
16328 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016329 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 if (type->memberTypes == NULL) {
16331 /*
16332 * This one is really needed, so get out.
16333 */
16334 return;
16335 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016336 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016337 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016339 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016340 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016342 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016343 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016344 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16345 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016346 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016347 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016348 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016349 */
16350 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016351 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016352 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016353 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16354 /*
16355 * Inherit the itemType.
16356 */
16357 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016358 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016359 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16360 /*
16361 * NOTE that we won't assign the memberTypes of the base,
16362 * since this will make trouble when freeing them; we will
16363 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016364 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016365 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016366 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016367 /*
16368 * Check constraints.
16369 *
16370 * TODO: Split this somehow, we need to know first if we can derive
16371 * from the base type at all!
16372 */
16373 if (type->baseType != NULL) {
16374 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016375 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016377 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016378 * applied beforehand.
16379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016380 xmlSchemaCheckSRCSimpleType(pctxt, type);
16381 xmlSchemaCheckFacetValues(type, pctxt);
16382 if ((type->facetSet != NULL) ||
16383 (type->baseType->facetSet != NULL))
16384 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16385 /*
16386 * Whitespace value.
16387 */
16388 xmlSchemaTypeFixupWhitespace(type);
16389 xmlSchemaTypeFixupOptimFacets(type);
16390 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016391 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016392
Daniel Veillard8651f532002-04-17 09:06:27 +000016393#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016395 xmlGenericError(xmlGenericErrorContext,
16396 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016397 type->node->doc->URL,
16398 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016399 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016400 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016401 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016402 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16403 switch (type->contentType) {
16404 case XML_SCHEMA_CONTENT_SIMPLE:
16405 xmlGenericError(xmlGenericErrorContext, "simple\n");
16406 break;
16407 case XML_SCHEMA_CONTENT_ELEMENTS:
16408 xmlGenericError(xmlGenericErrorContext, "elements\n");
16409 break;
16410 case XML_SCHEMA_CONTENT_UNKNOWN:
16411 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16412 break;
16413 case XML_SCHEMA_CONTENT_EMPTY:
16414 xmlGenericError(xmlGenericErrorContext, "empty\n");
16415 break;
16416 case XML_SCHEMA_CONTENT_MIXED:
16417 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016418 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016419 xmlGenericError(xmlGenericErrorContext,
16420 "mixed as emptiable particle\n");
16421 else
16422 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16423 break;
16424 /* Removed, since not used. */
16425 /*
16426 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16427 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16428 break;
16429 */
16430 case XML_SCHEMA_CONTENT_BASIC:
16431 xmlGenericError(xmlGenericErrorContext, "basic\n");
16432 break;
16433 default:
16434 xmlGenericError(xmlGenericErrorContext,
16435 "not registered !!!\n");
16436 break;
16437 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016438 }
16439#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016440}
16441
16442/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016443 * xmlSchemaCheckFacet:
16444 * @facet: the facet
16445 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016446 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016447 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016448 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016449 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016450 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016451 * Returns 0 if valid, a positive error code if not valid and
16452 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016453 */
16454int
16455xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016456 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016457 xmlSchemaParserCtxtPtr pctxt,
16458 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016459{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016460 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016461
Daniel Veillardce682bc2004-11-05 17:22:25 +000016462 if ((facet == NULL) || (typeDecl == NULL))
16463 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016464 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016465 * TODO: will the parser context be given if used from
16466 * the relaxNG module?
16467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016468 if (pctxt == NULL)
16469 ctxtGiven = 0;
16470 else
16471 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016472
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016473 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016474 case XML_SCHEMA_FACET_MININCLUSIVE:
16475 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16476 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016477 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16478 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016479 /*
16480 * Okay we need to validate the value
16481 * at that point.
16482 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016483 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016484
16485 /* 4.3.5.5 Constraints on enumeration Schema Components
16486 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016487 * It is an ·error· if any member of {value} is not in the
16488 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016489 *
16490 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491 * The value ·must· be in the
16492 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016493 */
16494 /*
16495 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016496 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016497 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016498 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016500 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016501 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016502 */
16503 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16504 base = typeDecl->baseType;
16505 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016506 PERROR_INT("xmlSchemaCheckFacet",
16507 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016508 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016509 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016510 } else
16511 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016512
16513 if (! ctxtGiven) {
16514 /*
16515 * A context is needed if called from RelaxNG.
16516 */
16517 pctxt = xmlSchemaNewParserCtxt("*");
16518 if (pctxt == NULL)
16519 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016520 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016523 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016524 * facet->node is just the node holding the facet
16525 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016526 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016527 */
16528 ret = xmlSchemaVCheckCVCSimpleType(
16529 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16530 facet->value, &(facet->val), 1, 1, 0);
16531 if (ret != 0) {
16532 if (ret < 0) {
16533 /* No error message for RelaxNG. */
16534 if (ctxtGiven) {
16535 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16536 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16537 "Internal error: xmlSchemaCheckFacet, "
16538 "failed to validate the value '%s' of the "
16539 "facet '%s' against the base type",
16540 facet->value, xmlSchemaFacetTypeToString(facet->type));
16541 }
16542 goto internal_error;
16543 }
16544 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16545 /* No error message for RelaxNG. */
16546 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016547 xmlChar *str = NULL;
16548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016549 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16550 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016551 "The value '%s' of the facet does not validate "
16552 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016553 facet->value,
16554 xmlSchemaFormatQName(&str,
16555 base->targetNamespace, base->name));
16556 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016557 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016558 goto exit;
16559 } else if (facet->val == NULL) {
16560 if (ctxtGiven) {
16561 PERROR_INT("xmlSchemaCheckFacet",
16562 "value was not computed");
16563 }
16564 TODO
16565 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016566 break;
16567 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016568 case XML_SCHEMA_FACET_PATTERN:
16569 facet->regexp = xmlRegexpCompile(facet->value);
16570 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016571 ret = XML_SCHEMAP_REGEXP_INVALID;
16572 /* No error message for RelaxNG. */
16573 if (ctxtGiven) {
16574 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16575 ret, facet->node, typeDecl,
16576 "The value '%s' of the facet 'pattern' is not a "
16577 "valid regular expression",
16578 facet->value, NULL);
16579 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016580 }
16581 break;
16582 case XML_SCHEMA_FACET_TOTALDIGITS:
16583 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16584 case XML_SCHEMA_FACET_LENGTH:
16585 case XML_SCHEMA_FACET_MAXLENGTH:
16586 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016587 ret = xmlSchemaValidatePredefinedType(
16588 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16589 facet->value, &(facet->val));
16590 if (ret != 0) {
16591 if (ret < 0) {
16592 /* No error message for RelaxNG. */
16593 if (ctxtGiven) {
16594 PERROR_INT("xmlSchemaCheckFacet",
16595 "validating facet value");
16596 }
16597 goto internal_error;
16598 }
16599 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16600 /* No error message for RelaxNG. */
16601 if (ctxtGiven) {
16602 /* error code */
16603 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16604 ret, facet->node, typeDecl,
16605 "The value '%s' of the facet '%s' is not a valid "
16606 "'nonNegativeInteger'",
16607 facet->value,
16608 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016609 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016610 }
16611 break;
16612 }
16613 case XML_SCHEMA_FACET_WHITESPACE:{
16614 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16615 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16616 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16617 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16618 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16619 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16620 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016621 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16622 /* No error message for RelaxNG. */
16623 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016624 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016625 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16626 ret, facet->node, typeDecl,
16627 "The value '%s' of the facet 'whitespace' is not "
16628 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016629 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016630 }
16631 }
16632 default:
16633 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016634 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016635exit:
16636 if ((! ctxtGiven) && (pctxt != NULL))
16637 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016638 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016639internal_error:
16640 if ((! ctxtGiven) && (pctxt != NULL))
16641 xmlSchemaFreeParserCtxt(pctxt);
16642 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016643}
16644
16645/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016646 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016647 * @typeDecl: the schema type definition
16648 * @ctxt: the schema parser context
16649 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016650 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016651 */
16652static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016653xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16654 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016655{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016656 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016657 /*
16658 * NOTE: It is intended to use the facets list, instead
16659 * of facetSet.
16660 */
16661 if (typeDecl->facets != NULL) {
16662 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016663
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016664 /*
16665 * Temporarily assign the "schema" to the validation context
16666 * of the parser context. This is needed for NOTATION validation.
16667 */
16668 if (ctxt->vctxt == NULL) {
16669 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16670 return;
16671 }
16672 ctxt->vctxt->schema = ctxt->schema;
16673
Daniel Veillard01fa6152004-06-29 17:04:39 +000016674 while (facet != NULL) {
16675 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16676 facet = facet->next;
16677 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016678
16679 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016680 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016681}
16682
16683/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016684 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016685 * @ctxtMGroup: the searched model group
16686 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016687 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016688 *
16689 * This one is intended to be used by
16690 * xmlSchemaCheckGroupDefCircular only.
16691 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016692 * Returns the particle with the circular model group definition reference,
16693 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016694 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016695static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016696xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016697 xmlSchemaTreeItemPtr particle)
16698{
16699 xmlSchemaTreeItemPtr circ = NULL;
16700 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016701 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016702
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016703 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016704 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016705 if (term == NULL)
16706 continue;
16707 switch (term->type) {
16708 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016709 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016710 if (gdef == groupDef)
16711 return (particle);
16712 /*
16713 * Mark this model group definition to avoid infinite
16714 * recursion on circular references not yet examined.
16715 */
16716 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16717 continue;
16718 if (gdef->children != NULL) {
16719 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16720 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16721 gdef->children->children);
16722 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16723 if (circ != NULL)
16724 return (circ);
16725 }
16726 break;
16727 case XML_SCHEMA_TYPE_SEQUENCE:
16728 case XML_SCHEMA_TYPE_CHOICE:
16729 case XML_SCHEMA_TYPE_ALL:
16730 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16731 if (circ != NULL)
16732 return (circ);
16733 break;
16734 default:
16735 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016736 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016737 }
16738 return (NULL);
16739}
16740
16741/**
16742 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016743 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016744 * @ctxt: the parser context
16745 * @name: the name
16746 *
16747 * Checks for circular references to model group definitions.
16748 */
16749static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016750xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016751 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016752 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016753{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016754 /*
16755 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016756 * 2 Circular groups are disallowed. That is, within the {particles}
16757 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016758 * is the group itself.
16759 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016760 if ((item == NULL) ||
16761 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16762 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016763 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016764 {
16765 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016766
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016767 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016768 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016769 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016770 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016771 * TODO: The error report is not adequate: this constraint
16772 * is defined for model groups but not definitions, but since
16773 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016774 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016775 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016776 */
16777 xmlSchemaPCustomErr(ctxt,
16778 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016779 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016780 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016781 "defined", xmlSchemaFormatQName(&str,
16782 item->targetNamespace, item->name));
16783 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016784 /*
16785 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016786 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016787 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016788 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016789 }
16790 }
16791}
16792
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016793/**
16794 * xmlSchemaGroupDefTermFixup:
16795 * @item: the particle with a model group definition as term
16796 * @ctxt: the parser context
16797 * @name: the name
16798 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016799 * Checks cos-all-limited.
16800 *
16801 * Assigns the model group of model group definitions to the "term"
16802 * of the referencing particle.
16803 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16804 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016805 */
16806static void
16807xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016808 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016809 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016810{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016811 if ((item == NULL) ||
16812 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16813 (item->children == NULL) ||
16814 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16815 (item->children->children == NULL))
16816 return;
16817 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016818 /*
16819 * TODO: Not nice, but we will anchor cos-all-limited here.
16820 */
16821 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16822 (item->maxOccurs != 1)) {
16823 /*
16824 * SPEC (1.2) "the {term} property of a particle with
16825 * {max occurs}=1which is part of a pair which constitutes the
16826 * {content type} of a complex type definition."
16827 */
16828 xmlSchemaPCustomErr(ctxt,
16829 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16830 NULL, (xmlSchemaTypePtr) item, item->node,
16831 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16832 "group is its term", NULL);
16833 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016834}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016835
16836/**
16837 * xmlSchemaGetCircAttrGrRef:
16838 * @ctxtGr: the searched attribute group
16839 * @attr: the current attribute list to be processed
16840 *
16841 * This one is intended to be used by
16842 * xmlSchemaCheckSRCAttributeGroupCircular only.
16843 *
16844 * Returns the circular attribute grou reference, otherwise NULL.
16845 */
16846static xmlSchemaAttributeGroupPtr
16847xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16848 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016849{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016850 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16851 int marked;
16852 /*
16853 * We will search for an attribute group reference which
16854 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016855 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016856 while (attr != NULL) {
16857 marked = 0;
16858 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16859 gr = (xmlSchemaAttributeGroupPtr) attr;
16860 if (gr->refItem != NULL) {
16861 if (gr->refItem == ctxtGr)
16862 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016863 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016864 XML_SCHEMAS_ATTRGROUP_MARKED) {
16865 attr = attr->next;
16866 continue;
16867 } else {
16868 /*
16869 * Mark as visited to avoid infinite recursion on
16870 * circular references not yet examined.
16871 */
16872 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16873 marked = 1;
16874 }
16875 }
16876 if (gr->attributes != NULL)
16877 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16878 /*
16879 * Unmark the visited group's attributes.
16880 */
16881 if (marked)
16882 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16883 if (circ != NULL)
16884 return (circ);
16885 }
16886 attr = attr->next;
16887 }
16888 return (NULL);
16889}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016890
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016891/**
16892 * xmlSchemaCheckSRCAttributeGroupCircular:
16893 * attrGr: the attribute group definition
16894 * @ctxt: the parser context
16895 * @name: the name
16896 *
16897 * Checks for circular references of attribute groups.
16898 */
16899static void
16900xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016901 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016902 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016903{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016904 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016905 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016906 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016907 * 3 Circular group reference is disallowed outside <redefine>.
16908 * That is, unless this element information item's parent is
16909 * <redefine>, then among the [children], if any, there must
16910 * not be an <attributeGroup> with ref [attribute] which resolves
16911 * to the component corresponding to this <attributeGroup>. Indirect
16912 * circularity is also ruled out. That is, when QName resolution
16913 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16914 * any <attributeGroup>s with a ref [attribute] among the [children],
16915 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016916 * which resolves to the component corresponding to this <attributeGroup>.
16917 */
16918 /*
16919 * Only global components can be referenced.
16920 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016921 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016922 (attrGr->attributes == NULL))
16923 return;
16924 else {
16925 xmlSchemaAttributeGroupPtr circ;
16926
16927 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16928 if (circ != NULL) {
16929 /*
16930 * TODO: Report the referenced attr group as QName.
16931 */
16932 xmlSchemaPCustomErr(ctxt,
16933 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16934 NULL, NULL, circ->node,
16935 "Circular reference to the attribute group '%s' "
16936 "defined", attrGr->name);
16937 /*
16938 * NOTE: We will cut the reference to avoid further
16939 * confusion of the processor.
16940 * BADSPEC: The spec should define how to process in this case.
16941 */
16942 circ->attributes = NULL;
16943 circ->refItem = NULL;
16944 }
16945 }
16946}
16947
16948/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016949 * xmlSchemaAttrGrpFixup:
16950 * @attrgrpDecl: the schema attribute definition
16951 * @ctxt: the schema parser context
16952 * @name: the attribute name
16953 *
16954 * Fixes finish doing the computations on the attributes definitions
16955 */
16956static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016957xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016958 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016959{
16960 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016961 name = attrgrp->name;
16962 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016963 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016964 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016965 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016966
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016967 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016968 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016969 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016970 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016971 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016972 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16973 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016974 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016975 return;
16976 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016977 attrgrp->refItem = ref;
16978 /*
16979 * Check for self reference!
16980 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016981 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016982 attrgrp->attributes = ref->attributes;
16983 attrgrp->attributeWildcard = ref->attributeWildcard;
16984 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016985}
16986
16987/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016988 * xmlSchemaAttrCheckValConstr:
16989 * @item: an schema attribute declaration/use
16990 * @ctxt: a schema parser context
16991 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016992 *
16993 *
16994 * Schema Component Constraint: Attribute Declaration Properties Correct
16995 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016996 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016997 *
16998 * Fixes finish doing the computations on the attributes definitions
16999 */
17000static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017001xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017002 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017003 const xmlChar * name ATTRIBUTE_UNUSED)
17004{
17005
17006 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017007 * 2 if there is a {value constraint}, the canonical lexical
17008 * representation of its value must be ·valid· with respect
17009 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017010 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017011 if (item->defValue != NULL) {
17012 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017013
17014 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017015 PERROR_INT("xmlSchemaCheckAttrValConstr",
17016 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017017 return;
17018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017019 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17020 item->node, item->subtypes, item->defValue, &(item->defVal),
17021 1, 1, 0);
17022 if (ret != 0) {
17023 if (ret < 0) {
17024 PERROR_INT("xmlSchemaAttrCheckValConstr",
17025 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017026 return;
17027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017028 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17029 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17030 ret, item->node, (xmlSchemaTypePtr) item,
17031 "The value of the value constraint is not valid", NULL, NULL);
17032 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017033 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017034 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017035}
17036
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017037static xmlSchemaElementPtr
17038xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17039 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017040{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017041 xmlSchemaElementPtr ret;
17042
17043 if (SUBST_GROUP_AFF(ancestor) == NULL)
17044 return (NULL);
17045 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17046 return (ancestor);
17047
17048 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17049 return (NULL);
17050 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17051 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17052 SUBST_GROUP_AFF(ancestor));
17053 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17054
17055 return (ret);
17056}
17057
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017058/**
17059 * xmlSchemaCheckElemPropsCorrect:
17060 * @ctxt: a schema parser context
17061 * @decl: the element declaration
17062 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017063 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017064 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017065 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017066 *
17067 * STATUS:
17068 * missing: (6)
17069 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017070static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017071xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17072 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017073{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017074 int ret = 0;
17075 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017076 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017077 * SPEC (1) "The values of the properties of an element declaration
17078 * must be as described in the property tableau in The Element
17079 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17080 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017081 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017082 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017083 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017084
17085 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017086 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017087 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017088 * affiliation}, then {scope} must be global."
17089 */
17090 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17091 xmlSchemaPCustomErr(pctxt,
17092 XML_SCHEMAP_E_PROPS_CORRECT_3,
17093 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17094 "Only global element declarations can have a "
17095 "substitution group affiliation", NULL);
17096 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017097 }
17098 /*
17099 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17100 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017101 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017102 * property."
17103 */
17104 if (head == elemDecl)
17105 circ = head;
17106 else if (SUBST_GROUP_AFF(head) != NULL)
17107 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17108 else
17109 circ = NULL;
17110 if (circ != NULL) {
17111 xmlChar *strA = NULL, *strB = NULL;
17112
17113 xmlSchemaPCustomErrExt(pctxt,
17114 XML_SCHEMAP_E_PROPS_CORRECT_6,
17115 NULL, (xmlSchemaTypePtr) circ, circ->node,
17116 "The element declaration '%s' defines a circular "
17117 "substitution group to element declaration '%s'",
17118 xmlSchemaGetComponentQName(&strA, circ),
17119 xmlSchemaGetComponentQName(&strB, head),
17120 NULL);
17121 FREE_AND_NULL(strA)
17122 FREE_AND_NULL(strB)
17123 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17124 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017125 /*
17126 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017127 * the {type definition}
17128 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017129 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017130 * of the {substitution group exclusions} of the {substitution group
17131 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17132 * (if the {type definition} is complex) or as defined in
17133 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017134 * simple)."
17135 *
17136 * NOTE: {substitution group exclusions} means the values of the
17137 * attribute "final".
17138 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017139
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017140 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017141 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017142
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017143 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17144 set |= SUBSET_EXTENSION;
17145 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17146 set |= SUBSET_RESTRICTION;
17147
17148 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17149 ELEM_TYPE(head), set) != 0) {
17150 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17151
17152 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017153 xmlSchemaPCustomErrExt(pctxt,
17154 XML_SCHEMAP_E_PROPS_CORRECT_4,
17155 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017156 "The type definition '%s' was "
17157 "either rejected by the substitution group "
17158 "affiliation '%s', or not validly derived from its type "
17159 "definition '%s'",
17160 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017161 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017162 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017163 FREE_AND_NULL(strA)
17164 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017165 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017166 }
17167 }
17168 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017169 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017170 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017171 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017172 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017173 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017174 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017175 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017176 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017177 ((IS_SIMPLE_TYPE(typeDef) &&
17178 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017179 (IS_COMPLEX_TYPE(typeDef) &&
17180 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017181 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17182 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017183
17184 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17185 xmlSchemaPCustomErr(pctxt,
17186 XML_SCHEMAP_E_PROPS_CORRECT_5,
17187 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17188 "The type definition (or type definition's content type) is or "
17189 "is derived from ID; value constraints are not allowed in "
17190 "conjunction with such a type definition", NULL);
17191 } else if (elemDecl->value != NULL) {
17192 int vcret;
17193 xmlNodePtr node = NULL;
17194
17195 /*
17196 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17197 * representation of its value must be ·valid· with respect to the
17198 * {type definition} as defined in Element Default Valid (Immediate)
17199 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017200 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017201 if (typeDef == NULL) {
17202 xmlSchemaPErr(pctxt, elemDecl->node,
17203 XML_SCHEMAP_INTERNAL,
17204 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17205 "type is missing... skipping validation of "
17206 "the value constraint", NULL, NULL);
17207 return (-1);
17208 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017209 if (elemDecl->node != NULL) {
17210 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17211 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17212 BAD_CAST "fixed");
17213 else
17214 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17215 BAD_CAST "default");
17216 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017217 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17218 typeDef, elemDecl->value, &(elemDecl->defVal));
17219 if (vcret != 0) {
17220 if (vcret < 0) {
17221 PERROR_INT("xmlSchemaElemCheckValConstr",
17222 "failed to validate the value constraint of an "
17223 "element declaration");
17224 return (-1);
17225 }
17226 return (vcret);
17227 }
17228 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017229
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017230 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017231}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017232
17233/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017234 * xmlSchemaCheckElemSubstGroup:
17235 * @ctxt: a schema parser context
17236 * @decl: the element declaration
17237 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017238 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017239 * Schema Component Constraint:
17240 * Substitution Group (cos-equiv-class)
17241 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017242 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017243 * a list will be built for each subst. group head, holding all direct
17244 * referents to this head.
17245 * NOTE that this function needs:
17246 * 1. circular subst. groups to be checked beforehand
17247 * 2. the declaration's type to be derived from the head's type
17248 *
17249 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017250 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017251 */
17252static void
17253xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17254 xmlSchemaElementPtr elemDecl)
17255{
17256 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17257 /* SPEC (1) "Its {abstract} is false." */
17258 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17259 return;
17260 {
17261 xmlSchemaElementPtr head;
17262 xmlSchemaTypePtr headType, type;
17263 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017264 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017265 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17266 * {disallowed substitutions} as the blocking constraint, as defined in
17267 * Substitution Group OK (Transitive) (§3.3.6)."
17268 */
17269 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17270 head = SUBST_GROUP_AFF(head)) {
17271 set = 0;
17272 methSet = 0;
17273 /*
17274 * The blocking constraints.
17275 */
17276 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17277 continue;
17278 headType = head->subtypes;
17279 type = elemDecl->subtypes;
17280 if (headType == type)
17281 goto add_member;
17282 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17283 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17284 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17285 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17286 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017287 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017288 * "The set of all {derivation method}s involved in the
17289 * derivation of D's {type definition} from C's {type definition}
17290 * does not intersect with the union of the blocking constraint,
17291 * C's {prohibited substitutions} (if C is complex, otherwise the
17292 * empty set) and the {prohibited substitutions} (respectively the
17293 * empty set) of any intermediate {type definition}s in the
17294 * derivation of D's {type definition} from C's {type definition}."
17295 */
17296 /*
17297 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17298 * subst.head axis, the methSet does not need to be computed for
17299 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017300 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017301 /*
17302 * The set of all {derivation method}s involved in the derivation
17303 */
17304 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017305 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017306 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17307 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17308 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017309
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017310 if ((type->flags &
17311 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17312 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17313 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17314
17315 type = type->baseType;
17316 }
17317 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017318 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017319 * the head's type.
17320 */
17321 type = elemDecl->subtypes->baseType;
17322 while (type != NULL) {
17323 if (IS_COMPLEX_TYPE(type)) {
17324 if ((type->flags &
17325 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17326 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17327 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17328 if ((type->flags &
17329 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17330 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17331 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17332 } else
17333 break;
17334 if (type == headType)
17335 break;
17336 type = type->baseType;
17337 }
17338 if ((set != 0) &&
17339 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17340 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17341 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17342 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17343 continue;
17344 }
17345add_member:
17346 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17347 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17348 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17349 }
17350 }
17351}
17352
17353/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017354 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017355 * @item: an schema element declaration/particle
17356 * @ctxt: a schema parser context
17357 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017358 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017359 * Validates the value constraints of an element declaration.
17360 *
17361 * Fixes finish doing the computations on the element declarations.
17362 */
17363static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017364xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017365 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017366 const xmlChar * name ATTRIBUTE_UNUSED)
17367{
17368 if (elemDecl == NULL)
17369 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017370 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17371 return;
17372 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017373 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17374 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017375}
17376
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017377/**
17378 * xmlSchemaMiscRefFixup:
17379 * @item: an schema component
17380 * @ctxt: a schema parser context
17381 * @name: the internal name of the component
17382 *
17383 * Resolves references of misc. schema components.
17384 */
17385static void
17386xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017387 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017388 const xmlChar * name ATTRIBUTE_UNUSED)
17389{
17390 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017391 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017392 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17393 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17394 xmlSchemaTreeItemPtr refItem;
17395 /*
17396 * Resolve the reference.
17397 */
17398 item->children = NULL;
17399 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17400 ref->itemType, ref->name, ref->targetNamespace);
17401 if (refItem == NULL) {
17402 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017403 NULL, GET_NODE(item), "ref", ref->name,
17404 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017405 } else {
17406 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17407 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017408 * NOTE that we will assign the model group definition
17409 * itself to the "term" of the particle. This will ease
17410 * the check for circular model group definitions. After
17411 * that the "term" will be assigned the model group of the
17412 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017413 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017414 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017415 } else
17416 item->children = refItem;
17417 }
17418 }
17419 }
17420}
17421
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017422static int
17423xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17424 xmlSchemaValPtr y)
17425{
17426 xmlSchemaTypePtr tx, ty, ptx, pty;
17427 int ret;
17428
17429 while (x != NULL) {
17430 /* Same types. */
17431 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17432 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17433 ptx = xmlSchemaGetPrimitiveType(tx);
17434 pty = xmlSchemaGetPrimitiveType(ty);
17435 /*
17436 * (1) if a datatype T' is ·derived· by ·restriction· from an
17437 * atomic datatype T then the ·value space· of T' is a subset of
17438 * the ·value space· of T. */
17439 /*
17440 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17441 * from a common atomic ancestor T then the ·value space·s of T'
17442 * and T'' may overlap.
17443 */
17444 if (ptx != pty)
17445 return(0);
17446 /*
17447 * We assume computed values to be normalized, so do a fast
17448 * string comparison for string based types.
17449 */
17450 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17451 IS_ANY_SIMPLE_TYPE(ptx)) {
17452 if (! xmlStrEqual(
17453 xmlSchemaValueGetAsString(x),
17454 xmlSchemaValueGetAsString(y)))
17455 return (0);
17456 } else {
17457 ret = xmlSchemaCompareValuesWhtsp(
17458 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17459 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17460 if (ret == -2)
17461 return(-1);
17462 if (ret != 0)
17463 return(0);
17464 }
17465 /*
17466 * Lists.
17467 */
17468 x = xmlSchemaValueGetNext(x);
17469 if (x != NULL) {
17470 y = xmlSchemaValueGetNext(y);
17471 if (y == NULL)
17472 return (0);
17473 } else if (xmlSchemaValueGetNext(y) != NULL)
17474 return (0);
17475 else
17476 return (1);
17477 }
17478 return (0);
17479}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017480
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017481/**
17482 * xmlSchemaAttrFixup:
17483 * @item: an schema attribute declaration/use.
17484 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017485 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017486 *
17487 * Fixes finish doing the computations on attribute declarations/uses.
17488 */
17489static void
17490xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017491 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017492 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017493{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017494 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017495 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017496 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017497 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017498 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017499 * The simple type definition corresponding to the <simpleType> element
17500 * information item in the [children], if present, otherwise the simple
17501 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017502 * [attribute], if present, otherwise the ·simple ur-type definition·.
17503 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017504 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017505 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017506 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17507 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017508 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017509 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017510 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017511
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017512 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17513 item->typeNs);
17514 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017515 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017516 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017517 (xmlSchemaTypePtr) item, item->node,
17518 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017519 XML_SCHEMA_TYPE_SIMPLE, NULL);
17520 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017521 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017522
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017523 } else if (item->ref != NULL) {
17524 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017525
Daniel Veillardc0826a72004-08-10 14:17:33 +000017526 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017527 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017528 * attribute declaration.
17529 */
17530 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017531 * TODO: Evaluate, what errors could occur if the declaration is not
17532 * found. It might be possible that the "typefixup" might crash if
17533 * no ref declaration was found.
17534 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017535 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017536 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017537 xmlSchemaPResCompAttrErr(ctxt,
17538 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017539 (xmlSchemaTypePtr) item, item->node,
17540 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017541 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017542 return;
17543 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017544 item->refDecl = decl;
17545 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017546 item->subtypes = decl->subtypes;
17547 /*
17548 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017549 * au-props-correct.2: If the {attribute declaration} has a fixed
17550 * {value constraint}, then if the attribute use itself has a
17551 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017552 * that of the {attribute declaration}'s {value constraint}.
17553 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017554 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017555 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017556 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017557 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017558 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17559 NULL, NULL, item->node,
17560 "The attribute declaration has a 'fixed' value constraint "
17561 ", thus it must be 'fixed' in attribute use as well",
17562 NULL);
17563 } else {
17564 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17565 xmlSchemaPCustomErr(ctxt,
17566 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17567 NULL, NULL, item->node,
17568 "The 'fixed' value constraint of the attribute use "
17569 "must match the attribute declaration's value "
17570 "constraint '%s'",
17571 decl->defValue);
17572 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017573 }
17574 /*
17575 * FUTURE: One should change the values of the attr. use
17576 * if ever validation should be attempted even if the
17577 * schema itself was not fully valid.
17578 */
17579 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017580 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017581 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17582 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017583}
17584
17585/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017586 * xmlSchemaResolveIDCKeyRef:
17587 * @idc: the identity-constraint definition
17588 * @ctxt: the schema parser context
17589 * @name: the attribute name
17590 *
17591 * Resolve keyRef references to key/unique IDCs.
17592 */
17593static void
17594xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017595 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017596 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017597{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017598 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17599 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017600 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017601 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017602 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017603 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017604 idc->ref->targetNamespace);
17605 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017606 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017607 * TODO: It is actually not an error to fail to resolve.
17608 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017609 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017610 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017611 (xmlSchemaTypePtr) idc, idc->node,
17612 "refer", idc->ref->name,
17613 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017614 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17615 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017616 } else {
17617 if (idc->nbFields !=
17618 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17619 xmlChar *str = NULL;
17620 xmlSchemaIDCPtr refer;
17621
17622 refer = (xmlSchemaIDCPtr) idc->ref->item;
17623 /*
17624 * SPEC c-props-correct(2)
17625 * "If the {identity-constraint category} is keyref,
17626 * the cardinality of the {fields} must equal that of
17627 * the {fields} of the {referenced key}.
17628 */
17629 xmlSchemaPCustomErr(pctxt,
17630 XML_SCHEMAP_C_PROPS_CORRECT,
17631 NULL, (xmlSchemaTypePtr) idc, idc->node,
17632 "The cardinality of the keyref differs from the "
17633 "cardinality of the referenced key '%s'",
17634 xmlSchemaFormatQName(&str, refer->targetNamespace,
17635 refer->name)
17636 );
17637 FREE_AND_NULL(str)
17638 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017639 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017640 }
17641}
17642
17643/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017644 * xmlSchemaParse:
17645 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017646 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017647 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017648 * XML Shema struture which can be used to validate instances.
17649 * *WARNING* this interface is highly subject to change
17650 *
17651 * Returns the internal XML Schema structure built from the resource or
17652 * NULL in case of error
17653 */
17654xmlSchemaPtr
17655xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17656{
17657 xmlSchemaPtr ret = NULL;
17658 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017659 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017660 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017661
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017662 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017663 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017664 * the API; i.e. not automatically by the validated instance document.
17665 */
17666
Daniel Veillard4255d502002-04-16 15:50:10 +000017667 xmlSchemaInitTypes();
17668
Daniel Veillard6045c902002-10-09 21:13:59 +000017669 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017670 return (NULL);
17671
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017672 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017673 ctxt->counter = 0;
17674 ctxt->container = NULL;
17675
17676 /*
17677 * First step is to parse the input document into an DOM/Infoset
17678 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017679 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017680 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017681 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017682 if (doc == NULL) {
17683 xmlSchemaPErr(ctxt, NULL,
17684 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017685 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017686 ctxt->URL, NULL);
17687 return (NULL);
17688 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017689 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017690 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17691 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017692 if (doc == NULL) {
17693 xmlSchemaPErr(ctxt, NULL,
17694 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017695 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017696 NULL, NULL);
17697 return (NULL);
17698 }
17699 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017700 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017701 } else if (ctxt->doc != NULL) {
17702 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017703 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017704 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017705 xmlSchemaPErr(ctxt, NULL,
17706 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017707 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017708 NULL, NULL);
17709 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017710 }
17711
17712 /*
17713 * Then extract the root and Schema parse it
17714 */
17715 root = xmlDocGetRootElement(doc);
17716 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017717 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17718 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017719 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017720 if (!preserve) {
17721 xmlFreeDoc(doc);
17722 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017723 return (NULL);
17724 }
17725
17726 /*
17727 * Remove all the blank text nodes
17728 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017729 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017730
17731 /*
17732 * Then do the parsing for good
17733 */
17734 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017735 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017736 if (!preserve) {
17737 xmlFreeDoc(doc);
17738 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017739 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017740 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017741 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017742 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017743 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017744 ctxt->ctxtType = NULL;
17745 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017746
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017747 /*
17748 * Resolve base types of simple/complex types.
17749 */
17750 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017751
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017752 if (ctxt->nberrors != 0)
17753 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017754
17755 if (ret->volatiles != NULL) {
17756 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17757 int i;
17758 xmlSchemaTreeItemPtr item;
17759
17760 for (i = 0; i < list->nbItems; i++) {
17761 item = (xmlSchemaTreeItemPtr) list->items[i];
17762 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17763 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017764 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017765 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017766 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017767 * Then fixup all attributes declarations
17768 */
17769 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017770 /*
17771 * Then fixup all attributes group declarations
17772 */
17773 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17774 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017775 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017776 * Resolve identity-constraint keyRefs.
17777 */
17778 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017779 /*
17780 * Check type defnitions for circular references.
17781 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017782 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017783 xmlSchemaCheckTypeDefCircular, ctxt);
17784 /*
17785 * Check model groups defnitions for circular references.
17786 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017787 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017788 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017789 /*
17790 * Set the "term" of particles pointing to model group definitions
17791 * to the contained model group.
17792 */
17793 if (ret->volatiles != NULL) {
17794 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17795 int i;
17796 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017797
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017798 for (i = 0; i < list->nbItems; i++) {
17799 item = (xmlSchemaParticlePtr) list->items[i];
17800 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17801 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17802 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017803 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017804 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017805 * Check attribute groups for circular references.
17806 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017807 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17808 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017809 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017810 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017811 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017812 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017813 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017814 /*
17815 * We will stop here if the schema was not valid to avoid internal errors
17816 * on missing sub-components. This is not conforming to the spec, since it
17817 * allows missing components, but it might make further processing crash.
17818 * So see it as a very strict handling, which might be made more lax in the
17819 * future.
17820 */
17821 if (ctxt->nberrors != 0)
17822 goto exit;
17823 /*
17824 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017825 */
17826 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017827 /*
17828 * Validate the value constraint of attribute declarations/uses.
17829 */
17830 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017831 /*
17832 * Validate the value constraint of element declarations.
17833 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017834 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017835
17836 if (ctxt->nberrors != 0)
17837 goto exit;
17838
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017839 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017840 * TODO: cos-element-consistent, cos-all-limited
17841 *
17842 * Then build the content model for all complex types
17843 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017844 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017845 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017846
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017847exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017848 if (ctxt->nberrors != 0) {
17849 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017850 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017851 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017852 return (ret);
17853}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017854
Daniel Veillard4255d502002-04-16 15:50:10 +000017855/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017856 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017857 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017858 * @err: the error callback
17859 * @warn: the warning callback
17860 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017861 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017862 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017863 */
17864void
17865xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017866 xmlSchemaValidityErrorFunc err,
17867 xmlSchemaValidityWarningFunc warn, void *ctx)
17868{
Daniel Veillard4255d502002-04-16 15:50:10 +000017869 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017870 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017871 ctxt->error = err;
17872 ctxt->warning = warn;
17873 ctxt->userData = ctx;
17874}
17875
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017876/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017877 * xmlSchemaGetParserErrors:
17878 * @ctxt: a XMl-Schema parser context
17879 * @err: the error callback result
17880 * @warn: the warning callback result
17881 * @ctx: contextual data for the callbacks result
17882 *
17883 * Get the callback information used to handle errors for a parser context
17884 *
17885 * Returns -1 in case of failure, 0 otherwise
17886 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017887int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017888xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17889 xmlSchemaValidityErrorFunc * err,
17890 xmlSchemaValidityWarningFunc * warn, void **ctx)
17891{
17892 if (ctxt == NULL)
17893 return(-1);
17894 if (err != NULL)
17895 *err = ctxt->error;
17896 if (warn != NULL)
17897 *warn = ctxt->warning;
17898 if (ctx != NULL)
17899 *ctx = ctxt->userData;
17900 return(0);
17901}
17902
17903/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017904 * xmlSchemaFacetTypeToString:
17905 * @type: the facet type
17906 *
17907 * Convert the xmlSchemaTypeType to a char string.
17908 *
17909 * Returns the char string representation of the facet type if the
17910 * type is a facet and an "Internal Error" string otherwise.
17911 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017912static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017913xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17914{
17915 switch (type) {
17916 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017917 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017918 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017919 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017920 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017921 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017922 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017923 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017924 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017925 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017926 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017927 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017928 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017929 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017930 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017931 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017932 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017933 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017934 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017935 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017936 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017937 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017938 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017939 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017940 default:
17941 break;
17942 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017943 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017944}
17945
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017946static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017947xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17948{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017949 /*
17950 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017951 * from xsd:string.
17952 */
17953 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017954 /*
17955 * Note that we assume a whitespace of preserve for anySimpleType.
17956 */
17957 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17958 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17959 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017960 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017961 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017962 else {
17963 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017964 * For all ·atomic· datatypes other than string (and types ·derived·
17965 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017966 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017967 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017968 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017969 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017970 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017971 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017972 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017973 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017974 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017975 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17976 } else if (VARIETY_UNION(type)) {
17977 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17978 } else if (VARIETY_ATOMIC(type)) {
17979 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17980 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17981 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17982 return (XML_SCHEMA_WHITESPACE_REPLACE);
17983 else
17984 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017985 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017986 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017987}
17988
Daniel Veillard4255d502002-04-16 15:50:10 +000017989/************************************************************************
17990 * *
17991 * Simple type validation *
17992 * *
17993 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017994
Daniel Veillard4255d502002-04-16 15:50:10 +000017995
17996/************************************************************************
17997 * *
17998 * DOM Validation code *
17999 * *
18000 ************************************************************************/
18001
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018002static void
18003xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18004{
18005 int i, nbItems;
18006 xmlSchemaTypePtr item, *items;
18007
18008
18009 /*
18010 * During the Assemble of the schema ctxt->curItems has
18011 * been filled with the relevant new items. Fix those up.
18012 */
18013 nbItems = ctxt->assemble->nbItems;
18014 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018015
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018016 for (i = 0; i < nbItems; i++) {
18017 item = items[i];
18018 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018019 case XML_SCHEMA_TYPE_COMPLEX:
18020 case XML_SCHEMA_TYPE_SIMPLE:
18021 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18022 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018023 case XML_SCHEMA_TYPE_ATTRIBUTE:
18024 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18025 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018026 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018027 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018028 ctxt, NULL);
18029 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018030 case XML_SCHEMA_TYPE_PARTICLE:
18031 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018032 break;
18033 case XML_SCHEMA_TYPE_IDC_KEY:
18034 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18035 case XML_SCHEMA_TYPE_IDC_KEYREF:
18036 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18037 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018038 default:
18039 break;
18040 }
18041 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018042 if (ctxt->nberrors != 0)
18043 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018044 /*
18045 * Circularity checks.
18046 */
18047 for (i = 0; i < nbItems; i++) {
18048 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018049 switch (item->type) {
18050 case XML_SCHEMA_TYPE_COMPLEX:
18051 case XML_SCHEMA_TYPE_SIMPLE:
18052 xmlSchemaCheckTypeDefCircular(
18053 (xmlSchemaTypePtr) item, ctxt, NULL);
18054 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018055 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018056 xmlSchemaCheckGroupDefCircular(
18057 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018058 break;
18059 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18060 xmlSchemaCheckAttributeGroupCircular(
18061 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18062 break;
18063 default:
18064 break;
18065 }
18066 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018067 if (ctxt->nberrors != 0)
18068 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018069 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018070 * Set the "term" of particles pointing to model group definitions
18071 * to the contained model group.
18072 */
18073 for (i = 0; i < nbItems; i++) {
18074 item = items[i];
18075 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18076 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018077 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018078 XML_SCHEMA_TYPE_GROUP)) {
18079 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18080 ctxt, NULL);
18081 }
18082 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018083 if (ctxt->nberrors != 0)
18084 return;
18085 for (i = 0; i < nbItems; i++) {
18086 item = items[i];
18087 switch (item->type) {
18088 case XML_SCHEMA_TYPE_ELEMENT:
18089 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18090 NULL, NULL, NULL);
18091 break;
18092 default:
18093 break;
18094 }
18095 }
18096 if (ctxt->nberrors != 0)
18097 return;
18098
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018099 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018100 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018101 */
18102 for (i = 0; i < nbItems; i++) {
18103 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018104 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018105 case XML_SCHEMA_TYPE_SIMPLE:
18106 case XML_SCHEMA_TYPE_COMPLEX:
18107 xmlSchemaTypeFixup(item, ctxt, NULL);
18108 break;
18109 default:
18110 break;
18111 }
18112 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018113 if (ctxt->nberrors != 0)
18114 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018115 /*
18116 * Validate value contraint values.
18117 */
18118 for (i = 0; i < nbItems; i++) {
18119 item = items[i];
18120 switch (item->type) {
18121 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018122 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18123 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018124 break;
18125 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018126 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018127 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018128 break;
18129 default:
18130 break;
18131 }
18132 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018133 if (ctxt->nberrors != 0)
18134 return;
18135 /*
18136 * Build the content model for complex types.
18137 */
18138 for (i = 0; i < nbItems; i++) {
18139 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018140 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018141 case XML_SCHEMA_TYPE_COMPLEX:
18142 xmlSchemaBuildContentModel(item, ctxt, NULL);
18143 break;
18144 default:
18145 break;
18146 }
18147 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018148}
18149
18150/**
18151 * xmlSchemaAssembleByLocation:
18152 * @pctxt: a schema parser context
18153 * @vctxt: a schema validation context
18154 * @schema: the existing schema
18155 * @node: the node that fired the assembling
18156 * @nsName: the namespace name of the new schema
18157 * @location: the location of the schema
18158 *
18159 * Expands an existing schema by an additional schema.
18160 *
18161 * Returns 0 if the new schema is correct, a positive error code
18162 * number otherwise and -1 in case of an internal or API error.
18163 */
18164static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018165xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018166 xmlSchemaPtr schema,
18167 xmlNodePtr node,
18168 const xmlChar *nsName,
18169 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018170{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018171 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018172 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018173 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018174 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018175 xmlSchemaParserCtxtPtr pctxt;
18176
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018177 /*
18178 * This should be used:
18179 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018180 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018181 * 3. if requested via the API
18182 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018183 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018184 return (-1);
18185 /*
18186 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018187 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018188 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018189 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18190 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018191 pctxt = vctxt->pctxt;
18192 /*
18193 * Set the counter to produce unique names for anonymous items.
18194 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018195 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018196 /*
18197 * Acquire the schema document.
18198 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018199 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18200 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018201 if (ret != 0) {
18202 if (doc != NULL)
18203 xmlFreeDoc(doc);
18204 } else if (doc != NULL) {
18205 docElem = xmlDocGetRootElement(doc);
18206 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018207 * Create new assemble info.
18208 */
18209 if (pctxt->assemble == NULL) {
18210 pctxt->assemble = xmlSchemaNewAssemble();
18211 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018212 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018213 "Memory error: xmlSchemaAssembleByLocation, "
18214 "allocating assemble info", NULL);
18215 xmlFreeDoc(doc);
18216 return (-1);
18217 }
18218 }
18219 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018220 * Save and reset the context & schema.
18221 */
18222 oldflags = schema->flags;
18223 oldtns = schema->targetNamespace;
18224 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018225 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018226
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018227 xmlSchemaClearSchemaDefaults(schema);
18228 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018229 if ((targetNs != NULL) &&
18230 xmlStrEqual(targetNs, xmlSchemaNs)) {
18231 /*
18232 * We are parsing the schema for schema!
18233 */
18234 vctxt->pctxt->isS4S = 1;
18235 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018236 /* schema->nbCurItems = 0; */
18237 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018238 pctxt->ctxtType = NULL;
18239 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018240
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018241 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18242 if (pctxt->nberrors != 0) {
18243 vctxt->nberrors += pctxt->nberrors;
18244 goto finally;
18245 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018246 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018247 if (pctxt->nberrors != 0) {
18248 vctxt->nberrors += pctxt->nberrors;
18249 goto finally;
18250 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018251 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018252 if (pctxt->nberrors != 0)
18253 vctxt->nberrors += pctxt->nberrors;
18254finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018255 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018256 * Set the counter of items.
18257 */
18258 schema->counter = pctxt->counter;
18259 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018260 * Free the list of assembled components.
18261 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018262 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018263 /*
18264 * Restore the context & schema.
18265 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018266 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018267 schema->flags = oldflags;
18268 schema->targetNamespace = oldtns;
18269 schema->doc = olddoc;
18270 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018271 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018272 return (ret);
18273}
18274
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018275static xmlSchemaAttrInfoPtr
18276xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18277 int metaType)
18278{
18279 if (vctxt->nbAttrInfos == 0)
18280 return (NULL);
18281 {
18282 int i;
18283 xmlSchemaAttrInfoPtr iattr;
18284
18285 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18286 iattr = vctxt->attrInfos[i];
18287 if (iattr->metaType == metaType)
18288 return (iattr);
18289 }
18290
18291 }
18292 return (NULL);
18293}
18294
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018296 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018297 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018298 *
18299 * Expands an existing schema by an additional schema using
18300 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18301 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18302 * must be set to 1.
18303 *
18304 * Returns 0 if the new schema is correct, a positive error code
18305 * number otherwise and -1 in case of an internal or API error.
18306 */
18307static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018308xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018309{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018310 const xmlChar *cur, *end;
18311 const xmlChar *nsname = NULL, *location;
18312 int count = 0;
18313 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018314 xmlSchemaAttrInfoPtr iattr;
18315
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018316 /*
18317 * Parse the value; we will assume an even number of values
18318 * to be given (this is how Xerces and XSV work).
18319 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018320 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18321 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18322 if (iattr == NULL)
18323 xmlSchemaGetMetaAttrInfo(vctxt,
18324 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18325 if (iattr == NULL)
18326 return (0);
18327 cur = iattr->value;
18328 do {
18329 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018330 /*
18331 * Get the namespace name.
18332 */
18333 while (IS_BLANK_CH(*cur))
18334 cur++;
18335 end = cur;
18336 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18337 end++;
18338 if (end == cur)
18339 break;
18340 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018341 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018342 cur = end;
18343 }
18344 /*
18345 * Get the URI.
18346 */
18347 while (IS_BLANK_CH(*cur))
18348 cur++;
18349 end = cur;
18350 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18351 end++;
18352 if (end == cur)
18353 break;
18354 count++;
18355 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018356 cur = end;
18357 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18358 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018359 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018360 VERROR_INT("xmlSchemaAssembleByXSI",
18361 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018362 return (-1);
18363 }
18364 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365 return (ret);
18366}
18367
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018368#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018369
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018370static const xmlChar *
18371xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18372 const xmlChar *prefix)
18373{
18374 if (vctxt->sax != NULL) {
18375 int i, j;
18376 xmlSchemaNodeInfoPtr inode;
18377
18378 for (i = vctxt->depth; i >= 0; i--) {
18379 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18380 inode = vctxt->elemInfos[i];
18381 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18382 if (((prefix == NULL) &&
18383 (inode->nsBindings[j] == NULL)) ||
18384 ((prefix != NULL) && xmlStrEqual(prefix,
18385 inode->nsBindings[j]))) {
18386
18387 /*
18388 * Note that the namespace bindings are already
18389 * in a string dict.
18390 */
18391 return (inode->nsBindings[j+1]);
18392 }
18393 }
18394 }
18395 }
18396 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018397#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018398 } else if (vctxt->reader != NULL) {
18399 xmlChar *nsName;
18400
18401 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18402 if (nsName != NULL) {
18403 const xmlChar *ret;
18404
18405 VAL_CREATE_DICT;
18406 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18407 xmlFree(nsName);
18408 return (ret);
18409 } else
18410 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018411#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018412 } else {
18413 xmlNsPtr ns;
18414
18415 if ((vctxt->inode->node == NULL) ||
18416 (vctxt->inode->node->doc == NULL)) {
18417 VERROR_INT("xmlSchemaLookupNamespace",
18418 "no node or node's doc avaliable");
18419 return (NULL);
18420 }
18421 ns = xmlSearchNs(vctxt->inode->node->doc,
18422 vctxt->inode->node, prefix);
18423 if (ns != NULL)
18424 return (ns->href);
18425 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018426 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018427}
18428
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018429/*
18430* This one works on the schema of the validation context.
18431*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018432static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018433xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18434 xmlSchemaPtr schema,
18435 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018436 const xmlChar *value,
18437 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018438 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018439{
18440 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018441
18442 if (vctxt && (vctxt->schema == NULL)) {
18443 VERROR_INT("xmlSchemaValidateNotation",
18444 "a schema is needed on the validation context");
18445 return (-1);
18446 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018447 ret = xmlValidateQName(value, 1);
18448 if (ret != 0)
18449 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018450 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018451 xmlChar *localName = NULL;
18452 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018453
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018454 localName = xmlSplitQName2(value, &prefix);
18455 if (prefix != NULL) {
18456 const xmlChar *nsName = NULL;
18457
18458 if (vctxt != NULL)
18459 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18460 else if (node != NULL) {
18461 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18462 if (ns != NULL)
18463 nsName = ns->href;
18464 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018465 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018466 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018467 return (1);
18468 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018469 if (nsName == NULL) {
18470 xmlFree(prefix);
18471 xmlFree(localName);
18472 return (1);
18473 }
18474 if (xmlHashLookup2(schema->notaDecl, localName,
18475 nsName) != NULL) {
18476 if (valNeeded && (val != NULL)) {
18477 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18478 BAD_CAST xmlStrdup(nsName));
18479 if (*val == NULL)
18480 ret = -1;
18481 }
18482 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018483 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018484 xmlFree(prefix);
18485 xmlFree(localName);
18486 } else {
18487 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18488 if (valNeeded && (val != NULL)) {
18489 (*val) = xmlSchemaNewNOTATIONValue(
18490 BAD_CAST xmlStrdup(value), NULL);
18491 if (*val == NULL)
18492 ret = -1;
18493 }
18494 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018495 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018496 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018497 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018498 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018499}
18500
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018501/************************************************************************
18502 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018503 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018504 * *
18505 ************************************************************************/
18506
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018507/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018508 * xmlSchemaAugmentIDC:
18509 * @idcDef: the IDC definition
18510 *
18511 * Creates an augmented IDC definition item.
18512 *
18513 * Returns the item, or NULL on internal errors.
18514 */
18515static void
18516xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18517 xmlSchemaValidCtxtPtr vctxt)
18518{
18519 xmlSchemaIDCAugPtr aidc;
18520
18521 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18522 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018523 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018524 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18525 NULL);
18526 return;
18527 }
18528 aidc->bubbleDepth = -1;
18529 aidc->def = idcDef;
18530 aidc->next = NULL;
18531 if (vctxt->aidcs == NULL)
18532 vctxt->aidcs = aidc;
18533 else {
18534 aidc->next = vctxt->aidcs;
18535 vctxt->aidcs = aidc;
18536 }
18537}
18538
18539/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018540 * xmlSchemaIDCNewBinding:
18541 * @idcDef: the IDC definition of this binding
18542 *
18543 * Creates a new IDC binding.
18544 *
18545 * Returns the new binding in case of succeeded, NULL on internal errors.
18546 */
18547static xmlSchemaPSVIIDCBindingPtr
18548xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18549{
18550 xmlSchemaPSVIIDCBindingPtr ret;
18551
18552 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18553 sizeof(xmlSchemaPSVIIDCBinding));
18554 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018555 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018556 "allocating a PSVI IDC binding item", NULL);
18557 return (NULL);
18558 }
18559 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18560 ret->definition = idcDef;
18561 return (ret);
18562}
18563
18564/**
18565 * xmlSchemaIDCStoreNodeTableItem:
18566 * @vctxt: the WXS validation context
18567 * @item: the IDC node table item
18568 *
18569 * The validation context is used to store an IDC node table items.
18570 * They are stored to avoid copying them if IDC node-tables are merged
18571 * with corresponding parent IDC node-tables (bubbling).
18572 *
18573 * Returns 0 if succeeded, -1 on internal errors.
18574 */
18575static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018576xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018577 xmlSchemaPSVIIDCNodePtr item)
18578{
18579 /*
18580 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018581 */
18582 if (vctxt->idcNodes == NULL) {
18583 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018584 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18585 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018586 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018587 "allocating the IDC node table item list", NULL);
18588 return (-1);
18589 }
18590 vctxt->sizeIdcNodes = 20;
18591 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18592 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018593 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18594 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018595 sizeof(xmlSchemaPSVIIDCNodePtr));
18596 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018597 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018598 "re-allocating the IDC node table item list", NULL);
18599 return (-1);
18600 }
18601 }
18602 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018603
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018604 return (0);
18605}
18606
18607/**
18608 * xmlSchemaIDCStoreKey:
18609 * @vctxt: the WXS validation context
18610 * @item: the IDC key
18611 *
18612 * The validation context is used to store an IDC key.
18613 *
18614 * Returns 0 if succeeded, -1 on internal errors.
18615 */
18616static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018617xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018618 xmlSchemaPSVIIDCKeyPtr key)
18619{
18620 /*
18621 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018622 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018623 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018624 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018625 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18626 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018627 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018628 "allocating the IDC key storage list", NULL);
18629 return (-1);
18630 }
18631 vctxt->sizeIdcKeys = 40;
18632 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18633 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018634 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18635 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018636 sizeof(xmlSchemaPSVIIDCKeyPtr));
18637 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018638 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018639 "re-allocating the IDC key storage list", NULL);
18640 return (-1);
18641 }
18642 }
18643 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018644
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018645 return (0);
18646}
18647
18648/**
18649 * xmlSchemaIDCAppendNodeTableItem:
18650 * @bind: the IDC binding
18651 * @ntItem: the node-table item
18652 *
18653 * Appends the IDC node-table item to the binding.
18654 *
18655 * Returns 0 on success and -1 on internal errors.
18656 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018657static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018658xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18659 xmlSchemaPSVIIDCNodePtr ntItem)
18660{
18661 if (bind->nodeTable == NULL) {
18662 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018663 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018664 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18665 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018666 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018667 "allocating an array of IDC node-table items", NULL);
18668 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018669 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018670 } else if (bind->sizeNodes <= bind->nbNodes) {
18671 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18673 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018674 sizeof(xmlSchemaPSVIIDCNodePtr));
18675 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018676 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018677 "re-allocating an array of IDC node-table items", NULL);
18678 return(-1);
18679 }
18680 }
18681 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018682 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018683}
18684
18685/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018686 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018687 * @vctxt: the WXS validation context
18688 * @matcher: the IDC matcher
18689 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018690 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018691 * of the given matcher. If none found, a new one is created
18692 * and added to the IDC table.
18693 *
18694 * Returns an IDC binding or NULL on internal errors.
18695 */
18696static xmlSchemaPSVIIDCBindingPtr
18697xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18698 xmlSchemaIDCMatcherPtr matcher)
18699{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018700 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018701
18702 info = vctxt->elemInfos[matcher->depth];
18703
18704 if (info->idcTable == NULL) {
18705 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18706 if (info->idcTable == NULL)
18707 return (NULL);
18708 return(info->idcTable);
18709 } else {
18710 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018711
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018712 bind = info->idcTable;
18713 do {
18714 if (bind->definition == matcher->aidc->def)
18715 return(bind);
18716 if (bind->next == NULL) {
18717 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18718 if (bind->next == NULL)
18719 return (NULL);
18720 return(bind->next);
18721 }
18722 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018723 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018724 }
18725 return (NULL);
18726}
18727
18728/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018729 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018730 * @key: the IDC key
18731 *
18732 * Frees an IDC key together with its compiled value.
18733 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018734static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018735xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18736{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018737 if (key->val != NULL)
18738 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018739 xmlFree(key);
18740}
18741
18742/**
18743 * xmlSchemaIDCFreeBinding:
18744 *
18745 * Frees an IDC binding. Note that the node table-items
18746 * are not freed.
18747 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018748static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018749xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18750{
18751 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018752 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18753 int i;
18754 /*
18755 * Node-table items for keyrefs are not stored globally
18756 * to the validation context, since they are not bubbled.
18757 * We need to free them here.
18758 */
18759 for (i = 0; i < bind->nbNodes; i++) {
18760 xmlFree(bind->nodeTable[i]->keys);
18761 xmlFree(bind->nodeTable[i]);
18762 }
18763 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018764 xmlFree(bind->nodeTable);
18765 }
18766 xmlFree(bind);
18767}
18768
18769/**
18770 * xmlSchemaIDCFreeIDCTable:
18771 * @bind: the first IDC binding in the list
18772 *
18773 * Frees an IDC table, i.e. all the IDC bindings in the list.
18774 */
18775static void
18776xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18777{
18778 xmlSchemaPSVIIDCBindingPtr prev;
18779
18780 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018781 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018782 bind = bind->next;
18783 xmlSchemaIDCFreeBinding(prev);
18784 }
18785}
18786
18787/**
18788 * xmlSchemaIDCFreeMatcherList:
18789 * @matcher: the first IDC matcher in the list
18790 *
18791 * Frees a list of IDC matchers.
18792 */
18793static void
18794xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18795{
18796 xmlSchemaIDCMatcherPtr next;
18797
18798 while (matcher != NULL) {
18799 next = matcher->next;
18800 if (matcher->keySeqs != NULL) {
18801 int i;
18802 for (i = 0; i < matcher->sizeKeySeqs; i++)
18803 if (matcher->keySeqs[i] != NULL)
18804 xmlFree(matcher->keySeqs[i]);
18805 xmlFree(matcher->keySeqs);
18806 }
18807 xmlFree(matcher);
18808 matcher = next;
18809 }
18810}
18811
18812/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018813 * xmlSchemaIDCAddStateObject:
18814 * @vctxt: the WXS validation context
18815 * @matcher: the IDC matcher
18816 * @sel: the XPath information
18817 * @parent: the parent "selector" state object if any
18818 * @type: "selector" or "field"
18819 *
18820 * Creates/reuses and activates state objects for the given
18821 * XPath information; if the XPath expression consists of unions,
18822 * multiple state objects are created for every unioned expression.
18823 *
18824 * Returns 0 on success and -1 on internal errors.
18825 */
18826static int
18827xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18828 xmlSchemaIDCMatcherPtr matcher,
18829 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018830 int type)
18831{
18832 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018833
18834 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018835 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018836 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018837 if (vctxt->xpathStatePool != NULL) {
18838 sto = vctxt->xpathStatePool;
18839 vctxt->xpathStatePool = sto->next;
18840 sto->next = NULL;
18841 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018842 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018843 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018844 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018845 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18846 if (sto == NULL) {
18847 xmlSchemaVErrMemory(NULL,
18848 "allocating an IDC state object", NULL);
18849 return (-1);
18850 }
18851 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18852 }
18853 /*
18854 * Add to global list.
18855 */
18856 if (vctxt->xpathStates != NULL)
18857 sto->next = vctxt->xpathStates;
18858 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018859
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018860 /*
18861 * Free the old xpath validation context.
18862 */
18863 if (sto->xpathCtxt != NULL)
18864 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18865
18866 /*
18867 * Create a new XPath (pattern) validation context.
18868 */
18869 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18870 (xmlPatternPtr) sel->xpathComp);
18871 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018872 VERROR_INT("xmlSchemaIDCAddStateObject",
18873 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018874 return (-1);
18875 }
18876 sto->type = type;
18877 sto->depth = vctxt->depth;
18878 sto->matcher = matcher;
18879 sto->sel = sel;
18880 sto->nbHistory = 0;
18881
18882#if DEBUG_IDC
18883 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18884 sto->sel->xpath);
18885#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018886 return (0);
18887}
18888
18889/**
18890 * xmlSchemaXPathEvaluate:
18891 * @vctxt: the WXS validation context
18892 * @nodeType: the nodeType of the current node
18893 *
18894 * Evaluates all active XPath state objects.
18895 *
18896 * Returns the number of IC "field" state objects which resolved to
18897 * this node, 0 if none resolved and -1 on internal errors.
18898 */
18899static int
18900xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018901 xmlElementType nodeType)
18902{
18903 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018904 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018905
18906 if (vctxt->xpathStates == NULL)
18907 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018908
18909 if (nodeType == XML_ATTRIBUTE_NODE)
18910 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018911#if DEBUG_IDC
18912 {
18913 xmlChar *str = NULL;
18914 xmlGenericError(xmlGenericErrorContext,
18915 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018916 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18917 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018918 FREE_AND_NULL(str)
18919 }
18920#endif
18921 /*
18922 * Process all active XPath state objects.
18923 */
18924 first = vctxt->xpathStates;
18925 sto = first;
18926 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018927#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018928 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018929 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18930 sto->matcher->aidc->def->name, sto->sel->xpath);
18931 else
18932 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18933 sto->matcher->aidc->def->name, sto->sel->xpath);
18934#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018935 if (nodeType == XML_ELEMENT_NODE)
18936 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018937 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018938 else
18939 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018940 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018941
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018942 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018943 VERROR_INT("xmlSchemaXPathEvaluate",
18944 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018945 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018946 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018947 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018948 goto next_sto;
18949 /*
18950 * Full match.
18951 */
18952#if DEBUG_IDC
18953 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018954 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018955#endif
18956 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018957 * Register a match in the state object history.
18958 */
18959 if (sto->history == NULL) {
18960 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18961 if (sto->history == NULL) {
18962 xmlSchemaVErrMemory(NULL,
18963 "allocating the state object history", NULL);
18964 return(-1);
18965 }
18966 sto->sizeHistory = 10;
18967 } else if (sto->sizeHistory <= sto->nbHistory) {
18968 sto->sizeHistory *= 2;
18969 sto->history = (int *) xmlRealloc(sto->history,
18970 sto->sizeHistory * sizeof(int));
18971 if (sto->history == NULL) {
18972 xmlSchemaVErrMemory(NULL,
18973 "re-allocating the state object history", NULL);
18974 return(-1);
18975 }
18976 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018977 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018978
18979#ifdef DEBUG_IDC
18980 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18981 vctxt->depth);
18982#endif
18983
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018984 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18985 xmlSchemaIDCSelectPtr sel;
18986 /*
18987 * Activate state objects for the IDC fields of
18988 * the IDC selector.
18989 */
18990#if DEBUG_IDC
18991 xmlGenericError(xmlGenericErrorContext, "IDC: "
18992 "activating field states\n");
18993#endif
18994 sel = sto->matcher->aidc->def->fields;
18995 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018996 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18997 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18998 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018999 sel = sel->next;
19000 }
19001 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19002 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019003 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019004 */
19005#if DEBUG_IDC
19006 xmlGenericError(xmlGenericErrorContext,
19007 "IDC: key found\n");
19008#endif
19009 /*
19010 * Notify that the character value of this node is
19011 * needed.
19012 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019013 if (resolved == 0) {
19014 if ((vctxt->inode->flags &
19015 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19016 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19017 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019018 resolved++;
19019 }
19020next_sto:
19021 if (sto->next == NULL) {
19022 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019023 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019024 */
19025 head = first;
19026 sto = vctxt->xpathStates;
19027 } else
19028 sto = sto->next;
19029 }
19030 return (resolved);
19031}
19032
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019033static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019034xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019035 xmlChar **buf,
19036 xmlSchemaPSVIIDCKeyPtr *seq,
19037 int count)
19038{
19039 int i, res;
19040 const xmlChar *value = NULL;
19041
19042 *buf = xmlStrdup(BAD_CAST "[");
19043 for (i = 0; i < count; i++) {
19044 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019045 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19046 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019047 if (res == 0)
19048 *buf = xmlStrcat(*buf, value);
19049 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019050 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19051 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019052 *buf = xmlStrcat(*buf, BAD_CAST "???");
19053 }
19054 if (i < count -1)
19055 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19056 else
19057 *buf = xmlStrcat(*buf, BAD_CAST "'");
19058 if (value != NULL) {
19059 xmlFree((xmlChar *) value);
19060 value = NULL;
19061 }
19062 }
19063 *buf = xmlStrcat(*buf, BAD_CAST "]");
19064
19065 return (BAD_CAST *buf);
19066}
19067
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019068/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019069 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019070 * @vctxt: the WXS validation context
19071 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019072 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019073 *
19074 * Processes and pops the history items of the IDC state objects.
19075 * IDC key-sequences are validated/created on IDC bindings.
19076 *
19077 * Returns 0 on success and -1 on internal errors.
19078 */
19079static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019080xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019081 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019082{
19083 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019084 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019085 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019086 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019087
19088 if (vctxt->xpathStates == NULL)
19089 return (0);
19090 sto = vctxt->xpathStates;
19091
19092#if DEBUG_IDC
19093 {
19094 xmlChar *str = NULL;
19095 xmlGenericError(xmlGenericErrorContext,
19096 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019097 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19098 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019099 FREE_AND_NULL(str)
19100 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019101#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019102 /*
19103 * Evaluate the state objects.
19104 */
19105 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019106 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19107 if (res == -1) {
19108 VERROR_INT("xmlSchemaXPathProcessHistory",
19109 "calling xmlStreamPop()");
19110 return (-1);
19111 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019112#if DEBUG_IDC
19113 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19114 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019115#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019116 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019117 goto deregister_check;
19118
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019119 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019120
19121 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019122 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019123 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019124 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019125 sto = sto->next;
19126 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019127 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019128 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19129 if (! IS_SIMPLE_TYPE(type)) {
19130 /*
19131 * Not qualified if the field resolves to a node of non
19132 * simple type.
19133 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019134 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19135 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019136 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19137 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019138 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019139
19140 sto->nbHistory--;
19141 goto deregister_check;
19142 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019143 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019144 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019145 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019146 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019148 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019149 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19150 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019151 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019152 sto->nbHistory--;
19153 goto deregister_check;
19154 } else {
19155 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19156 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019157 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019158
19159 /*
19160 * The key will be anchored on the matcher's list of
19161 * key-sequences. The position in this list is determined
19162 * by the target node's depth relative to the matcher's
19163 * depth of creation (i.e. the depth of the scope element).
19164 */
19165 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019166 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019167
19168 /*
19169 * Create/grow the array of key-sequences.
19170 */
19171 if (matcher->keySeqs == NULL) {
19172 if (pos > 9)
19173 matcher->sizeKeySeqs = pos * 2;
19174 else
19175 matcher->sizeKeySeqs = 10;
19176 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19177 xmlMalloc(matcher->sizeKeySeqs *
19178 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19179 if (matcher->keySeqs == NULL) {
19180 xmlSchemaVErrMemory(NULL,
19181 "allocating an array of key-sequences",
19182 NULL);
19183 return(-1);
19184 }
19185 memset(matcher->keySeqs, 0,
19186 matcher->sizeKeySeqs *
19187 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19188 } else if (pos >= matcher->sizeKeySeqs) {
19189 int i = matcher->sizeKeySeqs;
19190
19191 matcher->sizeKeySeqs *= 2;
19192 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19193 xmlRealloc(matcher->keySeqs,
19194 matcher->sizeKeySeqs *
19195 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019196 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019197 xmlSchemaVErrMemory(NULL,
19198 "reallocating an array of key-sequences",
19199 NULL);
19200 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019201 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019202 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019203 * The array needs to be NULLed.
19204 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019205 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019206 for (; i < matcher->sizeKeySeqs; i++)
19207 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019208 }
19209
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019210 /*
19211 * Get/create the key-sequence.
19212 */
19213 keySeq = matcher->keySeqs[pos];
19214 if (keySeq == NULL) {
19215 goto create_sequence;
19216 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019217 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019218 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019219 * cvc-identity-constraint:
19220 * 3 For each node in the ·target node set· all
19221 * of the {fields}, with that node as the context
19222 * node, evaluate to either an empty node-set or
19223 * a node-set with exactly one member, which must
19224 * have a simple type.
19225 *
19226 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019228 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19229 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019230 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019231 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019232 "with more than one member",
19233 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019234 sto->nbHistory--;
19235 goto deregister_check;
19236 } else {
19237 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019238 }
19239 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019240
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019241create_sequence:
19242 /*
19243 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019244 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019245 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19246 matcher->aidc->def->nbFields *
19247 sizeof(xmlSchemaPSVIIDCKeyPtr));
19248 if (keySeq == NULL) {
19249 xmlSchemaVErrMemory(NULL,
19250 "allocating an IDC key-sequence", NULL);
19251 return(-1);
19252 }
19253 memset(keySeq, 0, matcher->aidc->def->nbFields *
19254 sizeof(xmlSchemaPSVIIDCKeyPtr));
19255 matcher->keySeqs[pos] = keySeq;
19256create_key:
19257 /*
19258 * Created a key once per node only.
19259 */
19260 if (key == NULL) {
19261 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19262 sizeof(xmlSchemaPSVIIDCKey));
19263 if (key == NULL) {
19264 xmlSchemaVErrMemory(NULL,
19265 "allocating a IDC key", NULL);
19266 xmlFree(keySeq);
19267 matcher->keySeqs[pos] = NULL;
19268 return(-1);
19269 }
19270 /*
19271 * Consume the compiled value.
19272 */
19273 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019274 key->val = vctxt->inode->val;
19275 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019276 /*
19277 * Store the key in a global list.
19278 */
19279 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19280 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019281 return (-1);
19282 }
19283 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019284 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019285 }
19286 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019287
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019288 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19289 xmlSchemaPSVIIDCBindingPtr bind;
19290 xmlSchemaPSVIIDCNodePtr ntItem;
19291 xmlSchemaIDCMatcherPtr matcher;
19292 xmlSchemaIDCPtr idc;
19293 int pos, i, j, nbKeys;
19294 /*
19295 * Here we have the following scenario:
19296 * An IDC 'selector' state object resolved to a target node,
19297 * during the time this target node was in the
19298 * ancestor-or-self axis, the 'field' state object(s) looked
19299 * out for matching nodes to create a key-sequence for this
19300 * target node. Now we are back to this target node and need
19301 * to put the key-sequence, together with the target node
19302 * itself, into the node-table of the corresponding IDC
19303 * binding.
19304 */
19305 matcher = sto->matcher;
19306 idc = matcher->aidc->def;
19307 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019308 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019309 /*
19310 * Check if the matcher has any key-sequences at all, plus
19311 * if it has a key-sequence for the current target node.
19312 */
19313 if ((matcher->keySeqs == NULL) ||
19314 (matcher->sizeKeySeqs <= pos)) {
19315 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19316 goto selector_key_error;
19317 else
19318 goto selector_leave;
19319 }
19320
19321 keySeq = &(matcher->keySeqs[pos]);
19322 if (*keySeq == NULL) {
19323 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19324 goto selector_key_error;
19325 else
19326 goto selector_leave;
19327 }
19328
19329 for (i = 0; i < nbKeys; i++) {
19330 if ((*keySeq)[i] == NULL) {
19331 /*
19332 * Not qualified, if not all fields did resolve.
19333 */
19334 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19335 /*
19336 * All fields of a "key" IDC must resolve.
19337 */
19338 goto selector_key_error;
19339 }
19340 goto selector_leave;
19341 }
19342 }
19343 /*
19344 * All fields did resolve.
19345 */
19346
19347 /*
19348 * 4.1 If the {identity-constraint category} is unique(/key),
19349 * then no two members of the ·qualified node set· have
19350 * ·key-sequences· whose members are pairwise equal, as
19351 * defined by Equal in [XML Schemas: Datatypes].
19352 *
19353 * Get the IDC binding from the matcher and check for
19354 * duplicate key-sequences.
19355 */
19356 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19357 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19358 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019359 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019360
19361 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019362 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019363 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019364 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019365 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019366 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019367 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019368 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019369 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019370 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019371 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019372 if (res == -1) {
19373 return (-1);
19374 } else if (res == 0)
19375 break;
19376 }
19377 if (res == 1) {
19378 /*
19379 * Duplicate found.
19380 */
19381 break;
19382 }
19383 i++;
19384 } while (i < bind->nbNodes);
19385 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019386 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019387 /*
19388 * TODO: Try to report the key-sequence.
19389 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019390 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19391 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019392 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019393 "Duplicate key-sequence %s",
19394 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19395 (*keySeq), nbKeys), NULL);
19396 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019397 goto selector_leave;
19398 }
19399 }
19400 /*
19401 * Add a node-table item to the IDC binding.
19402 */
19403 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19404 sizeof(xmlSchemaPSVIIDCNode));
19405 if (ntItem == NULL) {
19406 xmlSchemaVErrMemory(NULL,
19407 "allocating an IDC node-table item", NULL);
19408 xmlFree(*keySeq);
19409 *keySeq = NULL;
19410 return(-1);
19411 }
19412 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19413
19414 /*
19415 * Store the node-table item on global list.
19416 */
19417 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19418 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19419 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019420 xmlFree(*keySeq);
19421 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019422 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019423 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019424 }
19425 /*
19426 * Init the node-table item. Consume the key-sequence.
19427 */
19428 ntItem->node = vctxt->node;
19429 ntItem->keys = *keySeq;
19430 *keySeq = NULL;
19431 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19432 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19433 /*
19434 * Free the item, since keyref items won't be
19435 * put on a global list.
19436 */
19437 xmlFree(ntItem->keys);
19438 xmlFree(ntItem);
19439 }
19440 return (-1);
19441 }
19442
19443 goto selector_leave;
19444selector_key_error:
19445 /*
19446 * 4.2.1 (KEY) The ·target node set· and the
19447 * ·qualified node set· are equal, that is, every
19448 * member of the ·target node set· is also a member
19449 * of the ·qualified node set· and vice versa.
19450 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019451 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19452 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019453selector_leave:
19454 /*
19455 * Free the key-sequence if not added to the IDC table.
19456 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019457 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019458 xmlFree(*keySeq);
19459 *keySeq = NULL;
19460 }
19461 } /* if selector */
19462
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019463 sto->nbHistory--;
19464
19465deregister_check:
19466 /*
19467 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019468 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019469 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019470#if DEBUG_IDC
19471 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19472 sto->sel->xpath);
19473#endif
19474 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019475 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019476 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019477 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019478 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019479 nextsto = sto->next;
19480 /*
19481 * Unlink from the list of active XPath state objects.
19482 */
19483 vctxt->xpathStates = sto->next;
19484 sto->next = vctxt->xpathStatePool;
19485 /*
19486 * Link it to the pool of reusable state objects.
19487 */
19488 vctxt->xpathStatePool = sto;
19489 sto = nextsto;
19490 } else
19491 sto = sto->next;
19492 } /* while (sto != NULL) */
19493 return (0);
19494}
19495
19496/**
19497 * xmlSchemaIDCRegisterMatchers:
19498 * @vctxt: the WXS validation context
19499 * @elemDecl: the element declaration
19500 *
19501 * Creates helper objects to evaluate IDC selectors/fields
19502 * successively.
19503 *
19504 * Returns 0 if OK and -1 on internal errors.
19505 */
19506static int
19507xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19508 xmlSchemaElementPtr elemDecl)
19509{
19510 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19511 xmlSchemaIDCPtr idc, refIdc;
19512 xmlSchemaIDCAugPtr aidc;
19513
19514 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19515 if (idc == NULL)
19516 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019517
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019518#if DEBUG_IDC
19519 {
19520 xmlChar *str = NULL;
19521 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019522 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019523 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19524 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019525 FREE_AND_NULL(str)
19526 }
19527#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019528 if (vctxt->inode->idcMatchers != NULL) {
19529 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19530 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019531 return (-1);
19532 }
19533 do {
19534 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19535 /*
19536 * Since IDCs bubbles are expensive we need to know the
19537 * depth at which the bubbles should stop; this will be
19538 * the depth of the top-most keyref IDC. If no keyref
19539 * references a key/unique IDC, the bubbleDepth will
19540 * be -1, indicating that no bubbles are needed.
19541 */
19542 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19543 if (refIdc != NULL) {
19544 /*
19545 * Lookup the augmented IDC.
19546 */
19547 aidc = vctxt->aidcs;
19548 while (aidc != NULL) {
19549 if (aidc->def == refIdc)
19550 break;
19551 aidc = aidc->next;
19552 }
19553 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019554 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019555 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019556 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019557 return (-1);
19558 }
19559 if ((aidc->bubbleDepth == -1) ||
19560 (vctxt->depth < aidc->bubbleDepth))
19561 aidc->bubbleDepth = vctxt->depth;
19562 }
19563 }
19564 /*
19565 * Lookup the augmented IDC item for the IDC definition.
19566 */
19567 aidc = vctxt->aidcs;
19568 while (aidc != NULL) {
19569 if (aidc->def == idc)
19570 break;
19571 aidc = aidc->next;
19572 }
19573 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019574 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19575 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019576 return (-1);
19577 }
19578 /*
19579 * Create an IDC matcher for every IDC definition.
19580 */
19581 matcher = (xmlSchemaIDCMatcherPtr)
19582 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19583 if (matcher == NULL) {
19584 xmlSchemaVErrMemory(vctxt,
19585 "allocating an IDC matcher", NULL);
19586 return (-1);
19587 }
19588 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19589 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019590 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019591 else
19592 last->next = matcher;
19593 last = matcher;
19594
19595 matcher->type = IDC_MATCHER;
19596 matcher->depth = vctxt->depth;
19597 matcher->aidc = aidc;
19598#if DEBUG_IDC
19599 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19600#endif
19601 /*
19602 * Init the automaton state object.
19603 */
19604 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019605 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019606 return (-1);
19607
19608 idc = idc->next;
19609 } while (idc != NULL);
19610 return (0);
19611}
19612
19613/**
19614 * xmlSchemaBubbleIDCNodeTables:
19615 * @depth: the current tree depth
19616 *
19617 * Merges IDC bindings of an element at @depth into the corresponding IDC
19618 * bindings of its parent element. If a duplicate note-table entry is found,
19619 * both, the parent node-table entry and child entry are discarded from the
19620 * node-table of the parent.
19621 *
19622 * Returns 0 if OK and -1 on internal errors.
19623 */
19624static int
19625xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19626{
19627 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019628 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19629 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019630 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19631 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019632 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019633 int duplTop;
19634
19635 /*
19636 * The node table has the following sections:
19637 *
19638 * O --> old node-table entries (first)
19639 * O
19640 * + --> new node-table entries
19641 * +
19642 * % --> new duplicate node-table entries
19643 * %
19644 * # --> old duplicate node-table entries
19645 * # (last)
19646 *
19647 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019648 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019649 if (bind == NULL) {
19650 /* Fine, no table, no bubbles. */
19651 return (0);
19652 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019653
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019654 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19655 /*
19656 * Walk all bindings; create new or add to existing bindings.
19657 * Remove duplicate key-sequences.
19658 */
19659start_binding:
19660 while (bind != NULL) {
19661 /*
19662 * Skip keyref IDCs.
19663 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019664 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19665 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019666 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019667 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019668 /*
19669 * Check if the key/unique IDC table needs to be bubbled.
19670 */
19671 aidc = vctxt->aidcs;
19672 do {
19673 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019674 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019675 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019676 bind = bind->next;
19677 goto start_binding;
19678 }
19679 break;
19680 }
19681 aidc = aidc->next;
19682 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019683
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019684 if (parTable != NULL)
19685 parBind = *parTable;
19686 while (parBind != NULL) {
19687 /*
19688 * Search a matching parent binding for the
19689 * IDC definition.
19690 */
19691 if (parBind->definition == bind->definition) {
19692
19693 /*
19694 * Compare every node-table entry of the child node,
19695 * i.e. the key-sequence within, ...
19696 */
19697 oldNum = parBind->nbNodes; /* Skip newly added items. */
19698 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019699 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019700
19701 for (i = 0; i < bind->nbNodes; i++) {
19702 node = bind->nodeTable[i];
19703 if (node == NULL)
19704 continue;
19705 /*
19706 * ...with every key-sequence of the parent node, already
19707 * evaluated to be a duplicate key-sequence.
19708 */
19709 if (parBind->nbDupls != 0) {
19710 j = bind->nbNodes + newDupls;
19711 while (j < duplTop) {
19712 parNode = parBind->nodeTable[j];
19713 for (k = 0; k < bind->definition->nbFields; k++) {
19714 key = node->keys[k];
19715 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019716 ret = xmlSchemaAreValuesEqual(key->val,
19717 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019718 if (ret == -1) {
19719 /* TODO: Internal error */
19720 return(-1);
19721 } else if (ret == 0)
19722 break;
19723
19724 }
19725 if (ret == 1)
19726 /* Duplicate found. */
19727 break;
19728 j++;
19729 }
19730 if (j != duplTop) {
19731 /* Duplicate found. */
19732 continue;
19733 }
19734 }
19735 /*
19736 * ... and with every key-sequence of the parent node.
19737 */
19738 j = 0;
19739 while (j < oldNum) {
19740 parNode = parBind->nodeTable[j];
19741 /*
19742 * Compare key by key.
19743 */
19744 for (k = 0; k < parBind->definition->nbFields; k++) {
19745 key = node->keys[k];
19746 parKey = parNode->keys[k];
19747
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019748 ret = xmlSchemaAreValuesEqual(key->val,
19749 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019750 if (ret == -1) {
19751 /* TODO: Internal error */
19752 } else if (ret == 0)
19753 break;
19754
19755 }
19756 if (ret == 1)
19757 /*
19758 * The key-sequences are equal.
19759 */
19760 break;
19761 j++;
19762 }
19763 if (j != oldNum) {
19764 /*
19765 * Handle duplicates.
19766 */
19767 newDupls++;
19768 oldNum--;
19769 parBind->nbNodes--;
19770 /*
19771 * Move last old item to pos of duplicate.
19772 */
19773 parBind->nodeTable[j] =
19774 parBind->nodeTable[oldNum];
19775
19776 if (parBind->nbNodes != oldNum) {
19777 /*
19778 * If new items exist, move last new item to
19779 * last of old items.
19780 */
19781 parBind->nodeTable[oldNum] =
19782 parBind->nodeTable[parBind->nbNodes];
19783 }
19784 /*
19785 * Move duplicate to last pos of new/old items.
19786 */
19787 parBind->nodeTable[parBind->nbNodes] = parNode;
19788
19789 } else {
19790 /*
19791 * Add the node-table entry (node and key-sequence) of
19792 * the child node to the node table of the parent node.
19793 */
19794 if (parBind->nodeTable == NULL) {
19795 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019796 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019797 if (parBind->nodeTable == NULL) {
19798 xmlSchemaVErrMemory(NULL,
19799 "allocating IDC list of node-table items", NULL);
19800 return(-1);
19801 }
19802 parBind->sizeNodes = 1;
19803 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019804 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019805 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19806 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19807 sizeof(xmlSchemaPSVIIDCNodePtr));
19808 if (parBind->nodeTable == NULL) {
19809 xmlSchemaVErrMemory(NULL,
19810 "re-allocating IDC list of node-table items", NULL);
19811 return(-1);
19812 }
19813 }
19814
19815 /*
19816 * Move first old duplicate to last position
19817 * of old duplicates +1.
19818 */
19819 if (parBind->nbDupls != 0) {
19820 parBind->nodeTable[duplTop] =
19821 parBind->nodeTable[parBind->nbNodes + newDupls];
19822 }
19823 /*
19824 * Move first new duplicate to last position of
19825 * new duplicates +1.
19826 */
19827 if (newDupls != 0) {
19828 parBind->nodeTable[parBind->nbNodes + newDupls] =
19829 parBind->nodeTable[parBind->nbNodes];
19830 }
19831 /*
19832 * Append the new node-table entry to the 'new node-table
19833 * entries' section.
19834 */
19835 parBind->nodeTable[parBind->nbNodes] = node;
19836 parBind->nbNodes++;
19837 duplTop++;
19838 }
19839 }
19840 parBind->nbDupls += newDupls;
19841 break;
19842 }
19843 if (parBind->next == NULL)
19844 lastParBind = parBind;
19845 parBind = parBind->next;
19846 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019847 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019848 /*
19849 * No binding for the IDC was found: create a new one and
19850 * copy all node-tables.
19851 */
19852 parBind = xmlSchemaIDCNewBinding(bind->definition);
19853 if (parBind == NULL)
19854 return(-1);
19855
19856 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19857 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19858 if (parBind->nodeTable == NULL) {
19859 xmlSchemaVErrMemory(NULL,
19860 "allocating an array of IDC node-table items", NULL);
19861 xmlSchemaIDCFreeBinding(parBind);
19862 return(-1);
19863 }
19864 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019865 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019866 memcpy(parBind->nodeTable, bind->nodeTable,
19867 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019868 if (*parTable == NULL)
19869 *parTable = parBind;
19870 else
19871 lastParBind->next = parBind;
19872 }
19873 bind = bind->next;
19874 }
19875 return (0);
19876}
19877
19878/**
19879 * xmlSchemaCheckCVCIDCKeyRef:
19880 * @vctxt: the WXS validation context
19881 * @elemDecl: the element declaration
19882 *
19883 * Check the cvc-idc-keyref constraints.
19884 */
19885static int
19886xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19887{
19888 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19889
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019890 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019891 /*
19892 * Find a keyref.
19893 */
19894 while (refbind != NULL) {
19895 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19896 int i, j, k, res;
19897 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19898 xmlSchemaPSVIIDCKeyPtr refKey, key;
19899
19900 /*
19901 * Find the referred key/unique.
19902 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019903 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019904 do {
19905 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19906 bind->definition)
19907 break;
19908 bind = bind->next;
19909 } while (bind != NULL);
19910
19911 /*
19912 * Search for a matching key-sequences.
19913 */
19914 for (i = 0; i < refbind->nbNodes; i++) {
19915 res = 0;
19916 if (bind != NULL) {
19917 refKeys = refbind->nodeTable[i]->keys;
19918 for (j = 0; j < bind->nbNodes; j++) {
19919 keys = bind->nodeTable[j]->keys;
19920 for (k = 0; k < bind->definition->nbFields; k++) {
19921 refKey = refKeys[k];
19922 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019923 res = xmlSchemaAreValuesEqual(key->val,
19924 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019925 if (res == 0)
19926 break;
19927 else if (res == -1) {
19928 return (-1);
19929 }
19930 }
19931 if (res == 1) {
19932 /*
19933 * Match found.
19934 */
19935 break;
19936 }
19937 }
19938 }
19939 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019940 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019941 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019942 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19943 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019944 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019945 "No match found for key-sequence %s of key "
19946 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019947 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019948 refbind->nodeTable[i]->keys,
19949 refbind->definition->nbFields),
19950 xmlSchemaFormatQName(&strB,
19951 refbind->definition->targetNamespace,
19952 refbind->definition->name));
19953 FREE_AND_NULL(str);
19954 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019955 }
19956 }
19957 }
19958 refbind = refbind->next;
19959 }
19960 return (0);
19961}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019962
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019963/************************************************************************
19964 * *
19965 * XML Reader validation code *
19966 * *
19967 ************************************************************************/
19968
19969static xmlSchemaAttrInfoPtr
19970xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019971{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019972 xmlSchemaAttrInfoPtr iattr;
19973 /*
19974 * Grow/create list of attribute infos.
19975 */
19976 if (vctxt->attrInfos == NULL) {
19977 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19978 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19979 vctxt->sizeAttrInfos = 1;
19980 if (vctxt->attrInfos == NULL) {
19981 xmlSchemaVErrMemory(vctxt,
19982 "allocating attribute info list", NULL);
19983 return (NULL);
19984 }
19985 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19986 vctxt->sizeAttrInfos++;
19987 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19988 xmlRealloc(vctxt->attrInfos,
19989 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19990 if (vctxt->attrInfos == NULL) {
19991 xmlSchemaVErrMemory(vctxt,
19992 "re-allocating attribute info list", NULL);
19993 return (NULL);
19994 }
19995 } else {
19996 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19997 if (iattr->localName != NULL) {
19998 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19999 "attr info not cleared");
20000 return (NULL);
20001 }
20002 iattr->nodeType = XML_ATTRIBUTE_NODE;
20003 return (iattr);
20004 }
20005 /*
20006 * Create an attribute info.
20007 */
20008 iattr = (xmlSchemaAttrInfoPtr)
20009 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20010 if (iattr == NULL) {
20011 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20012 return (NULL);
20013 }
20014 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20015 iattr->nodeType = XML_ATTRIBUTE_NODE;
20016 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20017
20018 return (iattr);
20019}
20020
20021static int
20022xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20023 xmlNodePtr attrNode,
20024 const xmlChar *localName,
20025 const xmlChar *nsName,
20026 int ownedNames,
20027 xmlChar *value,
20028 int ownedValue)
20029{
20030 xmlSchemaAttrInfoPtr attr;
20031
20032 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20033 if (attr == NULL) {
20034 VERROR_INT("xmlSchemaPushAttribute",
20035 "calling xmlSchemaGetFreshAttrInfo()");
20036 return (-1);
20037 }
20038 attr->node = attrNode;
20039 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20040 attr->localName = localName;
20041 attr->nsName = nsName;
20042 if (ownedNames)
20043 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20044 /*
20045 * Evaluate if it's an XSI attribute.
20046 */
20047 if (nsName != NULL) {
20048 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20049 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20050 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20051 }
20052 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20053 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20054 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20055 }
20056 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20057 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20058 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20059 }
20060 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20061 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20062 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20063 }
20064 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20065 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20066 }
20067 }
20068 attr->value = value;
20069 if (ownedValue)
20070 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20071 if (attr->metaType != 0)
20072 attr->state = XML_SCHEMAS_ATTR_META;
20073 return (0);
20074}
20075
20076static void
20077xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20078{
20079 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20080 FREE_AND_NULL(ielem->localName);
20081 FREE_AND_NULL(ielem->nsName);
20082 } else {
20083 ielem->localName = NULL;
20084 ielem->nsName = NULL;
20085 }
20086 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20087 FREE_AND_NULL(ielem->value);
20088 } else {
20089 ielem->value = NULL;
20090 }
20091 if (ielem->val != NULL) {
20092 xmlSchemaFreeValue(ielem->val);
20093 ielem->val = NULL;
20094 }
20095 if (ielem->idcMatchers != NULL) {
20096 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20097 ielem->idcMatchers = NULL;
20098 }
20099 if (ielem->idcTable != NULL) {
20100 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20101 ielem->idcTable = NULL;
20102 }
20103 if (ielem->regexCtxt != NULL) {
20104 xmlRegFreeExecCtxt(ielem->regexCtxt);
20105 ielem->regexCtxt = NULL;
20106 }
20107 if (ielem->nsBindings != NULL) {
20108 xmlFree((xmlChar **)ielem->nsBindings);
20109 ielem->nsBindings = NULL;
20110 ielem->nbNsBindings = 0;
20111 ielem->sizeNsBindings = 0;
20112 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020113}
20114
20115/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020116 * xmlSchemaGetFreshElemInfo:
20117 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020118 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020119 * Creates/reuses and initializes the element info item for
20120 * the currect tree depth.
20121 *
20122 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020123 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020124static xmlSchemaNodeInfoPtr
20125xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020126{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020127 xmlSchemaNodeInfoPtr info = NULL;
20128
20129 if (vctxt->depth > vctxt->sizeElemInfos) {
20130 VERROR_INT("xmlSchemaGetFreshElemInfo",
20131 "inconsistent depth encountered");
20132 return (NULL);
20133 }
20134 if (vctxt->elemInfos == NULL) {
20135 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20136 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20137 if (vctxt->elemInfos == NULL) {
20138 xmlSchemaVErrMemory(vctxt,
20139 "allocating the element info array", NULL);
20140 return (NULL);
20141 }
20142 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20143 vctxt->sizeElemInfos = 10;
20144 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20145 int i = vctxt->sizeElemInfos;
20146
20147 vctxt->sizeElemInfos *= 2;
20148 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20149 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20150 sizeof(xmlSchemaNodeInfoPtr));
20151 if (vctxt->elemInfos == NULL) {
20152 xmlSchemaVErrMemory(vctxt,
20153 "re-allocating the element info array", NULL);
20154 return (NULL);
20155 }
20156 /*
20157 * We need the new memory to be NULLed.
20158 * TODO: Use memset instead?
20159 */
20160 for (; i < vctxt->sizeElemInfos; i++)
20161 vctxt->elemInfos[i] = NULL;
20162 } else
20163 info = vctxt->elemInfos[vctxt->depth];
20164
20165 if (info == NULL) {
20166 info = (xmlSchemaNodeInfoPtr)
20167 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20168 if (info == NULL) {
20169 xmlSchemaVErrMemory(vctxt,
20170 "allocating an element info", NULL);
20171 return (NULL);
20172 }
20173 vctxt->elemInfos[vctxt->depth] = info;
20174 } else {
20175 if (info->localName != NULL) {
20176 VERROR_INT("xmlSchemaGetFreshElemInfo",
20177 "elem info has not been cleared");
20178 return (NULL);
20179 }
20180 }
20181 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20182 info->nodeType = XML_ELEMENT_NODE;
20183 info->depth = vctxt->depth;
20184
20185 return (info);
20186}
20187
20188#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20189#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20190#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20191
20192static int
20193xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20194 xmlNodePtr node,
20195 xmlSchemaTypePtr type,
20196 xmlSchemaValType valType,
20197 const xmlChar * value,
20198 xmlSchemaValPtr val,
20199 unsigned long length,
20200 int fireErrors)
20201{
20202 int ret, error = 0;
20203
20204 xmlSchemaTypePtr tmpType;
20205 xmlSchemaFacetLinkPtr facetLink;
20206 xmlSchemaFacetPtr facet;
20207 unsigned long len = 0;
20208 xmlSchemaWhitespaceValueType ws;
20209
20210 /*
20211 * In Libxml2, derived built-in types have currently no explicit facets.
20212 */
20213 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020214 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020215
20216 /*
20217 * NOTE: Do not jump away, if the facetSet of the given type is
20218 * empty: until now, "pattern" and "enumeration" facets of the
20219 * *base types* need to be checked as well.
20220 */
20221 if (type->facetSet == NULL)
20222 goto pattern_and_enum;
20223
20224 if (! VARIETY_ATOMIC(type)) {
20225 if (VARIETY_LIST(type))
20226 goto variety_list;
20227 else
20228 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020229 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020230 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020231 * Whitespace handling is only of importance for string-based
20232 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020233 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020234 tmpType = xmlSchemaGetPrimitiveType(type);
20235 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20236 IS_ANY_SIMPLE_TYPE(tmpType)) {
20237 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20238 } else
20239 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20240 /*
20241 * If the value was not computed (for string or
20242 * anySimpleType based types), then use the provided
20243 * type.
20244 */
20245 if (val == NULL)
20246 valType = valType;
20247 else
20248 valType = xmlSchemaGetValType(val);
20249
20250 ret = 0;
20251 for (facetLink = type->facetSet; facetLink != NULL;
20252 facetLink = facetLink->next) {
20253 /*
20254 * Skip the pattern "whiteSpace": it is used to
20255 * format the character content beforehand.
20256 */
20257 switch (facetLink->facet->type) {
20258 case XML_SCHEMA_FACET_WHITESPACE:
20259 case XML_SCHEMA_FACET_PATTERN:
20260 case XML_SCHEMA_FACET_ENUMERATION:
20261 continue;
20262 case XML_SCHEMA_FACET_LENGTH:
20263 case XML_SCHEMA_FACET_MINLENGTH:
20264 case XML_SCHEMA_FACET_MAXLENGTH:
20265 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20266 valType, value, val, &len, ws);
20267 break;
20268 default:
20269 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20270 valType, value, val, ws);
20271 break;
20272 }
20273 if (ret < 0) {
20274 AERROR_INT("xmlSchemaValidateFacets",
20275 "validating against a atomic type facet");
20276 return (-1);
20277 } else if (ret > 0) {
20278 if (fireErrors)
20279 xmlSchemaFacetErr(actxt, ret, node,
20280 value, len, type, facetLink->facet, NULL, NULL, NULL);
20281 else
20282 return (ret);
20283 if (error == 0)
20284 error = ret;
20285 }
20286 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020287 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020288
20289variety_list:
20290 if (! VARIETY_LIST(type))
20291 goto pattern_and_enum;
20292 /*
20293 * "length", "minLength" and "maxLength" of list types.
20294 */
20295 ret = 0;
20296 for (facetLink = type->facetSet; facetLink != NULL;
20297 facetLink = facetLink->next) {
20298
20299 switch (facetLink->facet->type) {
20300 case XML_SCHEMA_FACET_LENGTH:
20301 case XML_SCHEMA_FACET_MINLENGTH:
20302 case XML_SCHEMA_FACET_MAXLENGTH:
20303 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20304 value, length, NULL);
20305 break;
20306 default:
20307 continue;
20308 }
20309 if (ret < 0) {
20310 AERROR_INT("xmlSchemaValidateFacets",
20311 "validating against a list type facet");
20312 return (-1);
20313 } else if (ret > 0) {
20314 if (fireErrors)
20315 xmlSchemaFacetErr(actxt, ret, node,
20316 value, length, type, facetLink->facet, NULL, NULL, NULL);
20317 else
20318 return (ret);
20319 if (error == 0)
20320 error = ret;
20321 }
20322 ret = 0;
20323 }
20324
20325pattern_and_enum:
20326 if (error >= 0) {
20327 int found = 0;
20328 /*
20329 * Process enumerations. Facet values are in the value space
20330 * of the defining type's base type. This seems to be a bug in the
20331 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20332 * Only the first set of enumerations in the ancestor-or-self axis
20333 * is used for validation.
20334 */
20335 ret = 0;
20336 tmpType = type;
20337 do {
20338 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20339 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20340 continue;
20341 found = 1;
20342 ret = xmlSchemaAreValuesEqual(facet->val, val);
20343 if (ret == 1)
20344 break;
20345 else if (ret < 0) {
20346 AERROR_INT("xmlSchemaValidateFacets",
20347 "validating against an enumeration facet");
20348 return (-1);
20349 }
20350 }
20351 if (ret != 0)
20352 break;
20353 tmpType = tmpType->baseType;
20354 } while ((tmpType != NULL) &&
20355 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20356 if (found && (ret == 0)) {
20357 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20358 if (fireErrors) {
20359 xmlSchemaFacetErr(actxt, ret, node,
20360 value, 0, type, NULL, NULL, NULL, NULL);
20361 } else
20362 return (ret);
20363 if (error == 0)
20364 error = ret;
20365 }
20366 }
20367
20368 if (error >= 0) {
20369 int found;
20370 /*
20371 * Process patters. Pattern facets are ORed at type level
20372 * and ANDed if derived. Walk the base type axis.
20373 */
20374 tmpType = type;
20375 facet = NULL;
20376 do {
20377 found = 0;
20378 for (facetLink = tmpType->facetSet; facetLink != NULL;
20379 facetLink = facetLink->next) {
20380 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20381 continue;
20382 found = 1;
20383 /*
20384 * NOTE that for patterns, @value needs to be the
20385 * normalized vaule.
20386 */
20387 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20388 if (ret == 1)
20389 break;
20390 else if (ret < 0) {
20391 AERROR_INT("xmlSchemaValidateFacets",
20392 "validating against a pattern facet");
20393 return (-1);
20394 } else {
20395 /*
20396 * Save the last non-validating facet.
20397 */
20398 facet = facetLink->facet;
20399 }
20400 }
20401 if (found && (ret != 1)) {
20402 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20403 if (fireErrors) {
20404 xmlSchemaFacetErr(actxt, ret, node,
20405 value, 0, type, facet, NULL, NULL, NULL);
20406 } else
20407 return (ret);
20408 if (error == 0)
20409 error = ret;
20410 break;
20411 }
20412 tmpType = tmpType->baseType;
20413 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20414 }
20415
20416 return (error);
20417}
20418
20419static xmlChar *
20420xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20421 const xmlChar *value)
20422{
20423 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20424 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20425 return (xmlSchemaCollapseString(value));
20426 case XML_SCHEMA_WHITESPACE_REPLACE:
20427 return (xmlSchemaWhiteSpaceReplace(value));
20428 default:
20429 return (NULL);
20430 }
20431}
20432
20433static int
20434xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20435 const xmlChar *value,
20436 xmlSchemaValPtr *val,
20437 int valNeeded)
20438{
20439 int ret;
20440 const xmlChar *nsName;
20441 xmlChar *local, *prefix = NULL;
20442
20443 ret = xmlValidateQName(value, 1);
20444 if (ret != 0) {
20445 if (ret == -1) {
20446 VERROR_INT("xmlSchemaValidateQName",
20447 "calling xmlValidateQName()");
20448 return (-1);
20449 }
20450 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20451 }
20452 /*
20453 * NOTE: xmlSplitQName2 will always return a duplicated
20454 * strings.
20455 */
20456 local = xmlSplitQName2(value, &prefix);
20457 if (local == NULL)
20458 local = xmlStrdup(value);
20459 /*
20460 * OPTIMIZE TODO: Use flags for:
20461 * - is there any namespace binding?
20462 * - is there a default namespace?
20463 */
20464 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20465
20466 if (prefix != NULL) {
20467 xmlFree(prefix);
20468 /*
20469 * A namespace must be found if the prefix is
20470 * NOT NULL.
20471 */
20472 if (nsName == NULL) {
20473 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20474 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20475 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20476 "The QName value '%s' has no "
20477 "corresponding namespace declaration in "
20478 "scope", value, NULL);
20479 if (local != NULL)
20480 xmlFree(local);
20481 return (ret);
20482 }
20483 }
20484 if (valNeeded && val) {
20485 if (nsName != NULL)
20486 *val = xmlSchemaNewQNameValue(
20487 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20488 else
20489 *val = xmlSchemaNewQNameValue(NULL,
20490 BAD_CAST local);
20491 } else
20492 xmlFree(local);
20493 return (0);
20494}
20495
20496/*
20497* cvc-simple-type
20498*/
20499static int
20500xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20501 xmlNodePtr node,
20502 xmlSchemaTypePtr type,
20503 const xmlChar *value,
20504 xmlSchemaValPtr *retVal,
20505 int fireErrors,
20506 int normalize,
20507 int isNormalized)
20508{
20509 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20510 xmlSchemaValPtr val = NULL;
20511 xmlSchemaWhitespaceValueType ws;
20512 xmlChar *normValue = NULL;
20513
20514#define NORMALIZE(atype) \
20515 if ((! isNormalized) && \
20516 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20517 normValue = xmlSchemaNormalizeValue(atype, value); \
20518 if (normValue != NULL) \
20519 value = normValue; \
20520 isNormalized = 1; \
20521 }
20522
20523 if ((retVal != NULL) && (*retVal != NULL)) {
20524 xmlSchemaFreeValue(*retVal);
20525 *retVal = NULL;
20526 }
20527 /*
20528 * 3.14.4 Simple Type Definition Validation Rules
20529 * Validation Rule: String Valid
20530 */
20531 /*
20532 * 1 It is schema-valid with respect to that definition as defined
20533 * by Datatype Valid in [XML Schemas: Datatypes].
20534 */
20535 /*
20536 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20537 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20538 * the string must be a ·declared entity name·.
20539 */
20540 /*
20541 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20542 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20543 * then every whitespace-delimited substring of the string must be a ·declared
20544 * entity name·.
20545 */
20546 /*
20547 * 2.3 otherwise no further condition applies.
20548 */
20549 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20550 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020551 if (value == NULL)
20552 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020553 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20554 xmlSchemaTypePtr biType; /* The built-in type. */
20555 /*
20556 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20557 * a literal in the ·lexical space· of {base type definition}"
20558 */
20559 /*
20560 * Whitespace-normalize.
20561 */
20562 NORMALIZE(type);
20563 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20564 /*
20565 * Get the built-in type.
20566 */
20567 biType = type->baseType;
20568 while ((biType != NULL) &&
20569 (biType->type != XML_SCHEMA_TYPE_BASIC))
20570 biType = biType->baseType;
20571
20572 if (biType == NULL) {
20573 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20574 "could not get the built-in type");
20575 goto internal_error;
20576 }
20577 } else
20578 biType = type;
20579 /*
20580 * NOTATIONs need to be processed here, since they need
20581 * to lookup in the hashtable of NOTATION declarations of the schema.
20582 */
20583 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20584 switch (biType->builtInType) {
20585 case XML_SCHEMAS_NOTATION:
20586 ret = xmlSchemaValidateNotation(
20587 (xmlSchemaValidCtxtPtr) actxt,
20588 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20589 NULL, value, &val, valNeeded);
20590 break;
20591 case XML_SCHEMAS_QNAME:
20592 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20593 value, &val, valNeeded);
20594 break;
20595 default:
20596 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20597 if (valNeeded)
20598 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20599 value, &val, NULL);
20600 else
20601 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20602 value, NULL, NULL);
20603 break;
20604 }
20605 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20606 switch (biType->builtInType) {
20607 case XML_SCHEMAS_NOTATION:
20608 ret = xmlSchemaValidateNotation(NULL,
20609 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20610 value, &val, valNeeded);
20611 break;
20612 default:
20613 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20614 if (valNeeded)
20615 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20616 value, &val, node);
20617 else
20618 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20619 value, NULL, node);
20620 break;
20621 }
20622 } else {
20623 /*
20624 * Validation via a public API is not implemented yet.
20625 */
20626 TODO
20627 goto internal_error;
20628 }
20629 if (ret != 0) {
20630 if (ret < 0) {
20631 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20632 "validating against a built-in type");
20633 goto internal_error;
20634 }
20635 if (VARIETY_LIST(type))
20636 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20637 else
20638 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20639 }
20640 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20641 /*
20642 * Check facets.
20643 */
20644 ret = xmlSchemaValidateFacets(actxt, node, type,
20645 (xmlSchemaValType) biType->builtInType, value, val,
20646 0, fireErrors);
20647 if (ret != 0) {
20648 if (ret < 0) {
20649 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20650 "validating facets of atomic simple type");
20651 goto internal_error;
20652 }
20653 if (VARIETY_LIST(type))
20654 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20655 else
20656 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20657 }
20658 }
20659 if (fireErrors && (ret > 0))
20660 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20661 } else if (VARIETY_LIST(type)) {
20662
20663 xmlSchemaTypePtr itemType;
20664 const xmlChar *cur, *end;
20665 xmlChar *tmpValue = NULL;
20666 unsigned long len = 0;
20667 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20668 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20669 * of white space separated tokens, each of which ·match·es a literal
20670 * in the ·lexical space· of {item type definition}
20671 */
20672 /*
20673 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20674 * the list type has an enum or pattern facet.
20675 */
20676 NORMALIZE(type);
20677 /*
20678 * VAL TODO: Optimize validation of empty values.
20679 * VAL TODO: We do not have computed values for lists.
20680 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020681 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020682 cur = value;
20683 do {
20684 while (IS_BLANK_CH(*cur))
20685 cur++;
20686 end = cur;
20687 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20688 end++;
20689 if (end == cur)
20690 break;
20691 tmpValue = xmlStrndup(cur, end - cur);
20692 len++;
20693
20694 if (valNeeded)
20695 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20696 tmpValue, &curVal, fireErrors, 0, 1);
20697 else
20698 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20699 tmpValue, NULL, fireErrors, 0, 1);
20700 FREE_AND_NULL(tmpValue);
20701 if (curVal != NULL) {
20702 /*
20703 * Add to list of computed values.
20704 */
20705 if (val == NULL)
20706 val = curVal;
20707 else
20708 xmlSchemaValueAppend(prevVal, curVal);
20709 prevVal = curVal;
20710 curVal = NULL;
20711 }
20712 if (ret != 0) {
20713 if (ret < 0) {
20714 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20715 "validating an item of list simple type");
20716 goto internal_error;
20717 }
20718 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20719 break;
20720 }
20721 cur = end;
20722 } while (*cur != 0);
20723 FREE_AND_NULL(tmpValue);
20724 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20725 /*
20726 * Apply facets (pattern, enumeration).
20727 */
20728 ret = xmlSchemaValidateFacets(actxt, node, type,
20729 XML_SCHEMAS_UNKNOWN, value, val,
20730 len, fireErrors);
20731 if (ret != 0) {
20732 if (ret < 0) {
20733 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20734 "validating facets of list simple type");
20735 goto internal_error;
20736 }
20737 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20738 }
20739 }
20740 if (fireErrors && (ret > 0)) {
20741 /*
20742 * Report the normalized value.
20743 */
20744 normalize = 1;
20745 NORMALIZE(type);
20746 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20747 }
20748 } else if (VARIETY_UNION(type)) {
20749 xmlSchemaTypeLinkPtr memberLink;
20750 /*
20751 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20752 * not apply directly; however, the normalization behavior of ·union·
20753 * types is controlled by the value of whiteSpace on that one of the
20754 * ·memberTypes· against which the ·union· is successfully validated.
20755 *
20756 * This means that the value is normalized by the first validating
20757 * member type, then the facets of the union type are applied. This
20758 * needs changing of the value!
20759 */
20760
20761 /*
20762 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20763 * literal in the ·lexical space· of at least one member of
20764 * {member type definitions}
20765 */
20766 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20767 if (memberLink == NULL) {
20768 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20769 "union simple type has no member types");
20770 goto internal_error;
20771 }
20772 /*
20773 * Always normalize union type values, since we currently
20774 * cannot store the whitespace information with the value
20775 * itself; otherwise a later value-comparison would be
20776 * not possible.
20777 */
20778 while (memberLink != NULL) {
20779 if (valNeeded)
20780 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20781 memberLink->type, value, &val, 0, 1, 0);
20782 else
20783 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20784 memberLink->type, value, NULL, 0, 1, 0);
20785 if (ret <= 0)
20786 break;
20787 memberLink = memberLink->next;
20788 }
20789 if (ret != 0) {
20790 if (ret < 0) {
20791 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20792 "validating members of union simple type");
20793 goto internal_error;
20794 }
20795 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20796 }
20797 /*
20798 * Apply facets (pattern, enumeration).
20799 */
20800 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20801 /*
20802 * The normalization behavior of ·union· types is controlled by
20803 * the value of whiteSpace on that one of the ·memberTypes·
20804 * against which the ·union· is successfully validated.
20805 */
20806 NORMALIZE(memberLink->type);
20807 ret = xmlSchemaValidateFacets(actxt, node, type,
20808 XML_SCHEMAS_UNKNOWN, value, val,
20809 0, fireErrors);
20810 if (ret != 0) {
20811 if (ret < 0) {
20812 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20813 "validating facets of union simple type");
20814 goto internal_error;
20815 }
20816 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20817 }
20818 }
20819 if (fireErrors && (ret > 0))
20820 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20821 }
20822
20823 if (normValue != NULL)
20824 xmlFree(normValue);
20825 if (ret == 0) {
20826 if (retVal != NULL)
20827 *retVal = val;
20828 else if (val != NULL)
20829 xmlSchemaFreeValue(val);
20830 } else if (val != NULL)
20831 xmlSchemaFreeValue(val);
20832 return (ret);
20833internal_error:
20834 if (normValue != NULL)
20835 xmlFree(normValue);
20836 if (val != NULL)
20837 xmlSchemaFreeValue(val);
20838 return (-1);
20839}
20840
20841static int
20842xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20843 const xmlChar *value,
20844 const xmlChar **nsName,
20845 const xmlChar **localName)
20846{
20847 int ret = 0;
20848
20849 if ((nsName == NULL) || (localName == NULL))
20850 return (-1);
20851 *nsName = NULL;
20852 *localName = NULL;
20853
20854 ret = xmlValidateQName(value, 1);
20855 if (ret == -1)
20856 return (-1);
20857 if (ret > 0) {
20858 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20859 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20860 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20861 return (1);
20862 }
20863 {
20864 xmlChar *local = NULL;
20865 xmlChar *prefix;
20866
20867 /*
20868 * NOTE: xmlSplitQName2 will return a duplicated
20869 * string.
20870 */
20871 local = xmlSplitQName2(value, &prefix);
20872 VAL_CREATE_DICT;
20873 if (local == NULL)
20874 *localName = xmlDictLookup(vctxt->dict, value, -1);
20875 else {
20876 *localName = xmlDictLookup(vctxt->dict, local, -1);
20877 xmlFree(local);
20878 }
20879
20880 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20881
20882 if (prefix != NULL) {
20883 xmlFree(prefix);
20884 /*
20885 * A namespace must be found if the prefix is NOT NULL.
20886 */
20887 if (*nsName == NULL) {
20888 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20889 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20890 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20891 "The QName value '%s' has no "
20892 "corresponding namespace declaration in scope",
20893 value, NULL);
20894 return (2);
20895 }
20896 }
20897 }
20898 return (0);
20899}
20900
20901static int
20902xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20903 xmlSchemaAttrInfoPtr iattr,
20904 xmlSchemaTypePtr *localType,
20905 xmlSchemaElementPtr elemDecl)
20906{
20907 int ret = 0;
20908 /*
20909 * cvc-elt (3.3.4) : (4)
20910 * AND
20911 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20912 * (1.2.1.2.1) - (1.2.1.2.4)
20913 * Handle 'xsi:type'.
20914 */
20915 if (localType == NULL)
20916 return (-1);
20917 *localType = NULL;
20918 if (iattr == NULL)
20919 return (0);
20920 else {
20921 const xmlChar *nsName = NULL, *local = NULL;
20922 /*
20923 * TODO: We should report a *warning* that the type was overriden
20924 * by the instance.
20925 */
20926 ACTIVATE_ATTRIBUTE(iattr);
20927 /*
20928 * (cvc-elt) (3.3.4) : (4.1)
20929 * (cvc-assess-elt) (1.2.1.2.2)
20930 */
20931 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20932 &nsName, &local);
20933 if (ret != 0) {
20934 if (ret < 0) {
20935 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20936 "calling xmlSchemaQNameExpand() to validate the "
20937 "attribute 'xsi:type'");
20938 goto internal_error;
20939 }
20940 goto exit;
20941 }
20942 /*
20943 * (cvc-elt) (3.3.4) : (4.2)
20944 * (cvc-assess-elt) (1.2.1.2.3)
20945 */
20946 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20947 if (*localType == NULL) {
20948 xmlChar *str = NULL;
20949
20950 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20951 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20952 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20953 "The QName value '%s' of the xsi:type attribute does not "
20954 "resolve to a type definition",
20955 xmlSchemaFormatQName(&str, nsName, local), NULL);
20956 FREE_AND_NULL(str);
20957 ret = vctxt->err;
20958 goto exit;
20959 }
20960 if (elemDecl != NULL) {
20961 int set = 0;
20962
20963 /*
20964 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20965 * "The ·local type definition· must be validly
20966 * derived from the {type definition} given the union of
20967 * the {disallowed substitutions} and the {type definition}'s
20968 * {prohibited substitutions}, as defined in
20969 * Type Derivation OK (Complex) (§3.4.6)
20970 * (if it is a complex type definition),
20971 * or given {disallowed substitutions} as defined in Type
20972 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20973 * definition)."
20974 *
20975 * {disallowed substitutions}: the "block" on the element decl.
20976 * {prohibited substitutions}: the "block" on the type def.
20977 */
20978 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20979 (elemDecl->subtypes->flags &
20980 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20981 set |= SUBSET_EXTENSION;
20982
20983 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20984 (elemDecl->subtypes->flags &
20985 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20986 set |= SUBSET_RESTRICTION;
20987
20988 if (xmlSchemaCheckCOSDerivedOK(*localType,
20989 elemDecl->subtypes, set) != 0) {
20990 xmlChar *str = NULL;
20991
20992 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20993 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20994 "The type definition '%s', specified by xsi:type, is "
20995 "blocked or not validly derived from the type definition "
20996 "of the element declaration",
20997 xmlSchemaFormatQName(&str,
20998 (*localType)->targetNamespace,
20999 (*localType)->name),
21000 NULL);
21001 FREE_AND_NULL(str);
21002 ret = vctxt->err;
21003 *localType = NULL;
21004 }
21005 }
21006 }
21007exit:
21008 ACTIVATE_ELEM;
21009 return (ret);
21010internal_error:
21011 ACTIVATE_ELEM;
21012 return (-1);
21013}
21014
21015static int
21016xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21017{
21018 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21019 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21020
21021 /*
21022 * cvc-elt (3.3.4) : 1
21023 */
21024 if (elemDecl == NULL) {
21025 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21026 "No matching declaration available");
21027 return (vctxt->err);
21028 }
21029 /*
21030 * cvc-elt (3.3.4) : 2
21031 */
21032 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21033 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21034 "The element declaration is abstract");
21035 return (vctxt->err);
21036 }
21037 if (actualType == NULL) {
21038 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21039 "The type definition is absent");
21040 return (XML_SCHEMAV_CVC_TYPE_1);
21041 }
21042 if (vctxt->nbAttrInfos != 0) {
21043 int ret;
21044 xmlSchemaAttrInfoPtr iattr;
21045 /*
21046 * cvc-elt (3.3.4) : 3
21047 * Handle 'xsi:nil'.
21048 */
21049 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21050 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21051 if (iattr) {
21052 ACTIVATE_ATTRIBUTE(iattr);
21053 /*
21054 * Validate the value.
21055 */
21056 ret = xmlSchemaVCheckCVCSimpleType(
21057 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21058 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21059 iattr->value, &(iattr->val), 1, 0, 0);
21060 ACTIVATE_ELEM;
21061 if (ret < 0) {
21062 VERROR_INT("xmlSchemaValidateElemDecl",
21063 "calling xmlSchemaVCheckCVCSimpleType() to "
21064 "validate the attribute 'xsi:nil'");
21065 return (-1);
21066 }
21067 if (ret == 0) {
21068 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21069 /*
21070 * cvc-elt (3.3.4) : 3.1
21071 */
21072 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21073 "The element is not 'nillable'");
21074 /* Does not return an error on purpose. */
21075 } else {
21076 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21077 /*
21078 * cvc-elt (3.3.4) : 3.2.2
21079 */
21080 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21081 (elemDecl->value != NULL)) {
21082 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21083 "The element cannot be 'nilled' because "
21084 "there is a fixed value constraint defined "
21085 "for it");
21086 /* Does not return an error on purpose. */
21087 } else
21088 vctxt->inode->flags |=
21089 XML_SCHEMA_ELEM_INFO_NILLED;
21090 }
21091 }
21092 }
21093 }
21094 /*
21095 * cvc-elt (3.3.4) : 4
21096 * Handle 'xsi:type'.
21097 */
21098 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21099 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21100 if (iattr) {
21101 xmlSchemaTypePtr localType = NULL;
21102
21103 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21104 elemDecl);
21105 if (ret != 0) {
21106 if (ret == -1) {
21107 VERROR_INT("xmlSchemaValidateElemDecl",
21108 "calling xmlSchemaProcessXSIType() to "
21109 "process the attribute 'xsi:type'");
21110 return (-1);
21111 }
21112 /* Does not return an error on purpose. */
21113 }
21114 if (localType != NULL) {
21115 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21116 actualType = localType;
21117 }
21118 }
21119 }
21120 /*
21121 * IDC: Register identity-constraint XPath matchers.
21122 */
21123 if ((elemDecl->idcs != NULL) &&
21124 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21125 return (-1);
21126 /*
21127 * No actual type definition.
21128 */
21129 if (actualType == NULL) {
21130 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21131 "The type definition is absent");
21132 return (XML_SCHEMAV_CVC_TYPE_1);
21133 }
21134 /*
21135 * Remember the actual type definition.
21136 */
21137 vctxt->inode->typeDef = actualType;
21138
21139 return (0);
21140}
21141
21142static int
21143xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21144{
21145 xmlSchemaAttrInfoPtr iattr;
21146 int ret = 0, i;
21147
21148 /*
21149 * SPEC cvc-type (3.1.1)
21150 * "The attributes of must be empty, excepting those whose namespace
21151 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21152 * whose local name is one of type, nil, schemaLocation or
21153 * noNamespaceSchemaLocation."
21154 */
21155 if (vctxt->nbAttrInfos == 0)
21156 return (0);
21157 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21158 iattr = vctxt->attrInfos[i];
21159 if (! iattr->metaType) {
21160 ACTIVATE_ATTRIBUTE(iattr)
21161 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21162 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21163 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21164 }
21165 }
21166 ACTIVATE_ELEM
21167 return (ret);
21168}
21169
21170/*
21171* Cleanup currently used attribute infos.
21172*/
21173static void
21174xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21175{
21176 int i;
21177 xmlSchemaAttrInfoPtr attr;
21178
21179 if (vctxt->nbAttrInfos == 0)
21180 return;
21181 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21182 attr = vctxt->attrInfos[i];
21183 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21184 if (attr->localName != NULL)
21185 xmlFree((xmlChar *) attr->localName);
21186 if (attr->nsName != NULL)
21187 xmlFree((xmlChar *) attr->nsName);
21188 }
21189 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21190 if (attr->value != NULL)
21191 xmlFree((xmlChar *) attr->value);
21192 }
21193 if (attr->val != NULL) {
21194 xmlSchemaFreeValue(attr->val);
21195 attr->val = NULL;
21196 }
21197 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21198 }
21199 vctxt->nbAttrInfos = 0;
21200}
21201
21202/*
21203* 3.4.4 Complex Type Definition Validation Rules
21204* Element Locally Valid (Complex Type) (cvc-complex-type)
21205* 3.2.4 Attribute Declaration Validation Rules
21206* Validation Rule: Attribute Locally Valid (cvc-attribute)
21207* Attribute Locally Valid (Use) (cvc-au)
21208*
21209* Only "assessed" attribute information items will be visible to
21210* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21211*/
21212static int
21213xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21214{
21215 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21216 xmlSchemaAttributeLinkPtr attrUseLink;
21217 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21218 xmlSchemaAttrInfoPtr attr, tmpAttr;
21219 int i, found, nbAttrs;
21220 int xpathRes = 0, res, wildIDs = 0, fixed;
21221
21222 /*
21223 * SPEC (cvc-attribute)
21224 * (1) "The declaration must not be ·absent· (see Missing
21225 * Sub-components (§5.3) for how this can fail to be
21226 * the case)."
21227 * (2) "Its {type definition} must not be absent."
21228 *
21229 * NOTE (1) + (2): This is not handled here, since we currently do not
21230 * allow validation against schemas which have missing sub-components.
21231 *
21232 * SPEC (cvc-complex-type)
21233 * (3) "For each attribute information item in the element information
21234 * item's [attributes] excepting those whose [namespace name] is
21235 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21236 * [local name] is one of type, nil, schemaLocation or
21237 * noNamespaceSchemaLocation, the appropriate case among the following
21238 * must be true:
21239 *
21240 */
21241 nbAttrs = vctxt->nbAttrInfos;
21242 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21243 attrUseLink = attrUseLink->next) {
21244
21245 found = 0;
21246 attrUse = attrUseLink->attr;
21247 /*
21248 * VAL TODO: Implement a real "attribute use" component.
21249 */
21250 if (attrUse->refDecl != NULL)
21251 attrDecl = attrUse->refDecl;
21252 else
21253 attrDecl = attrUse;
21254 for (i = 0; i < nbAttrs; i++) {
21255 attr = vctxt->attrInfos[i];
21256 /*
21257 * SPEC (cvc-complex-type) (3)
21258 * Skip meta attributes.
21259 */
21260 if (attr->metaType)
21261 continue;
21262 if (attr->localName[0] != attrDecl->name[0])
21263 continue;
21264 if (!xmlStrEqual(attr->localName, attrDecl->name))
21265 continue;
21266 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21267 continue;
21268 found = 1;
21269 /*
21270 * SPEC (cvc-complex-type)
21271 * (3.1) "If there is among the {attribute uses} an attribute
21272 * use with an {attribute declaration} whose {name} matches
21273 * the attribute information item's [local name] and whose
21274 * {target namespace} is identical to the attribute information
21275 * item's [namespace name] (where an ·absent· {target namespace}
21276 * is taken to be identical to a [namespace name] with no value),
21277 * then the attribute information must be ·valid· with respect
21278 * to that attribute use as per Attribute Locally Valid (Use)
21279 * (§3.5.4). In this case the {attribute declaration} of that
21280 * attribute use is the ·context-determined declaration· for the
21281 * attribute information item with respect to Schema-Validity
21282 * Assessment (Attribute) (§3.2.4) and
21283 * Assessment Outcome (Attribute) (§3.2.5).
21284 */
21285 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21286 attr->use = attrUse;
21287 /*
21288 * Context-determined declaration.
21289 */
21290 attr->decl = attrDecl;
21291 attr->typeDef = attrDecl->subtypes;
21292 break;
21293 }
21294
21295 if (found)
21296 continue;
21297
21298 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21299 /*
21300 * Handle non-existent, required attributes.
21301 *
21302 * SPEC (cvc-complex-type)
21303 * (4) "The {attribute declaration} of each attribute use in
21304 * the {attribute uses} whose {required} is true matches one
21305 * of the attribute information items in the element information
21306 * item's [attributes] as per clause 3.1 above."
21307 */
21308 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21309 if (tmpAttr == NULL) {
21310 VERROR_INT(
21311 "xmlSchemaVAttributesComplex",
21312 "calling xmlSchemaGetFreshAttrInfo()");
21313 return (-1);
21314 }
21315 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21316 tmpAttr->use = attrUse;
21317 tmpAttr->decl = attrDecl;
21318 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21319 ((attrUse->defValue != NULL) ||
21320 (attrDecl->defValue != NULL))) {
21321 /*
21322 * Handle non-existent, optional, default/fixed attributes.
21323 */
21324 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21325 if (tmpAttr == NULL) {
21326 VERROR_INT(
21327 "xmlSchemaVAttributesComplex",
21328 "calling xmlSchemaGetFreshAttrInfo()");
21329 return (-1);
21330 }
21331 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21332 tmpAttr->use = attrUse;
21333 tmpAttr->decl = attrDecl;
21334 tmpAttr->typeDef = attrDecl->subtypes;
21335 tmpAttr->localName = attrDecl->name;
21336 tmpAttr->nsName = attrDecl->targetNamespace;
21337 }
21338 }
21339 if (vctxt->nbAttrInfos == 0)
21340 return (0);
21341 /*
21342 * Validate against the wildcard.
21343 */
21344 if (type->attributeWildcard != NULL) {
21345 /*
21346 * SPEC (cvc-complex-type)
21347 * (3.2.1) "There must be an {attribute wildcard}."
21348 */
21349 for (i = 0; i < nbAttrs; i++) {
21350 attr = vctxt->attrInfos[i];
21351 /*
21352 * SPEC (cvc-complex-type) (3)
21353 * Skip meta attributes.
21354 */
21355 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21356 continue;
21357 /*
21358 * SPEC (cvc-complex-type)
21359 * (3.2.2) "The attribute information item must be ·valid· with
21360 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21361 *
21362 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21363 * "... its [namespace name] must be ·valid· with respect to
21364 * the wildcard constraint, as defined in Wildcard allows
21365 * Namespace Name (§3.10.4)."
21366 */
21367 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21368 attr->nsName)) {
21369 /*
21370 * Handle processContents.
21371 *
21372 * SPEC (cvc-wildcard):
21373 * processContents | context-determined declaration:
21374 * "strict" "mustFind"
21375 * "lax" "none"
21376 * "skip" "skip"
21377 */
21378 if (type->attributeWildcard->processContents ==
21379 XML_SCHEMAS_ANY_SKIP) {
21380 /*
21381 * context-determined declaration = "skip"
21382 *
21383 * SPEC PSVI Assessment Outcome (Attribute)
21384 * [validity] = "notKnown"
21385 * [validation attempted] = "none"
21386 */
21387 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21388 continue;
21389 }
21390 /*
21391 * Find an attribute declaration.
21392 */
21393 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21394 attr->localName, attr->nsName);
21395 if (attr->decl != NULL) {
21396 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21397 /*
21398 * SPEC (cvc-complex-type)
21399 * (5) "Let [Definition:] the wild IDs be the set of
21400 * all attribute information item to which clause 3.2
21401 * applied and whose ·validation· resulted in a
21402 * ·context-determined declaration· of mustFind or no
21403 * ·context-determined declaration· at all, and whose
21404 * [local name] and [namespace name] resolve (as
21405 * defined by QName resolution (Instance) (§3.15.4)) to
21406 * an attribute declaration whose {type definition} is
21407 * or is derived from ID. Then all of the following
21408 * must be true:"
21409 */
21410 attr->typeDef = attr->decl->subtypes;
21411 if (xmlSchemaIsDerivedFromBuiltInType(
21412 attr->typeDef, XML_SCHEMAS_ID)) {
21413 /*
21414 * SPEC (5.1) "There must be no more than one
21415 * item in ·wild IDs·."
21416 */
21417 if (wildIDs != 0) {
21418 /* VAL TODO */
21419 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21420 TODO
21421 continue;
21422 }
21423 wildIDs++;
21424 /*
21425 * SPEC (cvc-complex-type)
21426 * (5.2) "If ·wild IDs· is non-empty, there must not
21427 * be any attribute uses among the {attribute uses}
21428 * whose {attribute declaration}'s {type definition}
21429 * is or is derived from ID."
21430 */
21431 for (attrUseLink = type->attributeUses;
21432 attrUseLink != NULL;
21433 attrUseLink = attrUseLink->next) {
21434 if (xmlSchemaIsDerivedFromBuiltInType(
21435 attrUseLink->attr->subtypes,
21436 XML_SCHEMAS_ID)) {
21437 /* VAL TODO */
21438 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21439 TODO
21440 }
21441 }
21442 }
21443 } else if (type->attributeWildcard->processContents ==
21444 XML_SCHEMAS_ANY_LAX) {
21445 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21446 /*
21447 * SPEC PSVI Assessment Outcome (Attribute)
21448 * [validity] = "notKnown"
21449 * [validation attempted] = "none"
21450 */
21451 } else {
21452 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21453 }
21454 }
21455 }
21456 }
21457
21458
21459 if (vctxt->nbAttrInfos == 0)
21460 return (0);
21461
21462 /*
21463 * Validate values, create default attributes, evaluate IDCs.
21464 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021465 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21466 attr = vctxt->attrInfos[i];
21467 /*
21468 * VAL TODO: Note that we won't try to resolve IDCs to
21469 * "lax" and "skip" validated attributes. Check what to
21470 * do in this case.
21471 */
21472 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21473 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21474 continue;
21475 /*
21476 * VAL TODO: What to do if the type definition is missing?
21477 */
21478 if (attr->typeDef == NULL) {
21479 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21480 continue;
21481 }
21482
21483 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021484 fixed = 0;
21485 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021486
21487 if (vctxt->xpathStates != NULL) {
21488 /*
21489 * Evaluate IDCs.
21490 */
21491 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21492 XML_ATTRIBUTE_NODE);
21493 if (xpathRes == -1) {
21494 VERROR_INT("xmlSchemaVAttributesComplex",
21495 "calling xmlSchemaXPathEvaluate()");
21496 goto internal_error;
21497 }
21498 }
21499
21500 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21501 /*
21502 * Default/fixed attributes.
21503 */
21504 if (xpathRes) {
21505 if (attr->use->defValue == NULL) {
21506 attr->value = (xmlChar *) attr->use->defValue;
21507 attr->val = attr->use->defVal;
21508 } else {
21509 attr->value = (xmlChar *) attr->decl->defValue;
21510 attr->val = attr->decl->defVal;
21511 }
21512 /*
21513 * IDCs will consume the precomputed default value,
21514 * so we need to clone it.
21515 */
21516 if (attr->val == NULL) {
21517 VERROR_INT("xmlSchemaVAttributesComplex",
21518 "default/fixed value on an attribute use was "
21519 "not precomputed");
21520 goto internal_error;
21521 }
21522 attr->val = xmlSchemaCopyValue(attr->val);
21523 if (attr->val == NULL) {
21524 VERROR_INT("xmlSchemaVAttributesComplex",
21525 "calling xmlSchemaCopyValue()");
21526 goto internal_error;
21527 }
21528 }
21529 /*
21530 * PSVI: Add the default attribute to the current element.
21531 * VAL TODO: Should we use the *normalized* value? This currently
21532 * uses the *initial* value.
21533 */
21534 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21535 (attr->node != NULL) && (attr->node->doc != NULL)) {
21536 xmlChar *normValue;
21537 const xmlChar *value;
21538
21539 value = attr->value;
21540 /*
21541 * Normalize the value.
21542 */
21543 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21544 attr->value);
21545 if (normValue != NULL)
21546 value = BAD_CAST normValue;
21547
21548 if (attr->nsName == NULL) {
21549 if (xmlNewProp(attr->node->parent,
21550 attr->localName, value) == NULL) {
21551 VERROR_INT("xmlSchemaVAttributesComplex",
21552 "callling xmlNewProp()");
21553 if (normValue != NULL)
21554 xmlFree(normValue);
21555 goto internal_error;
21556 }
21557 } else {
21558 xmlNsPtr ns;
21559
21560 ns = xmlSearchNsByHref(attr->node->doc,
21561 attr->node->parent, attr->nsName);
21562 if (ns == NULL) {
21563 xmlChar prefix[12];
21564 int counter = 0;
21565
21566 /*
21567 * Create a namespace declaration on the validation
21568 * root node if no namespace declaration is in scope.
21569 */
21570 do {
21571 snprintf((char *) prefix, 12, "p%d", counter++);
21572 ns = xmlSearchNs(attr->node->doc,
21573 attr->node->parent, BAD_CAST prefix);
21574 if (counter > 1000) {
21575 VERROR_INT(
21576 "xmlSchemaVAttributesComplex",
21577 "could not compute a ns prefix for a "
21578 "default/fixed attribute");
21579 if (normValue != NULL)
21580 xmlFree(normValue);
21581 goto internal_error;
21582 }
21583 } while (ns != NULL);
21584 ns = xmlNewNs(vctxt->validationRoot,
21585 attr->nsName, BAD_CAST prefix);
21586 }
21587 xmlNewNsProp(attr->node->parent, ns,
21588 attr->localName, value);
21589 }
21590 if (normValue != NULL)
21591 xmlFree(normValue);
21592 }
21593 /*
21594 * Go directly to IDC evaluation.
21595 */
21596 goto eval_idcs;
21597 }
21598 /*
21599 * Validate the value.
21600 */
21601 if (vctxt->value != NULL) {
21602 /*
21603 * Free last computed value; just for safety reasons.
21604 */
21605 xmlSchemaFreeValue(vctxt->value);
21606 vctxt->value = NULL;
21607 }
21608 /*
21609 * Note that the attribute *use* can be unavailable, if
21610 * the attribute was a wild attribute.
21611 */
21612 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21613 ((attr->use != NULL) &&
21614 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21615 fixed = 1;
21616 else
21617 fixed = 0;
21618 /*
21619 * SPEC (cvc-attribute)
21620 * (3) "The item's ·normalized value· must be locally ·valid·
21621 * with respect to that {type definition} as per
21622 * String Valid (§3.14.4)."
21623 *
21624 * VAL TODO: Do we already have the
21625 * "normalized attribute value" here?
21626 */
21627 if (xpathRes || fixed) {
21628 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21629 /*
21630 * Request a computed value.
21631 */
21632 res = xmlSchemaVCheckCVCSimpleType(
21633 (xmlSchemaAbstractCtxtPtr) vctxt,
21634 attr->node, attr->typeDef, attr->value, &(attr->val),
21635 1, 1, 0);
21636 } else {
21637 res = xmlSchemaVCheckCVCSimpleType(
21638 (xmlSchemaAbstractCtxtPtr) vctxt,
21639 attr->node, attr->typeDef, attr->value, NULL,
21640 1, 0, 0);
21641 }
21642
21643 if (res != 0) {
21644 if (res == -1) {
21645 VERROR_INT("xmlSchemaVAttributesComplex",
21646 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21647 goto internal_error;
21648 }
21649 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21650 /*
21651 * SPEC PSVI Assessment Outcome (Attribute)
21652 * [validity] = "invalid"
21653 */
21654 goto eval_idcs;
21655 }
21656
21657 if (fixed) {
21658 int ws;
21659 /*
21660 * SPEC Attribute Locally Valid (Use) (cvc-au)
21661 * "For an attribute information item to be·valid·
21662 * with respect to an attribute use its *normalized*
21663 * value· must match the *canonical* lexical
21664 * representation of the attribute use's {value
21665 * constraint}value, if it is present and fixed."
21666 *
21667 * VAL TODO: The requirement for the *canonical* value
21668 * will be removed in XML Schema 1.1.
21669 */
21670 /*
21671 * SPEC Attribute Locally Valid (cvc-attribute)
21672 * (4) "The item's *actual* value· must match the *value* of
21673 * the {value constraint}, if it is present and fixed."
21674 */
21675 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21676 if (attr->val == NULL) {
21677 /* VAL TODO: A value was not precomputed. */
21678 TODO
21679 goto eval_idcs;
21680 }
21681 if ((attr->use != NULL) &&
21682 (attr->use->defValue != NULL)) {
21683 if (attr->use->defVal == NULL) {
21684 /* VAL TODO: A default value was not precomputed. */
21685 TODO
21686 goto eval_idcs;
21687 }
21688 attr->vcValue = attr->use->defValue;
21689 /*
21690 if (xmlSchemaCompareValuesWhtsp(attr->val,
21691 (xmlSchemaWhitespaceValueType) ws,
21692 attr->use->defVal,
21693 (xmlSchemaWhitespaceValueType) ws) != 0) {
21694 */
21695 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21696 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21697 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021698 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021699 /* VAL TODO: A default value was not precomputed. */
21700 TODO
21701 goto eval_idcs;
21702 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021703 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021704 /*
21705 if (xmlSchemaCompareValuesWhtsp(attr->val,
21706 (xmlSchemaWhitespaceValueType) ws,
21707 attrDecl->defVal,
21708 (xmlSchemaWhitespaceValueType) ws) != 0) {
21709 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021710 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021711 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21712 }
21713 /*
21714 * [validity] = "valid"
21715 */
21716 }
21717eval_idcs:
21718 /*
21719 * Evaluate IDCs.
21720 */
21721 if (xpathRes) {
21722 if (xmlSchemaXPathProcessHistory(vctxt,
21723 vctxt->depth +1) == -1) {
21724 VERROR_INT("xmlSchemaVAttributesComplex",
21725 "calling xmlSchemaXPathEvaluate()");
21726 goto internal_error;
21727 }
21728 }
21729 }
21730
21731 /*
21732 * Report errors.
21733 */
21734 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21735 attr = vctxt->attrInfos[i];
21736 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21737 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21738 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21739 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21740 continue;
21741 ACTIVATE_ATTRIBUTE(attr);
21742 switch (attr->state) {
21743 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21744 xmlChar *str = NULL;
21745 ACTIVATE_ELEM;
21746 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21747 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21748 "The attribute '%s' is required but missing",
21749 xmlSchemaFormatQName(&str,
21750 attr->decl->targetNamespace,
21751 attr->decl->name),
21752 NULL);
21753 FREE_AND_NULL(str)
21754 break;
21755 }
21756 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21757 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21758 "The type definition is absent");
21759 break;
21760 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21761 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21762 XML_SCHEMAV_CVC_AU, NULL, NULL,
21763 "The value '%s' does not match the fixed "
21764 "value constraint '%s'",
21765 attr->value, attr->vcValue);
21766 break;
21767 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21768 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21769 "No matching global attribute declaration available, but "
21770 "demanded by the strict wildcard");
21771 break;
21772 case XML_SCHEMAS_ATTR_UNKNOWN:
21773 if (attr->metaType)
21774 break;
21775 /*
21776 * MAYBE VAL TODO: One might report different error messages
21777 * for the following errors.
21778 */
21779 if (type->attributeWildcard == NULL) {
21780 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21781 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21782 } else {
21783 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21784 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21785 }
21786 break;
21787 default:
21788 break;
21789 }
21790 }
21791
21792 ACTIVATE_ELEM;
21793 return (0);
21794internal_error:
21795 ACTIVATE_ELEM;
21796 return (-1);
21797}
21798
21799static int
21800xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21801 int *skip)
21802{
21803 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21804 /*
21805 * The namespace of the element was already identified to be
21806 * matching the wildcard.
21807 */
21808 if ((skip == NULL) || (wild == NULL) ||
21809 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21810 VERROR_INT("xmlSchemaValidateElemWildcard",
21811 "bad arguments");
21812 return (-1);
21813 }
21814 *skip = 0;
21815 if (wild->negNsSet != NULL) {
21816 /*
21817 * URGENT VAL TODO: Fix the content model to reject
21818 * "##other" wildcards.
21819 */
21820 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21821 vctxt->inode->nsName) != 0) {
21822 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21823 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21824 /*
21825 * VAL TODO: Workaround possible *only* if minOccurs and
21826 * maxOccurs are 1.
21827 */
21828 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21829 /* VAL TODO: error code? */
21830 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21831 (xmlSchemaTypePtr) wild,
21832 "This element is not accepted by the wildcard",
21833 0, 0, NULL);
21834 vctxt->skipDepth = vctxt->depth;
21835 if ((pinode->flags &
21836 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21837 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21838 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21839 return (XML_SCHEMAV_ELEMENT_CONTENT);
21840 }
21841 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21842 *skip = 1;
21843 return (0);
21844 }
21845 vctxt->inode->typeDef =
21846 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21847 return (0);
21848 }
21849 }
21850 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21851 /*
21852 * URGENT VAL TODO: Either we need to position the stream to the
21853 * next sibling, or walk the whole subtree.
21854 */
21855 *skip = 1;
21856 return (0);
21857 }
21858 {
21859 xmlSchemaElementPtr decl = NULL;
21860
21861 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21862 vctxt->inode->localName, vctxt->inode->nsName,
21863 NULL);
21864 if (decl != NULL) {
21865 vctxt->inode->decl = decl;
21866 return (0);
21867 }
21868 }
21869 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21870 /* VAL TODO: Change to proper error code. */
21871 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21872 "No matching global element declaration available, but "
21873 "demanded by the strict wildcard");
21874 return (vctxt->err);
21875 }
21876 if (vctxt->nbAttrInfos != 0) {
21877 xmlSchemaAttrInfoPtr iattr;
21878 /*
21879 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21880 * (1.2.1.2.1) - (1.2.1.2.3 )
21881 *
21882 * Use the xsi:type attribute for the type definition.
21883 */
21884 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21885 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21886 if (iattr != NULL) {
21887 if (xmlSchemaProcessXSIType(vctxt, iattr,
21888 &(vctxt->inode->typeDef), NULL) == -1) {
21889 VERROR_INT("xmlSchemaValidateElemWildcard",
21890 "calling xmlSchemaProcessXSIType() to "
21891 "process the attribute 'xsi:nil'");
21892 return (-1);
21893 }
21894 /*
21895 * Don't return an error on purpose.
21896 */
21897 return (0);
21898 }
21899 }
21900 /*
21901 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21902 *
21903 * Fallback to "anyType".
21904 */
21905 vctxt->inode->typeDef =
21906 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21907 return (0);
21908}
21909
21910/*
21911* xmlSchemaCheckCOSValidDefault:
21912*
21913* This will be called if: not nilled, no content and a default/fixed
21914* value is provided.
21915*/
21916
21917static int
21918xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21919 const xmlChar *value,
21920 xmlSchemaValPtr *val)
21921{
21922 int ret = 0;
21923 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21924
21925 /*
21926 * cos-valid-default:
21927 * Schema Component Constraint: Element Default Valid (Immediate)
21928 * For a string to be a valid default with respect to a type
21929 * definition the appropriate case among the following must be true:
21930 */
21931 if IS_COMPLEX_TYPE(inode->typeDef) {
21932 /*
21933 * Complex type.
21934 *
21935 * SPEC (2.1) "its {content type} must be a simple type definition
21936 * or mixed."
21937 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21938 * type}'s particle must be ·emptiable· as defined by
21939 * Particle Emptiable (§3.9.6)."
21940 */
21941 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21942 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21943 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21944 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21945 /* NOTE that this covers (2.2.2) as well. */
21946 VERROR(ret, NULL,
21947 "For a string to be a valid default, the type definition "
21948 "must be a simple type or a complex type with simple content "
21949 "or mixed content and a particle emptiable");
21950 return(ret);
21951 }
21952 }
21953 /*
21954 * 1 If the type definition is a simple type definition, then the string
21955 * must be ·valid· with respect to that definition as defined by String
21956 * Valid (§3.14.4).
21957 *
21958 * AND
21959 *
21960 * 2.2.1 If the {content type} is a simple type definition, then the
21961 * string must be ·valid· with respect to that simple type definition
21962 * as defined by String Valid (§3.14.4).
21963 */
21964 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21965
21966 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21967 NULL, inode->typeDef, value, val, 1, 1, 0);
21968
21969 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21970
21971 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21972 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21973 }
21974 if (ret < 0) {
21975 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21976 "calling xmlSchemaVCheckCVCSimpleType()");
21977 }
21978 return (ret);
21979}
21980
21981static void
21982xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21983 const xmlChar * name ATTRIBUTE_UNUSED,
21984 xmlSchemaElementPtr item,
21985 xmlSchemaNodeInfoPtr inode)
21986{
21987 inode->decl = item;
21988#ifdef DEBUG_CONTENT
21989 {
21990 xmlChar *str = NULL;
21991
21992 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21993 xmlGenericError(xmlGenericErrorContext,
21994 "AUTOMATON callback for '%s' [declaration]\n",
21995 xmlSchemaFormatQName(&str,
21996 inode->localName, inode->nsName));
21997 } else {
21998 xmlGenericError(xmlGenericErrorContext,
21999 "AUTOMATON callback for '%s' [wildcard]\n",
22000 xmlSchemaFormatQName(&str,
22001 inode->localName, inode->nsName));
22002
22003 }
22004 FREE_AND_NULL(str)
22005 }
22006#endif
22007}
22008
22009static int
22010xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022011{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022012 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22013 if (vctxt->inode == NULL) {
22014 VERROR_INT("xmlSchemaValidatorPushElem",
22015 "calling xmlSchemaGetFreshElemInfo()");
22016 return (-1);
22017 }
22018 vctxt->nbAttrInfos = 0;
22019 return (0);
22020}
22021
22022static int
22023xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22024 xmlSchemaNodeInfoPtr inode,
22025 xmlSchemaTypePtr type,
22026 const xmlChar *value)
22027{
22028 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22029 return (xmlSchemaVCheckCVCSimpleType(
22030 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22031 type, value, &(inode->val), 1, 1, 0));
22032 else
22033 return (xmlSchemaVCheckCVCSimpleType(
22034 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22035 type, value, NULL, 1, 0, 0));
22036}
22037
22038
22039
22040/*
22041* Process END of element.
22042*/
22043static int
22044xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22045{
22046 int ret = 0;
22047 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22048
22049 if (vctxt->nbAttrInfos != 0)
22050 xmlSchemaClearAttrInfos(vctxt);
22051 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22052 /*
22053 * This element was not expected;
22054 * we will not validate child elements of broken parents.
22055 * Skip validation of all content of the parent.
22056 */
22057 vctxt->skipDepth = vctxt->depth -1;
22058 goto end_elem;
22059 }
22060 if ((inode->typeDef == NULL) ||
22061 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22062 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022063 * 1. the type definition might be missing if the element was
22064 * error prone
22065 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022066 */
22067 goto end_elem;
22068 }
22069 /*
22070 * Check the content model.
22071 */
22072 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22073 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22074
22075 /*
22076 * Workaround for "anyType".
22077 */
22078 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22079 goto character_content;
22080
22081 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22082 xmlChar *values[10];
22083 int terminal, nbval = 10, nbneg;
22084
22085 if (inode->regexCtxt == NULL) {
22086 /*
22087 * Create the regex context.
22088 */
22089 inode->regexCtxt =
22090 xmlRegNewExecCtxt(inode->typeDef->contModel,
22091 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22092 vctxt);
22093 if (inode->regexCtxt == NULL) {
22094 VERROR_INT("xmlSchemaValidatorPopElem",
22095 "failed to create a regex context");
22096 goto internal_error;
22097 }
22098#ifdef DEBUG_AUTOMATA
22099 xmlGenericError(xmlGenericErrorContext,
22100 "AUTOMATON create on '%s'\n", inode->localName);
22101#endif
22102 }
22103 /*
22104 * Get hold of the still expected content, since a further
22105 * call to xmlRegExecPushString() will loose this information.
22106 */
22107 xmlRegExecNextValues(inode->regexCtxt,
22108 &nbval, &nbneg, &values[0], &terminal);
22109 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22110 if (ret <= 0) {
22111 /*
22112 * Still missing something.
22113 */
22114 ret = 1;
22115 inode->flags |=
22116 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22117 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22118 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22119 "Missing child element(s)",
22120 nbval, nbneg, values);
22121#ifdef DEBUG_AUTOMATA
22122 xmlGenericError(xmlGenericErrorContext,
22123 "AUTOMATON missing ERROR on '%s'\n",
22124 inode->localName);
22125#endif
22126 } else {
22127 /*
22128 * Content model is satisfied.
22129 */
22130 ret = 0;
22131#ifdef DEBUG_AUTOMATA
22132 xmlGenericError(xmlGenericErrorContext,
22133 "AUTOMATON succeeded on '%s'\n",
22134 inode->localName);
22135#endif
22136 }
22137
22138 }
22139 }
22140 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22141 goto end_elem;
22142
22143character_content:
22144
22145 if (vctxt->value != NULL) {
22146 xmlSchemaFreeValue(vctxt->value);
22147 vctxt->value = NULL;
22148 }
22149 /*
22150 * Check character content.
22151 */
22152 if (inode->decl == NULL) {
22153 /*
22154 * Speedup if no declaration exists.
22155 */
22156 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22157 ret = xmlSchemaVCheckINodeDataType(vctxt,
22158 inode, inode->typeDef, inode->value);
22159 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22160 ret = xmlSchemaVCheckINodeDataType(vctxt,
22161 inode, inode->typeDef->contentTypeDef,
22162 inode->value);
22163 }
22164 if (ret < 0) {
22165 VERROR_INT("xmlSchemaValidatorPopElem",
22166 "calling xmlSchemaVCheckCVCSimpleType()");
22167 goto internal_error;
22168 }
22169 goto end_elem;
22170 }
22171 /*
22172 * cvc-elt (3.3.4) : 5
22173 * The appropriate case among the following must be true:
22174 */
22175 /*
22176 * cvc-elt (3.3.4) : 5.1
22177 * If the declaration has a {value constraint},
22178 * the item has neither element nor character [children] and
22179 * clause 3.2 has not applied, then all of the following must be true:
22180 */
22181 if ((inode->decl->value != NULL) &&
22182 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22183 (! INODE_NILLED(inode))) {
22184 /*
22185 * cvc-elt (3.3.4) : 5.1.1
22186 * If the ·actual type definition· is a ·local type definition·
22187 * then the canonical lexical representation of the {value constraint}
22188 * value must be a valid default for the ·actual type definition· as
22189 * defined in Element Default Valid (Immediate) (§3.3.6).
22190 */
22191 /*
22192 * NOTE: 'local' above means types aquired by xsi:type.
22193 * NOTE: Although the *canonical* value is stated, it is not
22194 * relevant if canonical or not. Additionally XML Schema 1.1
22195 * will removed this requirement as well.
22196 */
22197 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22198
22199 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22200 inode->decl->value, &(inode->val));
22201 if (ret != 0) {
22202 if (ret < 0) {
22203 VERROR_INT("xmlSchemaValidatorPopElem",
22204 "calling xmlSchemaCheckCOSValidDefault()");
22205 goto internal_error;
22206 }
22207 goto end_elem;
22208 }
22209 /*
22210 * Stop here, to avoid redundant validation of the value
22211 * (see following).
22212 */
22213 goto default_psvi;
22214 }
22215 /*
22216 * cvc-elt (3.3.4) : 5.1.2
22217 * The element information item with the canonical lexical
22218 * representation of the {value constraint} value used as its
22219 * ·normalized value· must be ·valid· with respect to the
22220 * ·actual type definition· as defined by Element Locally Valid (Type)
22221 * (§3.3.4).
22222 */
22223 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22224 ret = xmlSchemaVCheckINodeDataType(vctxt,
22225 inode, inode->typeDef, inode->decl->value);
22226 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22227 ret = xmlSchemaVCheckINodeDataType(vctxt,
22228 inode, inode->typeDef->contentTypeDef,
22229 inode->decl->value);
22230 }
22231 if (ret != 0) {
22232 if (ret < 0) {
22233 VERROR_INT("xmlSchemaValidatorPopElem",
22234 "calling xmlSchemaVCheckCVCSimpleType()");
22235 goto internal_error;
22236 }
22237 goto end_elem;
22238 }
22239
22240default_psvi:
22241 /*
22242 * PSVI: Create a text node on the instance element.
22243 */
22244 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22245 (inode->node != NULL)) {
22246 xmlNodePtr textChild;
22247 xmlChar *normValue;
22248 /*
22249 * VAL TODO: Normalize the value.
22250 */
22251 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22252 inode->decl->value);
22253 if (normValue != NULL) {
22254 textChild = xmlNewText(BAD_CAST normValue);
22255 xmlFree(normValue);
22256 } else
22257 textChild = xmlNewText(inode->decl->value);
22258 if (textChild == NULL) {
22259 VERROR_INT("xmlSchemaValidatorPopElem",
22260 "calling xmlNewText()");
22261 goto internal_error;
22262 } else
22263 xmlAddChild(inode->node, textChild);
22264 }
22265
22266 } else if (! INODE_NILLED(inode)) {
22267 /*
22268 * 5.2.1 The element information item must be ·valid· with respect
22269 * to the ·actual type definition· as defined by Element Locally
22270 * Valid (Type) (§3.3.4).
22271 */
22272 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22273 /*
22274 * SPEC (cvc-type) (3.1)
22275 * "If the type definition is a simple type definition, ..."
22276 * (3.1.3) "If clause 3.2 of Element Locally Valid
22277 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22278 * must be ·valid· with respect to the type definition as defined
22279 * by String Valid (§3.14.4).
22280 */
22281 ret = xmlSchemaVCheckINodeDataType(vctxt,
22282 inode, inode->typeDef, inode->value);
22283 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22284 /*
22285 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22286 * definition, then the element information item must be
22287 * ·valid· with respect to the type definition as per
22288 * Element Locally Valid (Complex Type) (§3.4.4);"
22289 *
22290 * SPEC (cvc-complex-type) (2.2)
22291 * "If the {content type} is a simple type definition, ...
22292 * the ·normalized value· of the element information item is
22293 * ·valid· with respect to that simple type definition as
22294 * defined by String Valid (§3.14.4)."
22295 */
22296 ret = xmlSchemaVCheckINodeDataType(vctxt,
22297 inode, inode->typeDef->contentTypeDef, inode->value);
22298 }
22299 if (ret != 0) {
22300 if (ret < 0) {
22301 VERROR_INT("xmlSchemaValidatorPopElem",
22302 "calling xmlSchemaVCheckCVCSimpleType()");
22303 goto internal_error;
22304 }
22305 goto end_elem;
22306 }
22307 /*
22308 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22309 * not applied, all of the following must be true:
22310 */
22311 if ((inode->decl->value != NULL) &&
22312 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22313
22314 /*
22315 * TODO: We will need a computed value, when comparison is
22316 * done on computed values.
22317 */
22318 /*
22319 * 5.2.2.1 The element information item must have no element
22320 * information item [children].
22321 */
22322 if (inode->flags &
22323 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22324 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22325 VERROR(ret, NULL,
22326 "The content must not containt element nodes since "
22327 "there is a fixed value constraint");
22328 goto end_elem;
22329 } else {
22330 /*
22331 * 5.2.2.2 The appropriate case among the following must
22332 * be true:
22333 */
22334 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22335 /*
22336 * 5.2.2.2.1 If the {content type} of the ·actual type
22337 * definition· is mixed, then the *initial value* of the
22338 * item must match the canonical lexical representation
22339 * of the {value constraint} value.
22340 *
22341 * ... the *initial value* of an element information
22342 * item is the string composed of, in order, the
22343 * [character code] of each character information item in
22344 * the [children] of that element information item.
22345 */
22346 if (! xmlStrEqual(inode->value, inode->decl->value)){
22347 /*
22348 * VAL TODO: Report invalid & expected values as well.
22349 * VAL TODO: Implement the canonical stuff.
22350 */
22351 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22352 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22353 ret, NULL, NULL,
22354 "The initial value '%s' does not match the fixed "
22355 "value constraint '%s'",
22356 inode->value, inode->decl->value);
22357 goto end_elem;
22358 }
22359 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22360 /*
22361 * 5.2.2.2.2 If the {content type} of the ·actual type
22362 * definition· is a simple type definition, then the
22363 * *actual value* of the item must match the canonical
22364 * lexical representation of the {value constraint} value.
22365 */
22366 /*
22367 * VAL TODO: *actual value* is the normalized value, impl.
22368 * this.
22369 * VAL TODO: Report invalid & expected values as well.
22370 * VAL TODO: Implement a comparison with the computed values.
22371 */
22372 if (! xmlStrEqual(inode->value,
22373 inode->decl->value)) {
22374 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22375 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22376 ret, NULL, NULL,
22377 "The actual value '%s' does not match the fixed "
22378 "value constraint '%s'",
22379 inode->value,
22380 inode->decl->value);
22381 goto end_elem;
22382 }
22383 }
22384 }
22385 }
22386 }
22387
22388end_elem:
22389 if (vctxt->depth < 0) {
22390 /* TODO: raise error? */
22391 return (0);
22392 }
22393 if (vctxt->depth == vctxt->skipDepth)
22394 vctxt->skipDepth = -1;
22395 /*
22396 * Evaluate the history of XPath state objects.
22397 */
22398 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22399 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022400 /*
22401 * TODO: 6 The element information item must be ·valid· with respect to each of
22402 * the {identity-constraint definitions} as per Identity-constraint
22403 * Satisfied (§3.11.4).
22404 */
22405 /*
22406 * Validate IDC keyrefs.
22407 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022408 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22409 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022410 /*
22411 * Merge/free the IDC table.
22412 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022413 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022414#ifdef DEBUG_IDC
22415 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022416 inode->nsName,
22417 inode->localName,
22418 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022419#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022420 if (vctxt->depth > 0) {
22421 /*
22422 * Merge the IDC node table with the table of the parent node.
22423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022424 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22425 goto internal_error;
22426 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022427 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022428 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022429 * Clear the current ielem.
22430 * VAL TODO: Don't free the PSVI IDC tables if they are
22431 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022432 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022433 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022434 /*
22435 * Skip further processing if we are on the validation root.
22436 */
22437 if (vctxt->depth == 0) {
22438 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022439 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022440 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022441 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022442 /*
22443 * Reset the bubbleDepth if needed.
22444 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022445 if (vctxt->aidcs != NULL) {
22446 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22447 do {
22448 if (aidc->bubbleDepth == vctxt->depth) {
22449 /*
22450 * A bubbleDepth of a key/unique IDC matches the current
22451 * depth, this means that we are leaving the scope of the
22452 * top-most keyref IDC.
22453 */
22454 aidc->bubbleDepth = -1;
22455 }
22456 aidc = aidc->next;
22457 } while (aidc != NULL);
22458 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022459 vctxt->depth--;
22460 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022461 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022462 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022463 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22464 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022465 return (ret);
22466
22467internal_error:
22468 vctxt->err = -1;
22469 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022470}
22471
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022472/*
22473* 3.4.4 Complex Type Definition Validation Rules
22474* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22475*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022476static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022477xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022478{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022479 xmlSchemaNodeInfoPtr pielem;
22480 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022481 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022482
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022483 if (vctxt->depth <= 0) {
22484 VERROR_INT("xmlSchemaValidateChildElem",
22485 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022486 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022487 }
22488 pielem = vctxt->elemInfos[vctxt->depth -1];
22489 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22490 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022491 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022492 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022493 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022494 if (INODE_NILLED(pielem)) {
22495 /*
22496 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22497 */
22498 ACTIVATE_PARENT_ELEM;
22499 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22500 VERROR(ret, NULL,
22501 "Neither character nor element content is allowed, "
22502 "because the element was 'nilled'");
22503 ACTIVATE_ELEM;
22504 goto unexpected_elem;
22505 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022506
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022507 ptype = pielem->typeDef;
22508
22509 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22510 /*
22511 * Workaround for "anyType": we have currently no content model
22512 * assigned for "anyType", so handle it explicitely.
22513 * "anyType" has an unbounded, lax "any" wildcard.
22514 */
22515 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22516 vctxt->inode->localName,
22517 vctxt->inode->nsName);
22518
22519 if (vctxt->inode->decl == NULL) {
22520 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022522 * Process "xsi:type".
22523 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022524 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022525 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22526 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22527 if (iattr != NULL) {
22528 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22529 &(vctxt->inode->typeDef), NULL);
22530 if (ret != 0) {
22531 if (ret == -1) {
22532 VERROR_INT("xmlSchemaValidateChildElem",
22533 "calling xmlSchemaProcessXSIType() to "
22534 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022535 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022536 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022537 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022538 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022539 } else {
22540 /*
22541 * Fallback to "anyType".
22542 *
22543 * SPEC (cvc-assess-elt)
22544 * "If the item cannot be ·strictly assessed·, [...]
22545 * an element information item's schema validity may be laxly
22546 * assessed if its ·context-determined declaration· is not
22547 * skip by ·validating· with respect to the ·ur-type
22548 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22549 */
22550 vctxt->inode->typeDef =
22551 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022552 }
22553 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022554 return (0);
22555 }
22556
22557 switch (ptype->contentType) {
22558 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022559 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022560 * SPEC (2.1) "If the {content type} is empty, then the
22561 * element information item has no character or element
22562 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022563 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022564 ACTIVATE_PARENT_ELEM
22565 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22566 VERROR(ret, NULL,
22567 "Element content is not allowed, "
22568 "because the content type is empty");
22569 ACTIVATE_ELEM
22570 goto unexpected_elem;
22571 break;
22572
22573 case XML_SCHEMA_CONTENT_MIXED:
22574 case XML_SCHEMA_CONTENT_ELEMENTS: {
22575 xmlRegExecCtxtPtr regexCtxt;
22576 xmlChar *values[10];
22577 int terminal, nbval = 10, nbneg;
22578
22579 /* VAL TODO: Optimized "anyType" validation.*/
22580
22581 if (ptype->contModel == NULL) {
22582 VERROR_INT("xmlSchemaValidateChildElem",
22583 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022584 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022586 /*
22587 * Safety belf for evaluation if the cont. model was already
22588 * examined to be invalid.
22589 */
22590 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22591 VERROR_INT("xmlSchemaValidateChildElem",
22592 "validating elem, but elem content is already invalid");
22593 return (-1);
22594 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022595
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022596 regexCtxt = pielem->regexCtxt;
22597 if (regexCtxt == NULL) {
22598 /*
22599 * Create the regex context.
22600 */
22601 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22602 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22603 vctxt);
22604 if (regexCtxt == NULL) {
22605 VERROR_INT("xmlSchemaValidateChildElem",
22606 "failed to create a regex context");
22607 return (-1);
22608 }
22609 pielem->regexCtxt = regexCtxt;
22610#ifdef DEBUG_AUTOMATA
22611 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22612 pielem->localName);
22613#endif
22614 }
22615
22616 /*
22617 * SPEC (2.4) "If the {content type} is element-only or mixed,
22618 * then the sequence of the element information item's
22619 * element information item [children], if any, taken in
22620 * order, is ·valid· with respect to the {content type}'s
22621 * particle, as defined in Element Sequence Locally Valid
22622 * (Particle) (§3.9.4)."
22623 */
22624 ret = xmlRegExecPushString2(regexCtxt,
22625 vctxt->inode->localName,
22626 vctxt->inode->nsName,
22627 vctxt->inode);
22628#ifdef DEBUG_AUTOMATA
22629 if (ret < 0)
22630 xmlGenericError(xmlGenericErrorContext,
22631 "AUTOMATON push ERROR for '%s' on '%s'\n",
22632 vctxt->inode->localName, pielem->localName);
22633 else
22634 xmlGenericError(xmlGenericErrorContext,
22635 "AUTOMATON push OK for '%s' on '%s'\n",
22636 vctxt->inode->localName, pielem->localName);
22637#endif
22638 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22639 VERROR_INT("xmlSchemaValidateChildElem",
22640 "calling xmlRegExecPushString2()");
22641 return (-1);
22642 }
22643 if (ret < 0) {
22644 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22645 &values[0], &terminal);
22646 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22647 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22648 "This element is not expected",
22649 nbval, nbneg, values);
22650 ret = vctxt->err;
22651 goto unexpected_elem;
22652 } else
22653 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022654 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022655 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022656 case XML_SCHEMA_CONTENT_SIMPLE:
22657 case XML_SCHEMA_CONTENT_BASIC:
22658 ACTIVATE_PARENT_ELEM
22659 if (IS_COMPLEX_TYPE(ptype)) {
22660 /*
22661 * SPEC (cvc-complex-type) (2.2)
22662 * "If the {content type} is a simple type definition, then
22663 * the element information item has no element information
22664 * item [children], ..."
22665 */
22666 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22667 VERROR(ret, NULL, "Element content is not allowed, "
22668 "because the content type is a simple type definition");
22669 } else {
22670 /*
22671 * SPEC (cvc-type) (3.1.2) "The element information item must
22672 * have no element information item [children]."
22673 */
22674 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22675 VERROR(ret, NULL, "Element content is not allowed, "
22676 "because the type definition is simple");
22677 }
22678 ACTIVATE_ELEM
22679 ret = vctxt->err;
22680 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022681 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022682
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022683 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022684 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022685 }
22686 return (ret);
22687unexpected_elem:
22688 /*
22689 * Pop this element and set the skipDepth to skip
22690 * all further content of the parent element.
22691 */
22692 vctxt->skipDepth = vctxt->depth;
22693 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22694 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22695 return (ret);
22696}
22697
22698#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22699#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22700#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22701
22702static int
22703xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22704 int nodeType, const xmlChar *value, int len,
22705 int mode, int *consumed)
22706{
22707 /*
22708 * Unfortunately we have to duplicate the text sometimes.
22709 * OPTIMIZE: Maybe we could skip it, if:
22710 * 1. content type is simple
22711 * 2. whitespace is "collapse"
22712 * 3. it consists of whitespace only
22713 *
22714 * Process character content.
22715 */
22716 if (consumed != NULL)
22717 *consumed = 0;
22718 if (INODE_NILLED(vctxt->inode)) {
22719 /*
22720 * SPEC cvc-elt (3.3.4 - 3.2.1)
22721 * "The element information item must have no character or
22722 * element information item [children]."
22723 */
22724 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22725 "Neither character nor element content is allowed "
22726 "because the element is 'nilled'");
22727 return (vctxt->err);
22728 }
22729 /*
22730 * SPEC (2.1) "If the {content type} is empty, then the
22731 * element information item has no character or element
22732 * information item [children]."
22733 */
22734 if (vctxt->inode->typeDef->contentType ==
22735 XML_SCHEMA_CONTENT_EMPTY) {
22736 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22737 "Character content is not allowed, "
22738 "because the content type is empty");
22739 return (vctxt->err);
22740 }
22741
22742 if (vctxt->inode->typeDef->contentType ==
22743 XML_SCHEMA_CONTENT_ELEMENTS) {
22744 if ((nodeType != XML_TEXT_NODE) ||
22745 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22746 /*
22747 * SPEC cvc-complex-type (2.3)
22748 * "If the {content type} is element-only, then the
22749 * element information item has no character information
22750 * item [children] other than those whose [character
22751 * code] is defined as a white space in [XML 1.0 (Second
22752 * Edition)]."
22753 */
22754 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22755 "Character content other than whitespace is not allowed "
22756 "because the content type is 'element-only'");
22757 return (vctxt->err);
22758 }
22759 return (0);
22760 }
22761
22762 if ((value == NULL) || (value[0] == 0))
22763 return (0);
22764 /*
22765 * Save the value.
22766 * NOTE that even if the content type is *mixed*, we need the
22767 * *initial value* for default/fixed value constraints.
22768 */
22769 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22770 ((vctxt->inode->decl == NULL) ||
22771 (vctxt->inode->decl->value == NULL)))
22772 return (0);
22773
22774 if (vctxt->inode->value == NULL) {
22775 /*
22776 * Set the value.
22777 */
22778 switch (mode) {
22779 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22780 /*
22781 * When working on a tree.
22782 */
22783 vctxt->inode->value = value;
22784 break;
22785 case XML_SCHEMA_PUSH_TEXT_CREATED:
22786 /*
22787 * When working with the reader.
22788 * The value will be freed by the element info.
22789 */
22790 vctxt->inode->value = value;
22791 if (consumed != NULL)
22792 *consumed = 1;
22793 vctxt->inode->flags |=
22794 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22795 break;
22796 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22797 /*
22798 * When working with SAX.
22799 * The value will be freed by the element info.
22800 */
22801 if (len != -1)
22802 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22803 else
22804 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22805 vctxt->inode->flags |=
22806 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22807 break;
22808 default:
22809 break;
22810 }
22811 } else {
22812 /*
22813 * Concat the value.
22814 */
22815 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022816 vctxt->inode->value = BAD_CAST xmlStrncat(
22817 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022818 } else {
22819 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022820 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022821 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22822 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022823 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022824
22825 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022826}
22827
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022828static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022829xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022830{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022831 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022832
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022833 if ((vctxt->skipDepth != -1) &&
22834 (vctxt->depth >= vctxt->skipDepth)) {
22835 VERROR_INT("xmlSchemaValidateElem",
22836 "in skip-state");
22837 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022838 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022839 if (vctxt->xsiAssemble) {
22840 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22841 goto internal_error;
22842 }
22843 if (vctxt->depth > 0) {
22844 /*
22845 * Validate this element against the content model
22846 * of the parent.
22847 */
22848 ret = xmlSchemaValidateChildElem(vctxt);
22849 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022850 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022851 VERROR_INT("xmlSchemaValidateElem",
22852 "calling xmlSchemaStreamValidateChildElement()");
22853 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022854 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022855 goto exit;
22856 }
22857 if (vctxt->depth == vctxt->skipDepth)
22858 goto exit;
22859 if ((vctxt->inode->decl == NULL) &&
22860 (vctxt->inode->typeDef == NULL)) {
22861 VERROR_INT("xmlSchemaValidateElem",
22862 "the child element was valid but neither the "
22863 "declaration nor the type was set");
22864 goto internal_error;
22865 }
22866 } else {
22867 /*
22868 * Get the declaration of the validation root.
22869 */
22870 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22871 vctxt->inode->localName,
22872 vctxt->inode->nsName);
22873 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022874 ret = XML_SCHEMAV_CVC_ELT_1;
22875 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022876 "No matching global declaration available "
22877 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022878 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022879 }
22880 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022881
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022882 if (vctxt->inode->decl == NULL)
22883 goto type_validation;
22884
22885 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22886 int skip;
22887 /*
22888 * Wildcards.
22889 */
22890 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22891 if (ret != 0) {
22892 if (ret < 0) {
22893 VERROR_INT("xmlSchemaValidateElem",
22894 "calling xmlSchemaValidateElemWildcard()");
22895 goto internal_error;
22896 }
22897 goto exit;
22898 }
22899 if (skip) {
22900 vctxt->skipDepth = vctxt->depth;
22901 goto exit;
22902 }
22903 /*
22904 * The declaration might be set by the wildcard validation,
22905 * when the processContents is "lax" or "strict".
22906 */
22907 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22908 /*
22909 * Clear the "decl" field to not confuse further processing.
22910 */
22911 vctxt->inode->decl = NULL;
22912 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022913 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022915 /*
22916 * Validate against the declaration.
22917 */
22918 ret = xmlSchemaValidateElemDecl(vctxt);
22919 if (ret != 0) {
22920 if (ret < 0) {
22921 VERROR_INT("xmlSchemaValidateElem",
22922 "calling xmlSchemaValidateElemDecl()");
22923 goto internal_error;
22924 }
22925 goto exit;
22926 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022927 /*
22928 * Validate against the type definition.
22929 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022930type_validation:
22931
22932 if (vctxt->inode->typeDef == NULL) {
22933 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22934 ret = XML_SCHEMAV_CVC_TYPE_1;
22935 VERROR(ret, NULL,
22936 "The type definition is absent");
22937 goto exit;
22938 }
22939 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22940 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22941 ret = XML_SCHEMAV_CVC_TYPE_2;
22942 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022943 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022944 goto exit;
22945 }
22946 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022947 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022948 * during validation against the declaration. This must be done
22949 * _before_ attribute validation.
22950 */
22951 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22952 if (ret == -1) {
22953 VERROR_INT("xmlSchemaValidateElem",
22954 "calling xmlSchemaXPathEvaluate()");
22955 goto internal_error;
22956 }
22957 /*
22958 * Validate attributes.
22959 */
22960 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22961 if ((vctxt->nbAttrInfos != 0) ||
22962 (vctxt->inode->typeDef->attributeUses != NULL)) {
22963
22964 ret = xmlSchemaVAttributesComplex(vctxt);
22965 }
22966 } else if (vctxt->nbAttrInfos != 0) {
22967
22968 ret = xmlSchemaVAttributesSimple(vctxt);
22969 }
22970 /*
22971 * Clear registered attributes.
22972 */
22973 if (vctxt->nbAttrInfos != 0)
22974 xmlSchemaClearAttrInfos(vctxt);
22975 if (ret == -1) {
22976 VERROR_INT("xmlSchemaValidateElem",
22977 "calling attributes validation");
22978 goto internal_error;
22979 }
22980 /*
22981 * Don't return an error if attributes are invalid on purpose.
22982 */
22983 ret = 0;
22984
22985exit:
22986 if (ret != 0)
22987 vctxt->skipDepth = vctxt->depth;
22988 return (ret);
22989internal_error:
22990 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022991}
22992
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022993#ifdef XML_SCHEMA_READER_ENABLED
22994static int
22995xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022996{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022997 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22998 int depth, nodeType, ret = 0, consumed;
22999 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023000
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023001 vctxt->depth = -1;
23002 ret = xmlTextReaderRead(vctxt->reader);
23003 /*
23004 * Move to the document element.
23005 */
23006 while (ret == 1) {
23007 nodeType = xmlTextReaderNodeType(vctxt->reader);
23008 if (nodeType == XML_ELEMENT_NODE)
23009 goto root_found;
23010 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023011 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023012 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023013
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023014root_found:
23015
23016 do {
23017 depth = xmlTextReaderDepth(vctxt->reader);
23018 nodeType = xmlTextReaderNodeType(vctxt->reader);
23019
23020 if (nodeType == XML_ELEMENT_NODE) {
23021
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023022 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023023 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23024 VERROR_INT("xmlSchemaVReaderWalk",
23025 "calling xmlSchemaValidatorPushElem()");
23026 goto internal_error;
23027 }
23028 ielem = vctxt->inode;
23029 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23030 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23031 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23032 /*
23033 * Is the element empty?
23034 */
23035 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23036 if (ret == -1) {
23037 VERROR_INT("xmlSchemaVReaderWalk",
23038 "calling xmlTextReaderIsEmptyElement()");
23039 goto internal_error;
23040 }
23041 if (ret) {
23042 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23043 }
23044 /*
23045 * Register attributes.
23046 */
23047 vctxt->nbAttrInfos = 0;
23048 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23049 if (ret == -1) {
23050 VERROR_INT("xmlSchemaVReaderWalk",
23051 "calling xmlTextReaderMoveToFirstAttribute()");
23052 goto internal_error;
23053 }
23054 if (ret == 1) {
23055 do {
23056 /*
23057 * VAL TODO: How do we know that the reader works on a
23058 * node tree, to be able to pass a node here?
23059 */
23060 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23061 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23062 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23063 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23064
23065 VERROR_INT("xmlSchemaVReaderWalk",
23066 "calling xmlSchemaValidatorPushAttribute()");
23067 goto internal_error;
23068 }
23069 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23070 if (ret == -1) {
23071 VERROR_INT("xmlSchemaVReaderWalk",
23072 "calling xmlTextReaderMoveToFirstAttribute()");
23073 goto internal_error;
23074 }
23075 } while (ret == 1);
23076 /*
23077 * Back to element position.
23078 */
23079 ret = xmlTextReaderMoveToElement(vctxt->reader);
23080 if (ret == -1) {
23081 VERROR_INT("xmlSchemaVReaderWalk",
23082 "calling xmlTextReaderMoveToElement()");
23083 goto internal_error;
23084 }
23085 }
23086 /*
23087 * Validate the element.
23088 */
23089 ret= xmlSchemaValidateElem(vctxt);
23090 if (ret != 0) {
23091 if (ret == -1) {
23092 VERROR_INT("xmlSchemaVReaderWalk",
23093 "calling xmlSchemaValidateElem()");
23094 goto internal_error;
23095 }
23096 goto exit;
23097 }
23098 if (vctxt->depth == vctxt->skipDepth) {
23099 int curDepth;
23100 /*
23101 * Skip all content.
23102 */
23103 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23104 ret = xmlTextReaderRead(vctxt->reader);
23105 curDepth = xmlTextReaderDepth(vctxt->reader);
23106 while ((ret == 1) && (curDepth != depth)) {
23107 ret = xmlTextReaderRead(vctxt->reader);
23108 curDepth = xmlTextReaderDepth(vctxt->reader);
23109 }
23110 if (ret < 0) {
23111 /*
23112 * VAL TODO: A reader error occured; what to do here?
23113 */
23114 ret = 1;
23115 goto exit;
23116 }
23117 }
23118 goto leave_elem;
23119 }
23120 /*
23121 * READER VAL TODO: Is an END_ELEM really never called
23122 * if the elem is empty?
23123 */
23124 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23125 goto leave_elem;
23126 } else if (nodeType == END_ELEM) {
23127 /*
23128 * Process END of element.
23129 */
23130leave_elem:
23131 ret = xmlSchemaValidatorPopElem(vctxt);
23132 if (ret != 0) {
23133 if (ret < 0) {
23134 VERROR_INT("xmlSchemaVReaderWalk",
23135 "calling xmlSchemaValidatorPopElem()");
23136 goto internal_error;
23137 }
23138 goto exit;
23139 }
23140 if (vctxt->depth >= 0)
23141 ielem = vctxt->inode;
23142 else
23143 ielem = NULL;
23144 } else if ((nodeType == XML_TEXT_NODE) ||
23145 (nodeType == XML_CDATA_SECTION_NODE) ||
23146 (nodeType == WHTSP) ||
23147 (nodeType == SIGN_WHTSP)) {
23148 /*
23149 * Process character content.
23150 */
23151 xmlChar *value;
23152
23153 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23154 nodeType = XML_TEXT_NODE;
23155
23156 value = xmlTextReaderValue(vctxt->reader);
23157 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23158 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23159 if (! consumed)
23160 xmlFree(value);
23161 if (ret == -1) {
23162 VERROR_INT("xmlSchemaVReaderWalk",
23163 "calling xmlSchemaVPushText()");
23164 goto internal_error;
23165 }
23166 } else if ((nodeType == XML_ENTITY_NODE) ||
23167 (nodeType == XML_ENTITY_REF_NODE)) {
23168 /*
23169 * VAL TODO: What to do with entities?
23170 */
23171 TODO
23172 }
23173 /*
23174 * Read next node.
23175 */
23176 ret = xmlTextReaderRead(vctxt->reader);
23177 } while (ret == 1);
23178
23179exit:
23180 return (ret);
23181internal_error:
23182 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023183}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023184#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023185
23186/************************************************************************
23187 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023188 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023189 * *
23190 ************************************************************************/
23191
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023192#ifdef XML_SCHEMA_SAX_ENABLED
23193/*
23194* Process text content.
23195*/
23196static void
23197xmlSchemaSAXHandleText(void *ctx,
23198 const xmlChar * ch,
23199 int len)
23200{
23201 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23202
23203 if (vctxt->depth < 0)
23204 return;
23205 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23206 return;
23207 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23208 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23209 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23210 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23211 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23212 "calling xmlSchemaVPushText()");
23213 vctxt->err = -1;
23214 xmlStopParser(vctxt->parserCtxt);
23215 }
23216}
23217
23218/*
23219* Process CDATA content.
23220*/
23221static void
23222xmlSchemaSAXHandleCDataSection(void *ctx,
23223 const xmlChar * ch,
23224 int len)
23225{
23226 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23227
23228 if (vctxt->depth < 0)
23229 return;
23230 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23231 return;
23232 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23233 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23234 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23235 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23236 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23237 "calling xmlSchemaVPushText()");
23238 vctxt->err = -1;
23239 xmlStopParser(vctxt->parserCtxt);
23240 }
23241}
23242
23243static void
23244xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23245 const xmlChar * name ATTRIBUTE_UNUSED)
23246{
23247 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23248
23249 if (vctxt->depth < 0)
23250 return;
23251 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23252 return;
23253 /* SAX VAL TODO: What to do here? */
23254 TODO
23255}
23256
23257static void
23258xmlSchemaSAXHandleStartElementNs(void *ctx,
23259 const xmlChar * localname,
23260 const xmlChar * prefix ATTRIBUTE_UNUSED,
23261 const xmlChar * URI,
23262 int nb_namespaces,
23263 const xmlChar ** namespaces,
23264 int nb_attributes,
23265 int nb_defaulted ATTRIBUTE_UNUSED,
23266 const xmlChar ** attributes)
23267{
23268 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23269 int ret;
23270 xmlSchemaNodeInfoPtr ielem;
23271 int i, j;
23272
23273 /*
23274 * SAX VAL TODO: What to do with nb_defaulted?
23275 */
23276 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023277 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023278 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023279 vctxt->depth++;
23280 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023281 return;
23282 /*
23283 * Push the element.
23284 */
23285 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23286 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23287 "calling xmlSchemaValidatorPushElem()");
23288 goto internal_error;
23289 }
23290 ielem = vctxt->inode;
23291 ielem->localName = localname;
23292 ielem->nsName = URI;
23293 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23294 /*
23295 * Register namespaces on the elem info.
23296 */
23297 if (nb_namespaces != 0) {
23298 /*
23299 * Although the parser builds its own namespace list,
23300 * we have no access to it, so we'll use an own one.
23301 */
23302 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23303 /*
23304 * Store prefix and namespace name.
23305 */
23306 if (ielem->nsBindings == NULL) {
23307 ielem->nsBindings =
23308 (const xmlChar **) xmlMalloc(10 *
23309 sizeof(const xmlChar *));
23310 if (ielem->nsBindings == NULL) {
23311 xmlSchemaVErrMemory(vctxt,
23312 "allocating namespace bindings for SAX validation",
23313 NULL);
23314 goto internal_error;
23315 }
23316 ielem->nbNsBindings = 0;
23317 ielem->sizeNsBindings = 5;
23318 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23319 ielem->sizeNsBindings *= 2;
23320 ielem->nsBindings =
23321 (const xmlChar **) xmlRealloc(
23322 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023323 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023324 if (ielem->nsBindings == NULL) {
23325 xmlSchemaVErrMemory(vctxt,
23326 "re-allocating namespace bindings for SAX validation",
23327 NULL);
23328 goto internal_error;
23329 }
23330 }
23331
23332 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23333 if (namespaces[j+1][0] == 0) {
23334 /*
23335 * Handle xmlns="".
23336 */
23337 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23338 } else
23339 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23340 namespaces[j+1];
23341 ielem->nbNsBindings++;
23342 }
23343 }
23344 /*
23345 * Register attributes.
23346 * SAX VAL TODO: We are not adding namespace declaration
23347 * attributes yet.
23348 */
23349 if (nb_attributes != 0) {
23350 xmlChar *value;
23351
23352 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23353 /*
23354 * Duplicate the value.
23355 */
23356 value = xmlStrndup(attributes[j+3],
23357 attributes[j+4] - attributes[j+3]);
23358 ret = xmlSchemaValidatorPushAttribute(vctxt,
23359 NULL, attributes[j], attributes[j+2], 0,
23360 value, 1);
23361 if (ret == -1) {
23362 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23363 "calling xmlSchemaValidatorPushAttribute()");
23364 goto internal_error;
23365 }
23366 }
23367 }
23368 /*
23369 * Validate the element.
23370 */
23371 ret = xmlSchemaValidateElem(vctxt);
23372 if (ret != 0) {
23373 if (ret == -1) {
23374 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23375 "calling xmlSchemaValidateElem()");
23376 goto internal_error;
23377 }
23378 goto exit;
23379 }
23380
23381exit:
23382 return;
23383internal_error:
23384 vctxt->err = -1;
23385 xmlStopParser(vctxt->parserCtxt);
23386 return;
23387}
23388
23389static void
23390xmlSchemaSAXHandleEndElementNs(void *ctx,
23391 const xmlChar * localname ATTRIBUTE_UNUSED,
23392 const xmlChar * prefix ATTRIBUTE_UNUSED,
23393 const xmlChar * URI ATTRIBUTE_UNUSED)
23394{
23395 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23396 int res;
23397
23398 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023399 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023400 */
23401 if (vctxt->skipDepth != -1) {
23402 if (vctxt->depth > vctxt->skipDepth) {
23403 vctxt->depth--;
23404 return;
23405 } else
23406 vctxt->skipDepth = -1;
23407 }
23408 /*
23409 * SAX VAL TODO: Just a temporary check.
23410 */
23411 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23412 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23413 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23414 "elem pop mismatch");
23415 }
23416 res = xmlSchemaValidatorPopElem(vctxt);
23417 if (res != 0) {
23418 if (res < 0) {
23419 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23420 "calling xmlSchemaValidatorPopElem()");
23421 goto internal_error;
23422 }
23423 goto exit;
23424 }
23425exit:
23426 return;
23427internal_error:
23428 vctxt->err = -1;
23429 xmlStopParser(vctxt->parserCtxt);
23430 return;
23431}
23432#endif
23433
Daniel Veillard4255d502002-04-16 15:50:10 +000023434/************************************************************************
23435 * *
23436 * Validation interfaces *
23437 * *
23438 ************************************************************************/
23439
23440/**
23441 * xmlSchemaNewValidCtxt:
23442 * @schema: a precompiled XML Schemas
23443 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023444 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023445 *
23446 * Returns the validation context or NULL in case of error
23447 */
23448xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023449xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23450{
Daniel Veillard4255d502002-04-16 15:50:10 +000023451 xmlSchemaValidCtxtPtr ret;
23452
23453 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23454 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023455 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023456 return (NULL);
23457 }
23458 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023459 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23460 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023461 return (ret);
23462}
23463
23464/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023465 * xmlSchemaClearValidCtxt:
23466 * @ctxt: the schema validation context
23467 *
23468 * Free the resources associated to the schema validation context;
23469 * leaves some fields alive intended for reuse of the context.
23470 */
23471static void
23472xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23473{
23474 if (vctxt == NULL)
23475 return;
23476
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023477 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023478 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023479 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023480#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023481 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023482#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023483 if (vctxt->value != NULL) {
23484 xmlSchemaFreeValue(vctxt->value);
23485 vctxt->value = NULL;
23486 }
23487 /*
23488 * Augmented IDC information.
23489 */
23490 if (vctxt->aidcs != NULL) {
23491 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23492 do {
23493 next = cur->next;
23494 xmlFree(cur);
23495 cur = next;
23496 } while (cur != NULL);
23497 vctxt->aidcs = NULL;
23498 }
23499 if (vctxt->idcNodes != NULL) {
23500 int i;
23501 xmlSchemaPSVIIDCNodePtr item;
23502
23503 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023504 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023505 xmlFree(item->keys);
23506 xmlFree(item);
23507 }
23508 xmlFree(vctxt->idcNodes);
23509 vctxt->idcNodes = NULL;
23510 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023511 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023512 * Note that we won't delete the XPath state pool here.
23513 */
23514 if (vctxt->xpathStates != NULL) {
23515 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23516 vctxt->xpathStates = NULL;
23517 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023518 /*
23519 * Attribute info.
23520 */
23521 if (vctxt->nbAttrInfos != 0) {
23522 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023523 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023524 /*
23525 * Element info.
23526 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023527 if (vctxt->elemInfos != NULL) {
23528 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023529 xmlSchemaNodeInfoPtr ei;
23530
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023531 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023532 ei = vctxt->elemInfos[i];
23533 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023534 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023535 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023536 }
23537 }
23538}
23539
23540/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023541 * xmlSchemaFreeValidCtxt:
23542 * @ctxt: the schema validation context
23543 *
23544 * Free the resources associated to the schema validation context
23545 */
23546void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023547xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23548{
Daniel Veillard4255d502002-04-16 15:50:10 +000023549 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023550 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023551 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023552 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023553 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023554 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023555 if (ctxt->idcNodes != NULL) {
23556 int i;
23557 xmlSchemaPSVIIDCNodePtr item;
23558
23559 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023560 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023561 xmlFree(item->keys);
23562 xmlFree(item);
23563 }
23564 xmlFree(ctxt->idcNodes);
23565 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023566 if (ctxt->idcKeys != NULL) {
23567 int i;
23568 for (i = 0; i < ctxt->nbIdcKeys; i++)
23569 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23570 xmlFree(ctxt->idcKeys);
23571 }
23572
23573 if (ctxt->xpathStates != NULL)
23574 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23575 if (ctxt->xpathStatePool != NULL)
23576 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23577
23578 /*
23579 * Augmented IDC information.
23580 */
23581 if (ctxt->aidcs != NULL) {
23582 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23583 do {
23584 next = cur->next;
23585 xmlFree(cur);
23586 cur = next;
23587 } while (cur != NULL);
23588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023589 if (ctxt->attrInfos != NULL) {
23590 int i;
23591 xmlSchemaAttrInfoPtr attr;
23592
23593 /* Just a paranoid call to the cleanup. */
23594 if (ctxt->nbAttrInfos != 0)
23595 xmlSchemaClearAttrInfos(ctxt);
23596 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23597 attr = ctxt->attrInfos[i];
23598 xmlFree(attr);
23599 }
23600 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023601 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023602 if (ctxt->elemInfos != NULL) {
23603 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023604 xmlSchemaNodeInfoPtr ei;
23605
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023606 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023607 ei = ctxt->elemInfos[i];
23608 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023609 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023610 xmlSchemaClearElemInfo(ei);
23611 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023612 }
23613 xmlFree(ctxt->elemInfos);
23614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023615 if (ctxt->dict != NULL)
23616 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023617 xmlFree(ctxt);
23618}
23619
23620/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023621 * xmlSchemaIsValid:
23622 * @ctxt: the schema validation context
23623 *
23624 * Check if any error was detected during validation.
23625 *
23626 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23627 * of internal error.
23628 */
23629int
23630xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23631{
23632 if (ctxt == NULL)
23633 return(-1);
23634 return(ctxt->err == 0);
23635}
23636
23637/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023638 * xmlSchemaSetValidErrors:
23639 * @ctxt: a schema validation context
23640 * @err: the error function
23641 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023642 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023643 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023644 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023645 */
23646void
23647xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023648 xmlSchemaValidityErrorFunc err,
23649 xmlSchemaValidityWarningFunc warn, void *ctx)
23650{
Daniel Veillard4255d502002-04-16 15:50:10 +000023651 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023652 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023653 ctxt->error = err;
23654 ctxt->warning = warn;
23655 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023656 if (ctxt->pctxt != NULL)
23657 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023658}
23659
23660/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023661 * xmlSchemaSetValidStructuredErrors:
23662 * @ctxt: a schema validation context
23663 * @serror: the structured error function
23664 * @ctx: the functions context
23665 *
23666 * Set the structured error callback
23667 */
23668void
23669xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23670 xmlStructuredErrorFunc serror, void *ctx)
23671{
23672 if (ctxt == NULL)
23673 return;
23674 ctxt->serror = serror;
23675 ctxt->error = NULL;
23676 ctxt->warning = NULL;
23677 ctxt->userData = ctx;
23678}
23679
23680/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023681 * xmlSchemaGetValidErrors:
23682 * @ctxt: a XML-Schema validation context
23683 * @err: the error function result
23684 * @warn: the warning function result
23685 * @ctx: the functions context result
23686 *
23687 * Get the error and warning callback informations
23688 *
23689 * Returns -1 in case of error and 0 otherwise
23690 */
23691int
23692xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23693 xmlSchemaValidityErrorFunc * err,
23694 xmlSchemaValidityWarningFunc * warn, void **ctx)
23695{
23696 if (ctxt == NULL)
23697 return (-1);
23698 if (err != NULL)
23699 *err = ctxt->error;
23700 if (warn != NULL)
23701 *warn = ctxt->warning;
23702 if (ctx != NULL)
23703 *ctx = ctxt->userData;
23704 return (0);
23705}
23706
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023707
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023708/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023709 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023710 * @ctxt: a schema validation context
23711 * @options: a combination of xmlSchemaValidOption
23712 *
23713 * Sets the options to be used during the validation.
23714 *
23715 * Returns 0 in case of success, -1 in case of an
23716 * API error.
23717 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023718int
23719xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23720 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023721
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023722{
23723 int i;
23724
23725 if (ctxt == NULL)
23726 return (-1);
23727 /*
23728 * WARNING: Change the start value if adding to the
23729 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023730 * TODO: Is there an other, more easy to maintain,
23731 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023732 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023733 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023734 if (options & 1<<i)
23735 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023736 }
23737 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023738 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023739}
23740
23741/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023742 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023743 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023744 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023745 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023746 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023747 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023748 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023749int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023750xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023751
23752{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023753 if (ctxt == NULL)
23754 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023755 else
23756 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023757}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023759static int
23760xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23761{
23762 xmlAttrPtr attr;
23763 int ret = 0;
23764 xmlSchemaNodeInfoPtr ielem = NULL;
23765 xmlNodePtr node, valRoot;
23766 const xmlChar *nsName;
23767
23768 /* DOC VAL TODO: Move this to the start function. */
23769 valRoot = xmlDocGetRootElement(vctxt->doc);
23770 if (valRoot == NULL) {
23771 /* VAL TODO: Error code? */
23772 VERROR(1, NULL, "The document has no document element");
23773 return (1);
23774 }
23775 vctxt->depth = -1;
23776 vctxt->validationRoot = valRoot;
23777 node = valRoot;
23778 while (node != NULL) {
23779 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23780 goto next_sibling;
23781 if (node->type == XML_ELEMENT_NODE) {
23782
23783 /*
23784 * Init the node-info.
23785 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023786 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023787 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23788 goto internal_error;
23789 ielem = vctxt->inode;
23790 ielem->node = node;
23791 ielem->localName = node->name;
23792 if (node->ns != NULL)
23793 ielem->nsName = node->ns->href;
23794 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23795 /*
23796 * Register attributes.
23797 * DOC VAL TODO: We do not register namespace declaration
23798 * attributes yet.
23799 */
23800 vctxt->nbAttrInfos = 0;
23801 if (node->properties != NULL) {
23802 attr = node->properties;
23803 do {
23804 if (attr->ns != NULL)
23805 nsName = attr->ns->href;
23806 else
23807 nsName = NULL;
23808 ret = xmlSchemaValidatorPushAttribute(vctxt,
23809 (xmlNodePtr) attr,
23810 attr->name, nsName, 0,
23811 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23812 if (ret == -1) {
23813 VERROR_INT("xmlSchemaDocWalk",
23814 "calling xmlSchemaValidatorPushAttribute()");
23815 goto internal_error;
23816 }
23817 attr = attr->next;
23818 } while (attr);
23819 }
23820 /*
23821 * Validate the element.
23822 */
23823 ret = xmlSchemaValidateElem(vctxt);
23824 if (ret != 0) {
23825 if (ret == -1) {
23826 VERROR_INT("xmlSchemaDocWalk",
23827 "calling xmlSchemaValidateElem()");
23828 goto internal_error;
23829 }
23830 /*
23831 * Don't stop validation; just skip the content
23832 * of this element.
23833 */
23834 goto leave_node;
23835 }
23836 if ((vctxt->skipDepth != -1) &&
23837 (vctxt->depth >= vctxt->skipDepth))
23838 goto leave_node;
23839 } else if ((node->type == XML_TEXT_NODE) ||
23840 (node->type == XML_CDATA_SECTION_NODE)) {
23841 /*
23842 * Process character content.
23843 */
23844 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23845 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23846 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23847 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23848 if (ret < 0) {
23849 VERROR_INT("xmlSchemaVDocWalk",
23850 "calling xmlSchemaVPushText()");
23851 goto internal_error;
23852 }
23853 /*
23854 * DOC VAL TODO: Should we skip further validation of the
23855 * element content here?
23856 */
23857 } else if ((node->type == XML_ENTITY_NODE) ||
23858 (node->type == XML_ENTITY_REF_NODE)) {
23859 /*
23860 * DOC VAL TODO: What to do with entities?
23861 */
23862 TODO
23863 } else {
23864 goto leave_node;
23865 /*
23866 * DOC VAL TODO: XInclude nodes, etc.
23867 */
23868 }
23869 /*
23870 * Walk the doc.
23871 */
23872 if (node->children != NULL) {
23873 node = node->children;
23874 continue;
23875 }
23876leave_node:
23877 if (node->type == XML_ELEMENT_NODE) {
23878 /*
23879 * Leaving the scope of an element.
23880 */
23881 if (node != vctxt->inode->node) {
23882 VERROR_INT("xmlSchemaVDocWalk",
23883 "element position mismatch");
23884 goto internal_error;
23885 }
23886 ret = xmlSchemaValidatorPopElem(vctxt);
23887 if (ret != 0) {
23888 if (ret < 0) {
23889 VERROR_INT("xmlSchemaVDocWalk",
23890 "calling xmlSchemaValidatorPopElem()");
23891 goto internal_error;
23892 }
23893 }
23894 if (node == valRoot)
23895 goto exit;
23896 }
23897next_sibling:
23898 if (node->next != NULL)
23899 node = node->next;
23900 else {
23901 node = node->parent;
23902 goto leave_node;
23903 }
23904 }
23905
23906exit:
23907 return (ret);
23908internal_error:
23909 return (-1);
23910}
23911
23912static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023913xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023914 /*
23915 * Some initialization.
23916 */
23917 vctxt->err = 0;
23918 vctxt->nberrors = 0;
23919 vctxt->depth = -1;
23920 vctxt->skipDepth = -1;
23921 /*
23922 * Create a schema + parser if necessary.
23923 */
23924 if (vctxt->schema == NULL) {
23925
23926 if ((vctxt->pctxt == NULL) &&
23927 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23928 return (-1);
23929
23930 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23931 if (vctxt->schema == NULL) {
23932 VERROR_INT("xmlSchemaVStartValidation",
23933 "creating a schema");
23934 return (-1);
23935 }
23936 vctxt->xsiAssemble = 1;
23937 } else
23938 vctxt->xsiAssemble = 0;
23939 /*
23940 * Augment the IDC definitions.
23941 */
23942 if (vctxt->schema->idcDef != NULL) {
23943 xmlHashScan(vctxt->schema->idcDef,
23944 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23945 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023946 return(0);
23947}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023948
Daniel Veillardf10ae122005-07-10 19:03:16 +000023949static void
23950xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023951 if (vctxt->xsiAssemble) {
23952 if (vctxt->schema != NULL) {
23953 xmlSchemaFree(vctxt->schema);
23954 vctxt->schema = NULL;
23955 }
23956 }
23957 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000023958}
23959
23960static int
23961xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23962{
23963 int ret = 0;
23964
23965 if (xmlSchemaPreRun(vctxt) < 0)
23966 return(-1);
23967
23968 if (vctxt->doc != NULL) {
23969 /*
23970 * Tree validation.
23971 */
23972 ret = xmlSchemaVDocWalk(vctxt);
23973#ifdef LIBXML_READER_ENABLED
23974 } else if (vctxt->reader != NULL) {
23975 /*
23976 * XML Reader validation.
23977 */
23978#ifdef XML_SCHEMA_READER_ENABLED
23979 ret = xmlSchemaVReaderWalk(vctxt);
23980#endif
23981#endif
23982 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23983 /*
23984 * SAX validation.
23985 */
23986 ret = xmlParseDocument(vctxt->parserCtxt);
23987 } else {
23988 VERROR_INT("xmlSchemaVStartValidation",
23989 "no instance to validate");
23990 ret = -1;
23991 }
23992
23993 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023994 if (ret == 0)
23995 ret = vctxt->err;
23996 return (ret);
23997}
23998
23999/**
24000 * xmlSchemaValidateOneElement:
24001 * @ctxt: a schema validation context
24002 * @elem: an element node
24003 *
24004 * Validate a branch of a tree, starting with the given @elem.
24005 *
24006 * Returns 0 if the element and its subtree is valid, a positive error
24007 * code number otherwise and -1 in case of an internal or API error.
24008 */
24009int
24010xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24011{
24012 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24013 return (-1);
24014
24015 if (ctxt->schema == NULL)
24016 return (-1);
24017
24018 ctxt->doc = elem->doc;
24019 ctxt->node = elem;
24020 ctxt->validationRoot = elem;
24021 return(xmlSchemaVStart(ctxt));
24022}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024023
Daniel Veillard259f0df2004-08-18 09:13:18 +000024024/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024025 * xmlSchemaValidateDoc:
24026 * @ctxt: a schema validation context
24027 * @doc: a parsed document tree
24028 *
24029 * Validate a document tree in memory.
24030 *
24031 * Returns 0 if the document is schemas valid, a positive error code
24032 * number otherwise and -1 in case of internal or API error.
24033 */
24034int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024035xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24036{
Daniel Veillard4255d502002-04-16 15:50:10 +000024037 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024038 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024039
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024040 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024041 ctxt->node = xmlDocGetRootElement(doc);
24042 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024043 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024044 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24045 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024046 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024047 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024048 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024049 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024050 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024051}
24052
Daniel Veillardcdc82732005-07-08 15:04:06 +000024053
24054/************************************************************************
24055 * *
24056 * Function and data for SAX streaming API *
24057 * *
24058 ************************************************************************/
24059typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24060typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24061
24062struct _xmlSchemaSplitSAXData {
24063 xmlSAXHandlerPtr user_sax;
24064 void *user_data;
24065 xmlSchemaValidCtxtPtr ctxt;
24066 xmlSAXHandlerPtr schemas_sax;
24067};
24068
Daniel Veillard971771e2005-07-09 17:32:57 +000024069#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24070
24071struct _xmlSchemaSAXPlug {
24072 unsigned int magic;
24073
24074 /* the original callbacks informations */
24075 xmlSAXHandlerPtr *user_sax_ptr;
24076 xmlSAXHandlerPtr user_sax;
24077 void **user_data_ptr;
24078 void *user_data;
24079
24080 /* the block plugged back and validation informations */
24081 xmlSAXHandler schemas_sax;
24082 xmlSchemaValidCtxtPtr ctxt;
24083};
24084
Daniel Veillardcdc82732005-07-08 15:04:06 +000024085/* All those functions just bounces to the user provided SAX handlers */
24086static void
24087internalSubsetSplit(void *ctx, const xmlChar *name,
24088 const xmlChar *ExternalID, const xmlChar *SystemID)
24089{
Daniel Veillard971771e2005-07-09 17:32:57 +000024090 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024091 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24092 (ctxt->user_sax->internalSubset != NULL))
24093 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24094 SystemID);
24095}
24096
24097static int
24098isStandaloneSplit(void *ctx)
24099{
Daniel Veillard971771e2005-07-09 17:32:57 +000024100 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024101 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24102 (ctxt->user_sax->isStandalone != NULL))
24103 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24104 return(0);
24105}
24106
24107static int
24108hasInternalSubsetSplit(void *ctx)
24109{
Daniel Veillard971771e2005-07-09 17:32:57 +000024110 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024111 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24112 (ctxt->user_sax->hasInternalSubset != NULL))
24113 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24114 return(0);
24115}
24116
24117static int
24118hasExternalSubsetSplit(void *ctx)
24119{
Daniel Veillard971771e2005-07-09 17:32:57 +000024120 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024121 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24122 (ctxt->user_sax->hasExternalSubset != NULL))
24123 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24124 return(0);
24125}
24126
24127static void
24128externalSubsetSplit(void *ctx, const xmlChar *name,
24129 const xmlChar *ExternalID, const xmlChar *SystemID)
24130{
Daniel Veillard971771e2005-07-09 17:32:57 +000024131 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024132 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24133 (ctxt->user_sax->internalSubset != NULL))
24134 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24135 SystemID);
24136}
24137
24138static xmlParserInputPtr
24139resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24140{
Daniel Veillard971771e2005-07-09 17:32:57 +000024141 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024142 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24143 (ctxt->user_sax->resolveEntity != NULL))
24144 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24145 systemId));
24146 return(NULL);
24147}
24148
24149static xmlEntityPtr
24150getEntitySplit(void *ctx, const xmlChar *name)
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->getEntity != NULL))
24155 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24156 return(NULL);
24157}
24158
24159static xmlEntityPtr
24160getParameterEntitySplit(void *ctx, const xmlChar *name)
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->getParameterEntity != NULL))
24165 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24166 return(NULL);
24167}
24168
24169
24170static void
24171entityDeclSplit(void *ctx, const xmlChar *name, int type,
24172 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24173{
Daniel Veillard971771e2005-07-09 17:32:57 +000024174 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024175 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24176 (ctxt->user_sax->entityDecl != NULL))
24177 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24178 systemId, content);
24179}
24180
24181static void
24182attributeDeclSplit(void *ctx, const xmlChar * elem,
24183 const xmlChar * name, int type, int def,
24184 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24185{
Daniel Veillard971771e2005-07-09 17:32:57 +000024186 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024187 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24188 (ctxt->user_sax->attributeDecl != NULL)) {
24189 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24190 def, defaultValue, tree);
24191 } else {
24192 xmlFreeEnumeration(tree);
24193 }
24194}
24195
24196static void
24197elementDeclSplit(void *ctx, const xmlChar *name, int type,
24198 xmlElementContentPtr content)
24199{
Daniel Veillard971771e2005-07-09 17:32:57 +000024200 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024201 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24202 (ctxt->user_sax->elementDecl != NULL))
24203 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24204}
24205
24206static void
24207notationDeclSplit(void *ctx, const xmlChar *name,
24208 const xmlChar *publicId, const xmlChar *systemId)
24209{
Daniel Veillard971771e2005-07-09 17:32:57 +000024210 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024211 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24212 (ctxt->user_sax->notationDecl != NULL))
24213 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24214 systemId);
24215}
24216
24217static void
24218unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24219 const xmlChar *publicId, const xmlChar *systemId,
24220 const xmlChar *notationName)
24221{
Daniel Veillard971771e2005-07-09 17:32:57 +000024222 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024223 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24224 (ctxt->user_sax->unparsedEntityDecl != NULL))
24225 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24226 systemId, notationName);
24227}
24228
24229static void
24230setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24231{
Daniel Veillard971771e2005-07-09 17:32:57 +000024232 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024233 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24234 (ctxt->user_sax->setDocumentLocator != NULL))
24235 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24236}
24237
24238static void
24239startDocumentSplit(void *ctx)
24240{
Daniel Veillard971771e2005-07-09 17:32:57 +000024241 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024242 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24243 (ctxt->user_sax->startDocument != NULL))
24244 ctxt->user_sax->startDocument(ctxt->user_data);
24245}
24246
24247static void
24248endDocumentSplit(void *ctx)
24249{
Daniel Veillard971771e2005-07-09 17:32:57 +000024250 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024251 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24252 (ctxt->user_sax->endDocument != NULL))
24253 ctxt->user_sax->endDocument(ctxt->user_data);
24254}
24255
24256static void
24257processingInstructionSplit(void *ctx, const xmlChar *target,
24258 const xmlChar *data)
24259{
Daniel Veillard971771e2005-07-09 17:32:57 +000024260 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024261 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24262 (ctxt->user_sax->processingInstruction != NULL))
24263 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24264}
24265
24266static void
24267commentSplit(void *ctx, const xmlChar *value)
24268{
Daniel Veillard971771e2005-07-09 17:32:57 +000024269 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024270 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24271 (ctxt->user_sax->comment != NULL))
24272 ctxt->user_sax->comment(ctxt->user_data, value);
24273}
24274
24275/*
24276 * Varargs error callbacks to the user application, harder ...
24277 */
24278
24279static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024280warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024281 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024282 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24283 (ctxt->user_sax->warning != NULL)) {
24284 TODO
24285 }
24286}
24287static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024288errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024289 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024290 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24291 (ctxt->user_sax->error != NULL)) {
24292 TODO
24293 }
24294}
24295static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024296fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024297 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024298 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24299 (ctxt->user_sax->fatalError != NULL)) {
24300 TODO
24301 }
24302}
24303
24304/*
24305 * Those are function where both the user handler and the schemas handler
24306 * need to be called.
24307 */
24308static void
24309charactersSplit(void *ctx, const xmlChar *ch, int len)
24310{
Daniel Veillard971771e2005-07-09 17:32:57 +000024311 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024312 if (ctxt == NULL)
24313 return;
24314 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24315 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24316 if (ctxt->ctxt != NULL)
24317 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24318}
24319
24320static void
24321ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24322{
Daniel Veillard971771e2005-07-09 17:32:57 +000024323 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024324 if (ctxt == NULL)
24325 return;
24326 if ((ctxt->user_sax != NULL) &&
24327 (ctxt->user_sax->ignorableWhitespace != NULL))
24328 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24329 if (ctxt->ctxt != NULL)
24330 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24331}
24332
24333static void
24334cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24335{
Daniel Veillard971771e2005-07-09 17:32:57 +000024336 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024337 if (ctxt == NULL)
24338 return;
24339 if ((ctxt->user_sax != NULL) &&
24340 (ctxt->user_sax->ignorableWhitespace != NULL))
24341 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24342 if (ctxt->ctxt != NULL)
24343 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24344}
24345
24346static void
24347referenceSplit(void *ctx, const xmlChar *name)
24348{
Daniel Veillard971771e2005-07-09 17:32:57 +000024349 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024350 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24351 (ctxt->user_sax->reference != NULL))
24352 ctxt->user_sax->reference(ctxt->user_data, name);
24353 if (ctxt->ctxt != NULL)
24354 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24355}
24356
24357static void
24358startElementNsSplit(void *ctx, const xmlChar * localname,
24359 const xmlChar * prefix, const xmlChar * URI,
24360 int nb_namespaces, const xmlChar ** namespaces,
24361 int nb_attributes, int nb_defaulted,
24362 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024363 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024364 if (ctxt == NULL)
24365 return;
24366 if ((ctxt->user_sax != NULL) &&
24367 (ctxt->user_sax->startElementNs != NULL))
24368 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24369 URI, nb_namespaces, namespaces,
24370 nb_attributes, nb_defaulted,
24371 attributes);
24372 if (ctxt->ctxt != NULL)
24373 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24374 URI, nb_namespaces, namespaces,
24375 nb_attributes, nb_defaulted,
24376 attributes);
24377}
24378
24379static void
24380endElementNsSplit(void *ctx, const xmlChar * localname,
24381 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024382 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024383 if (ctxt == NULL)
24384 return;
24385 if ((ctxt->user_sax != NULL) &&
24386 (ctxt->user_sax->endElementNs != NULL))
24387 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24388 if (ctxt->ctxt != NULL)
24389 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24390}
24391
Daniel Veillard4255d502002-04-16 15:50:10 +000024392/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024393 * xmlSchemaSAXPlug:
24394 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024395 * @sax: a pointer to the original xmlSAXHandlerPtr
24396 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024397 *
24398 * Plug a SAX based validation layer in a SAX parsing event flow.
24399 * The original @saxptr and @dataptr data are replaced by new pointers
24400 * but the calls to the original will be maintained.
24401 *
24402 * Returns a pointer to a data structure needed to unplug the validation layer
24403 * or NULL in case of errors.
24404 */
24405xmlSchemaSAXPlugPtr
24406xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24407 xmlSAXHandlerPtr *sax, void **user_data)
24408{
24409 xmlSchemaSAXPlugPtr ret;
24410 xmlSAXHandlerPtr old_sax;
24411
24412 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24413 return(NULL);
24414
24415 /*
24416 * We only allow to plug into SAX2 event streams
24417 */
24418 old_sax = *sax;
24419 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24420 return(NULL);
24421 if ((old_sax != NULL) &&
24422 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24423 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24424 return(NULL);
24425
24426 /*
24427 * everything seems right allocate the local data needed for that layer
24428 */
24429 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24430 if (ret == NULL) {
24431 return(NULL);
24432 }
24433 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24434 ret->magic = XML_SAX_PLUG_MAGIC;
24435 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24436 ret->ctxt = ctxt;
24437 ret->user_sax_ptr = sax;
24438 ret->user_sax = old_sax;
24439 if (old_sax == NULL) {
24440 /*
24441 * go direct, no need for the split block and functions.
24442 */
24443 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24444 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24445 /*
24446 * Note that we use the same text-function for both, to prevent
24447 * the parser from testing for ignorable whitespace.
24448 */
24449 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24450 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24451
24452 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24453 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24454
24455 ret->user_data = ctxt;
24456 *user_data = ctxt;
24457 } else {
24458 /*
24459 * for each callback unused by Schemas initialize it to the Split
24460 * routine only if non NULL in the user block, this can speed up
24461 * things at the SAX level.
24462 */
24463 if (old_sax->internalSubset != NULL)
24464 ret->schemas_sax.internalSubset = internalSubsetSplit;
24465 if (old_sax->isStandalone != NULL)
24466 ret->schemas_sax.isStandalone = isStandaloneSplit;
24467 if (old_sax->hasInternalSubset != NULL)
24468 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24469 if (old_sax->hasExternalSubset != NULL)
24470 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24471 if (old_sax->resolveEntity != NULL)
24472 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24473 if (old_sax->getEntity != NULL)
24474 ret->schemas_sax.getEntity = getEntitySplit;
24475 if (old_sax->entityDecl != NULL)
24476 ret->schemas_sax.entityDecl = entityDeclSplit;
24477 if (old_sax->notationDecl != NULL)
24478 ret->schemas_sax.notationDecl = notationDeclSplit;
24479 if (old_sax->attributeDecl != NULL)
24480 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24481 if (old_sax->elementDecl != NULL)
24482 ret->schemas_sax.elementDecl = elementDeclSplit;
24483 if (old_sax->unparsedEntityDecl != NULL)
24484 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24485 if (old_sax->setDocumentLocator != NULL)
24486 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24487 if (old_sax->startDocument != NULL)
24488 ret->schemas_sax.startDocument = startDocumentSplit;
24489 if (old_sax->endDocument != NULL)
24490 ret->schemas_sax.endDocument = endDocumentSplit;
24491 if (old_sax->processingInstruction != NULL)
24492 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24493 if (old_sax->comment != NULL)
24494 ret->schemas_sax.comment = commentSplit;
24495 if (old_sax->warning != NULL)
24496 ret->schemas_sax.warning = warningSplit;
24497 if (old_sax->error != NULL)
24498 ret->schemas_sax.error = errorSplit;
24499 if (old_sax->fatalError != NULL)
24500 ret->schemas_sax.fatalError = fatalErrorSplit;
24501 if (old_sax->getParameterEntity != NULL)
24502 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24503 if (old_sax->externalSubset != NULL)
24504 ret->schemas_sax.externalSubset = externalSubsetSplit;
24505
24506 /*
24507 * the 6 schemas callback have to go to the splitter functions
24508 * Note that we use the same text-function for ignorableWhitespace
24509 * if possible, to prevent the parser from testing for ignorable
24510 * whitespace.
24511 */
24512 ret->schemas_sax.characters = charactersSplit;
24513 if ((old_sax->ignorableWhitespace != NULL) &&
24514 (old_sax->ignorableWhitespace != old_sax->characters))
24515 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24516 else
24517 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24518 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24519 ret->schemas_sax.reference = referenceSplit;
24520 ret->schemas_sax.startElementNs = startElementNsSplit;
24521 ret->schemas_sax.endElementNs = endElementNsSplit;
24522
24523 ret->user_data_ptr = user_data;
24524 ret->user_data = *user_data;
24525 *user_data = ret;
24526 }
24527
24528 /*
24529 * plug the pointers back.
24530 */
24531 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024532 ctxt->sax = *sax;
24533 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24534 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024535 return(ret);
24536}
24537
24538/**
24539 * xmlSchemaSAXUnplug:
24540 * @plug: a data structure returned by xmlSchemaSAXPlug
24541 *
24542 * Unplug a SAX based validation layer in a SAX parsing event flow.
24543 * The original pointers used in the call are restored.
24544 *
24545 * Returns 0 in case of success and -1 in case of failure.
24546 */
24547int
24548xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24549{
24550 xmlSAXHandlerPtr *sax;
24551 void **user_data;
24552
24553 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24554 return(-1);
24555 plug->magic = 0;
24556
Daniel Veillardf10ae122005-07-10 19:03:16 +000024557 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024558 /* restore the data */
24559 sax = plug->user_sax_ptr;
24560 *sax = plug->user_sax;
24561 if (plug->user_sax != NULL) {
24562 user_data = plug->user_data_ptr;
24563 *user_data = plug->user_data;
24564 }
24565
24566 /* free and return */
24567 xmlFree(plug);
24568 return(0);
24569}
24570
24571/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024572 * xmlSchemaValidateStream:
24573 * @ctxt: a schema validation context
24574 * @input: the input to use for reading the data
24575 * @enc: an optional encoding information
24576 * @sax: a SAX handler for the resulting events
24577 * @user_data: the context to provide to the SAX handler.
24578 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024579 * Validate an input based on a flow of SAX event from the parser
24580 * and forward the events to the @sax handler with the provided @user_data
24581 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024582 *
24583 * Returns 0 if the document is schemas valid, a positive error code
24584 * number otherwise and -1 in case of internal or API error.
24585 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024586int
Daniel Veillard4255d502002-04-16 15:50:10 +000024587xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024588 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24589 xmlSAXHandlerPtr sax, void *user_data)
24590{
Daniel Veillard971771e2005-07-09 17:32:57 +000024591 xmlSchemaSAXPlugPtr plug = NULL;
24592 xmlSAXHandlerPtr old_sax = NULL;
24593 xmlParserCtxtPtr pctxt = NULL;
24594 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024595 int ret;
24596
Daniel Veillard4255d502002-04-16 15:50:10 +000024597 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024598 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024599
Daniel Veillardcdc82732005-07-08 15:04:06 +000024600 /*
24601 * prepare the parser
24602 */
24603 pctxt = xmlNewParserCtxt();
24604 if (pctxt == NULL)
24605 return (-1);
24606 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024607 pctxt->sax = sax;
24608 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024609#if 0
24610 if (options)
24611 xmlCtxtUseOptions(pctxt, options);
24612#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024613 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024614
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024615 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024616 if (inputStream == NULL) {
24617 ret = -1;
24618 goto done;
24619 }
24620 inputPush(pctxt, inputStream);
24621 ctxt->parserCtxt = pctxt;
24622 ctxt->input = input;
24623
24624 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024625 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024626 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024627 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24628 if (plug == NULL) {
24629 ret = -1;
24630 goto done;
24631 }
24632 ctxt->input = input;
24633 ctxt->enc = enc;
24634 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024635 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24636 ret = xmlSchemaVStart(ctxt);
24637
24638 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24639 ret = ctxt->parserCtxt->errNo;
24640 if (ret == 0)
24641 ret = 1;
24642 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024643
24644done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024645 ctxt->parserCtxt = NULL;
24646 ctxt->sax = NULL;
24647 ctxt->input = NULL;
24648 if (plug != NULL) {
24649 xmlSchemaSAXUnplug(plug);
24650 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024651 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024652 if (pctxt != NULL) {
24653 pctxt->sax = old_sax;
24654 xmlFreeParserCtxt(pctxt);
24655 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024656 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024657}
24658
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024659/**
24660 * xmlSchemaValidateFile:
24661 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024662 * @filename: the URI of the instance
24663 * @options: a future set of options, currently unused
24664 *
24665 * Do a schemas validation of the given resource, it will use the
24666 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024667 *
24668 * Returns 0 if the document is valid, a positive error code
24669 * number otherwise and -1 in case of an internal or API error.
24670 */
24671int
24672xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024673 const char * filename,
24674 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024675{
Daniel Veillard81562d22005-06-15 13:27:56 +000024676#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024677 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024678 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024679
24680 if ((ctxt == NULL) || (filename == NULL))
24681 return (-1);
24682
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024683 input = xmlParserInputBufferCreateFilename(filename,
24684 XML_CHAR_ENCODING_NONE);
24685 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024686 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024687 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24688 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024689 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024690#else
24691 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024692#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024693}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024694
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024695#define bottom_xmlschemas
24696#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024697#endif /* LIBXML_SCHEMAS_ENABLED */