blob: 3ee5563e57bb2109aa13ab8068c57a11c3cddfff [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000799 case XML_SCHEMA_TYPE_IDC_UNIQUE:
800 return(BAD_CAST "IDC (unique)");
801 case XML_SCHEMA_TYPE_IDC_KEY:
802 return(BAD_CAST "IDC (key)");
803 case XML_SCHEMA_TYPE_IDC_KEYREF:
804 return(BAD_CAST "IDC (keyref)");
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +0000805 case XML_SCHEMA_TYPE_ANY:
806 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000807 case XML_SCHEMA_EXTRA_QNAMEREF:
808 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000809 default:
810 return(BAD_CAST "Not a schema component");
811 }
812}
813
814/**
815 * xmlSchemaGetComponentNode:
816 * @item: a schema component
817 *
818 * Returns node associated with the schema component.
819 * NOTE that such a node need not be available; plus, a component's
820 * node need not to reflect the component directly, since there is no
821 * one-to-one relationship between the XML Schema representation and
822 * the component representation.
823 */
824static xmlNodePtr
825xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
826{
827 switch (item->type) {
828 case XML_SCHEMA_TYPE_ELEMENT:
829 return (((xmlSchemaElementPtr) item)->node);
830 case XML_SCHEMA_TYPE_ATTRIBUTE:
831 return (((xmlSchemaAttributePtr) item)->node);
832 case XML_SCHEMA_TYPE_COMPLEX:
833 case XML_SCHEMA_TYPE_SIMPLE:
834 return (((xmlSchemaTypePtr) item)->node);
835 case XML_SCHEMA_TYPE_ANY:
836 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
837 return (((xmlSchemaWildcardPtr) item)->node);
838 case XML_SCHEMA_TYPE_PARTICLE:
839 return (((xmlSchemaParticlePtr) item)->node);
840 case XML_SCHEMA_TYPE_SEQUENCE:
841 case XML_SCHEMA_TYPE_CHOICE:
842 case XML_SCHEMA_TYPE_ALL:
843 return (((xmlSchemaModelGroupPtr) item)->node);
844 case XML_SCHEMA_TYPE_GROUP:
845 return (((xmlSchemaModelGroupDefPtr) item)->node);
846 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
847 return (((xmlSchemaAttributeGroupPtr) item)->node);
848 case XML_SCHEMA_TYPE_IDC_UNIQUE:
849 case XML_SCHEMA_TYPE_IDC_KEY:
850 case XML_SCHEMA_TYPE_IDC_KEYREF:
851 return (((xmlSchemaIDCPtr) item)->node);
852 default:
853 return (NULL);
854 }
855}
856
857#if 0
858/**
859 * xmlSchemaGetNextComponent:
860 * @item: a schema component
861 *
862 * Returns the next sibling of the schema component.
863 */
864static xmlSchemaBasicItemPtr
865xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
866{
867 switch (item->type) {
868 case XML_SCHEMA_TYPE_ELEMENT:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
870 case XML_SCHEMA_TYPE_ATTRIBUTE:
871 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
872 case XML_SCHEMA_TYPE_COMPLEX:
873 case XML_SCHEMA_TYPE_SIMPLE:
874 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
875 case XML_SCHEMA_TYPE_ANY:
876 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
877 return (NULL);
878 case XML_SCHEMA_TYPE_PARTICLE:
879 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
880 case XML_SCHEMA_TYPE_SEQUENCE:
881 case XML_SCHEMA_TYPE_CHOICE:
882 case XML_SCHEMA_TYPE_ALL:
883 return (NULL);
884 case XML_SCHEMA_TYPE_GROUP:
885 return (NULL);
886 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
887 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
888 case XML_SCHEMA_TYPE_IDC_UNIQUE:
889 case XML_SCHEMA_TYPE_IDC_KEY:
890 case XML_SCHEMA_TYPE_IDC_KEYREF:
891 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
892 default:
893 return (NULL);
894 }
895}
896#endif
897
898/**
899 * xmlSchemaGetAttrName:
900 * @attr: the attribute declaration/use
901 *
902 * Returns the name of the attribute; if the attribute
903 * is a reference, the name of the referenced global type will be returned.
904 */
905static const xmlChar *
906xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
907{
908 if (attr->ref != NULL)
909 return(attr->ref);
910 else
911 return(attr->name);
912}
913
914/**
915 * xmlSchemaGetAttrTargetNsURI:
916 * @type: the type (element or attribute)
917 *
918 * Returns the target namespace URI of the type; if the type is a reference,
919 * the target namespace of the referenced type will be returned.
920 */
921static const xmlChar *
922xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
923{
924 if (attr->ref != NULL)
925 return (attr->refNs);
926 else
927 return(attr->targetNamespace);
928}
929
930/**
931 * xmlSchemaFormatQName:
932 * @buf: the string buffer
933 * @namespaceName: the namespace name
934 * @localName: the local name
935 *
936 * Returns the given QName in the format "{namespaceName}localName" or
937 * just "localName" if @namespaceName is NULL.
938 *
939 * Returns the localName if @namespaceName is NULL, a formatted
940 * string otherwise.
941 */
942static const xmlChar*
943xmlSchemaFormatQName(xmlChar **buf,
944 const xmlChar *namespaceName,
945 const xmlChar *localName)
946{
947 FREE_AND_NULL(*buf)
948 if (namespaceName == NULL)
949 return(localName);
950
951 *buf = xmlStrdup(BAD_CAST "{");
952 *buf = xmlStrcat(*buf, namespaceName);
953 *buf = xmlStrcat(*buf, BAD_CAST "}");
954 *buf = xmlStrcat(*buf, localName);
955
956 return ((const xmlChar *) *buf);
957}
958
959static const xmlChar*
960xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
961{
962 if (ns != NULL)
963 return (xmlSchemaFormatQName(buf, ns->href, localName));
964 else
965 return (xmlSchemaFormatQName(buf, NULL, localName));
966}
967
968static const xmlChar *
969xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
970{
971 switch (item->type) {
972 case XML_SCHEMA_TYPE_ELEMENT:
973 return (((xmlSchemaElementPtr) item)->name);
974 case XML_SCHEMA_TYPE_ATTRIBUTE:
975 return (((xmlSchemaAttributePtr) item)->name);
976 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
977 return (((xmlSchemaAttributeGroupPtr) item)->name);
978 case XML_SCHEMA_TYPE_BASIC:
979 case XML_SCHEMA_TYPE_SIMPLE:
980 case XML_SCHEMA_TYPE_COMPLEX:
981 return (((xmlSchemaTypePtr) item)->name);
982 case XML_SCHEMA_TYPE_GROUP:
983 return (((xmlSchemaModelGroupDefPtr) item)->name);
984 case XML_SCHEMA_TYPE_IDC_KEY:
985 case XML_SCHEMA_TYPE_IDC_UNIQUE:
986 case XML_SCHEMA_TYPE_IDC_KEYREF:
987 return (((xmlSchemaIDCPtr) item)->name);
988 default:
989 /*
990 * Other components cannot have names.
991 */
992 break;
993 }
994 return (NULL);
995}
996
997static const xmlChar *
998xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
999{
1000 switch (item->type) {
1001 case XML_SCHEMA_TYPE_ELEMENT:
1002 return (((xmlSchemaElementPtr) item)->targetNamespace);
1003 case XML_SCHEMA_TYPE_ATTRIBUTE:
1004 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1005 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1006 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1007 case XML_SCHEMA_TYPE_BASIC:
1008 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1009 case XML_SCHEMA_TYPE_SIMPLE:
1010 case XML_SCHEMA_TYPE_COMPLEX:
1011 return (((xmlSchemaTypePtr) item)->targetNamespace);
1012 case XML_SCHEMA_TYPE_GROUP:
1013 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1014 case XML_SCHEMA_TYPE_IDC_KEY:
1015 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1016 case XML_SCHEMA_TYPE_IDC_KEYREF:
1017 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1018 default:
1019 /*
1020 * Other components cannot have names.
1021 */
1022 break;
1023 }
1024 return (NULL);
1025}
1026
1027static const xmlChar*
1028xmlSchemaGetComponentQName(xmlChar **buf,
1029 void *item)
1030{
1031 return (xmlSchemaFormatQName(buf,
1032 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1033 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1034}
1035
1036/**
1037 * xmlSchemaWildcardPCToString:
1038 * @pc: the type of processContents
1039 *
1040 * Returns a string representation of the type of
1041 * processContents.
1042 */
1043static const xmlChar *
1044xmlSchemaWildcardPCToString(int pc)
1045{
1046 switch (pc) {
1047 case XML_SCHEMAS_ANY_SKIP:
1048 return (BAD_CAST "skip");
1049 case XML_SCHEMAS_ANY_LAX:
1050 return (BAD_CAST "lax");
1051 case XML_SCHEMAS_ANY_STRICT:
1052 return (BAD_CAST "strict");
1053 default:
1054 return (BAD_CAST "invalid process contents");
1055 }
1056}
1057
1058/**
1059 * xmlSchemaGetCanonValueWhtspExt:
1060 * @val: the precomputed value
1061 * @retValue: the returned value
1062 * @ws: the whitespace type of the value
1063 *
1064 * Get a the cononical representation of the value.
1065 * The caller has to free the returned retValue.
1066 *
1067 * Returns 0 if the value could be built and -1 in case of
1068 * API errors or if the value type is not supported yet.
1069 */
1070static int
1071xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1072 xmlSchemaWhitespaceValueType ws,
1073 xmlChar **retValue)
1074{
1075 int list;
1076 xmlSchemaValType valType;
1077 const xmlChar *value, *value2 = NULL;
1078
1079
1080 if ((retValue == NULL) || (val == NULL))
1081 return (-1);
1082 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1083 *retValue = NULL;
1084 do {
1085 value = NULL;
1086 valType = xmlSchemaGetValType(val);
1087 switch (valType) {
1088 case XML_SCHEMAS_STRING:
1089 case XML_SCHEMAS_NORMSTRING:
1090 case XML_SCHEMAS_ANYSIMPLETYPE:
1091 value = xmlSchemaValueGetAsString(val);
1092 if (value != NULL) {
1093 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1094 value2 = xmlSchemaCollapseString(value);
1095 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1096 value2 = xmlSchemaWhiteSpaceReplace(value);
1097 if (value2 != NULL)
1098 value = value2;
1099 }
1100 break;
1101 default:
1102 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1103 if (value2 != NULL)
1104 xmlFree((xmlChar *) value2);
1105 goto internal_error;
1106 }
1107 value = value2;
1108 }
1109 if (*retValue == NULL)
1110 if (value == NULL) {
1111 if (! list)
1112 *retValue = xmlStrdup(BAD_CAST "");
1113 } else
1114 *retValue = xmlStrdup(value);
1115 else if (value != NULL) {
1116 /* List. */
1117 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1118 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1119 }
1120 FREE_AND_NULL(value2)
1121 val = xmlSchemaValueGetNext(val);
1122 } while (val != NULL);
1123
1124 return (0);
1125internal_error:
1126 if (*retValue != NULL)
1127 xmlFree((xmlChar *) (*retValue));
1128 if (value2 != NULL)
1129 xmlFree((xmlChar *) value2);
1130 return (-1);
1131}
1132
1133/**
1134 * xmlSchemaFormatItemForReport:
1135 * @buf: the string buffer
1136 * @itemDes: the designation of the item
1137 * @itemName: the name of the item
1138 * @item: the item as an object
1139 * @itemNode: the node of the item
1140 * @local: the local name
1141 * @parsing: if the function is used during the parse
1142 *
1143 * Returns a representation of the given item used
1144 * for error reports.
1145 *
1146 * The following order is used to build the resulting
1147 * designation if the arguments are not NULL:
1148 * 1a. If itemDes not NULL -> itemDes
1149 * 1b. If (itemDes not NULL) and (itemName not NULL)
1150 * -> itemDes + itemName
1151 * 2. If the preceding was NULL and (item not NULL) -> item
1152 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1153 *
1154 * If the itemNode is an attribute node, the name of the attribute
1155 * will be appended to the result.
1156 *
1157 * Returns the formatted string and sets @buf to the resulting value.
1158 */
1159static xmlChar*
1160xmlSchemaFormatItemForReport(xmlChar **buf,
1161 const xmlChar *itemDes,
1162 xmlSchemaTypePtr item,
1163 xmlNodePtr itemNode)
1164{
1165 xmlChar *str = NULL;
1166 int named = 1;
1167
1168 if (*buf != NULL) {
1169 xmlFree(*buf);
1170 *buf = NULL;
1171 }
1172
1173 if (itemDes != NULL) {
1174 *buf = xmlStrdup(itemDes);
1175 } else if (item != NULL) {
1176 switch (item->type) {
1177 case XML_SCHEMA_TYPE_BASIC:
1178 if (VARIETY_ATOMIC(item))
1179 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1180 else if (VARIETY_LIST(item))
1181 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1182 else if (VARIETY_UNION(item))
1183 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1184 else
1185 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1186 *buf = xmlStrcat(*buf, item->name);
1187 *buf = xmlStrcat(*buf, BAD_CAST "'");
1188 break;
1189 case XML_SCHEMA_TYPE_SIMPLE:
1190 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1191 *buf = xmlStrdup(BAD_CAST"");
1192 } else {
1193 *buf = xmlStrdup(BAD_CAST "local ");
1194 }
1195 if (VARIETY_ATOMIC(item))
1196 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1197 else if (VARIETY_LIST(item))
1198 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1199 else if (VARIETY_UNION(item))
1200 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1201 else
1202 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1203 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1204 *buf = xmlStrcat(*buf, BAD_CAST " '");
1205 *buf = xmlStrcat(*buf, item->name);
1206 *buf = xmlStrcat(*buf, BAD_CAST "'");
1207 }
1208 break;
1209 case XML_SCHEMA_TYPE_COMPLEX:
1210 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1211 *buf = xmlStrdup(BAD_CAST "");
1212 else
1213 *buf = xmlStrdup(BAD_CAST "local ");
1214 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1215 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1216 *buf = xmlStrcat(*buf, BAD_CAST " '");
1217 *buf = xmlStrcat(*buf, item->name);
1218 *buf = xmlStrcat(*buf, BAD_CAST "'");
1219 }
1220 break;
1221 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1222 xmlSchemaAttributePtr attr;
1223
1224 attr = (xmlSchemaAttributePtr) item;
1225 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1226 (attr->ref == NULL)) {
1227 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1228 *buf = xmlStrcat(*buf, BAD_CAST " '");
1229 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1230 attr->targetNamespace, attr->name));
1231 FREE_AND_NULL(str)
1232 *buf = xmlStrcat(*buf, BAD_CAST "'");
1233 } else {
1234 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1235 *buf = xmlStrcat(*buf, BAD_CAST " '");
1236 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1237 attr->refNs, attr->ref));
1238 FREE_AND_NULL(str)
1239 *buf = xmlStrcat(*buf, BAD_CAST "'");
1240 }
1241 }
1242 break;
1243 case XML_SCHEMA_TYPE_ELEMENT: {
1244 xmlSchemaElementPtr elem;
1245
1246 elem = (xmlSchemaElementPtr) item;
1247 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1248 (elem->ref == NULL)) {
1249 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1250 *buf = xmlStrcat(*buf, BAD_CAST " '");
1251 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1252 elem->targetNamespace, elem->name));
1253 *buf = xmlStrcat(*buf, BAD_CAST "'");
1254 }
1255 }
1256 break;
1257 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1258 case XML_SCHEMA_TYPE_IDC_KEY:
1259 case XML_SCHEMA_TYPE_IDC_KEYREF:
1260 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1261 *buf = xmlStrdup(BAD_CAST "unique '");
1262 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1263 *buf = xmlStrdup(BAD_CAST "key '");
1264 else
1265 *buf = xmlStrdup(BAD_CAST "keyRef '");
1266 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1267 *buf = xmlStrcat(*buf, BAD_CAST "'");
1268 break;
1269 case XML_SCHEMA_TYPE_ANY:
1270 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1271 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1272 ((xmlSchemaWildcardPtr) item)->processContents));
1273 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1274 break;
1275 case XML_SCHEMA_FACET_MININCLUSIVE:
1276 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1277 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1278 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1279 case XML_SCHEMA_FACET_TOTALDIGITS:
1280 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1281 case XML_SCHEMA_FACET_PATTERN:
1282 case XML_SCHEMA_FACET_ENUMERATION:
1283 case XML_SCHEMA_FACET_WHITESPACE:
1284 case XML_SCHEMA_FACET_LENGTH:
1285 case XML_SCHEMA_FACET_MAXLENGTH:
1286 case XML_SCHEMA_FACET_MINLENGTH:
1287 *buf = xmlStrdup(BAD_CAST "facet '");
1288 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1289 *buf = xmlStrcat(*buf, BAD_CAST "'");
1290 break;
1291 case XML_SCHEMA_TYPE_NOTATION:
1292 *buf = xmlStrdup(BAD_CAST "notation");
1293 break;
1294 case XML_SCHEMA_TYPE_GROUP: {
1295 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1296 *buf = xmlStrcat(*buf, BAD_CAST " '");
1297 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1298 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1299 ((xmlSchemaModelGroupDefPtr) item)->name));
1300 *buf = xmlStrcat(*buf, BAD_CAST "'");
1301 FREE_AND_NULL(str)
1302 }
1303 break;
1304 case XML_SCHEMA_TYPE_SEQUENCE:
1305 case XML_SCHEMA_TYPE_CHOICE:
1306 case XML_SCHEMA_TYPE_ALL:
1307 case XML_SCHEMA_TYPE_PARTICLE:
1308 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1309 break;
1310 default:
1311 named = 0;
1312 }
1313 } else
1314 named = 0;
1315
1316 if ((named == 0) && (itemNode != NULL)) {
1317 xmlNodePtr elem;
1318
1319 if (itemNode->type == XML_ATTRIBUTE_NODE)
1320 elem = itemNode->parent;
1321 else
1322 elem = itemNode;
1323 *buf = xmlStrdup(BAD_CAST "Element '");
1324 if (elem->ns != NULL) {
1325 *buf = xmlStrcat(*buf,
1326 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1327 FREE_AND_NULL(str)
1328 } else
1329 *buf = xmlStrcat(*buf, elem->name);
1330 *buf = xmlStrcat(*buf, BAD_CAST "'");
1331
1332 }
1333 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1334 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1335 if (itemNode->ns != NULL) {
1336 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1337 itemNode->ns->href, itemNode->name));
1338 FREE_AND_NULL(str)
1339 } else
1340 *buf = xmlStrcat(*buf, itemNode->name);
1341 *buf = xmlStrcat(*buf, BAD_CAST "'");
1342 }
1343 FREE_AND_NULL(str)
1344
1345 return (*buf);
1346}
1347
1348/**
1349 * xmlSchemaFormatFacetEnumSet:
1350 * @buf: the string buffer
1351 * @type: the type holding the enumeration facets
1352 *
1353 * Builds a string consisting of all enumeration elements.
1354 *
1355 * Returns a string of all enumeration elements.
1356 */
1357static const xmlChar *
1358xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1359 xmlChar **buf, xmlSchemaTypePtr type)
1360{
1361 xmlSchemaFacetPtr facet;
1362 xmlSchemaWhitespaceValueType ws;
1363 xmlChar *value = NULL;
1364 int res;
1365
1366 if (*buf != NULL)
1367 xmlFree(*buf);
1368 *buf = NULL;
1369
1370 do {
1371 /*
1372 * Use the whitespace type of the base type.
1373 */
1374 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1375 for (facet = type->facets; facet != NULL; facet = facet->next) {
1376 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1377 continue;
1378 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1379 ws, &value);
1380 if (res == -1) {
1381 xmlSchemaInternalErr(actxt,
1382 "xmlSchemaFormatFacetEnumSet",
1383 "compute the canonical lexical representation");
1384 if (*buf != NULL)
1385 xmlFree(*buf);
1386 *buf = NULL;
1387 return (NULL);
1388 }
1389 if (*buf == NULL)
1390 *buf = xmlStrdup(BAD_CAST "'");
1391 else
1392 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1393 *buf = xmlStrcat(*buf, BAD_CAST value);
1394 *buf = xmlStrcat(*buf, BAD_CAST "'");
1395 if (value != NULL) {
1396 xmlFree((xmlChar *)value);
1397 value = NULL;
1398 }
1399 }
1400 type = type->baseType;
1401 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1402
1403 return ((const xmlChar *) *buf);
1404}
1405
1406/************************************************************************
1407 * *
1408 * Error functions *
1409 * *
1410 ************************************************************************/
1411
1412#if 0
1413static void
1414xmlSchemaErrMemory(const char *msg)
1415{
1416 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1417 msg);
1418}
1419#endif
1420
1421/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001422 * xmlSchemaPErrMemory:
1423 * @node: a context node
1424 * @extra: extra informations
1425 *
1426 * Handle an out of memory condition
1427 */
1428static void
1429xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1430 const char *extra, xmlNodePtr node)
1431{
1432 if (ctxt != NULL)
1433 ctxt->nberrors++;
1434 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1435 extra);
1436}
1437
1438/**
1439 * xmlSchemaPErr:
1440 * @ctxt: the parsing context
1441 * @node: the context node
1442 * @error: the error code
1443 * @msg: the error message
1444 * @str1: extra data
1445 * @str2: extra data
1446 *
1447 * Handle a parser error
1448 */
1449static void
1450xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1451 const char *msg, const xmlChar * str1, const xmlChar * str2)
1452{
1453 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001454 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001455 void *data = NULL;
1456
1457 if (ctxt != NULL) {
1458 ctxt->nberrors++;
1459 channel = ctxt->error;
1460 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001461 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001462 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001463 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001464 error, XML_ERR_ERROR, NULL, 0,
1465 (const char *) str1, (const char *) str2, NULL, 0, 0,
1466 msg, str1, str2);
1467}
1468
1469/**
1470 * xmlSchemaPErr2:
1471 * @ctxt: the parsing context
1472 * @node: the context node
1473 * @node: the current child
1474 * @error: the error code
1475 * @msg: the error message
1476 * @str1: extra data
1477 * @str2: extra data
1478 *
1479 * Handle a parser error
1480 */
1481static void
1482xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1483 xmlNodePtr child, int error,
1484 const char *msg, const xmlChar * str1, const xmlChar * str2)
1485{
1486 if (child != NULL)
1487 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1488 else
1489 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1490}
1491
Daniel Veillard01fa6152004-06-29 17:04:39 +00001492
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001493/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001494 * xmlSchemaPErrExt:
1495 * @ctxt: the parsing context
1496 * @node: the context node
1497 * @error: the error code
1498 * @strData1: extra data
1499 * @strData2: extra data
1500 * @strData3: extra data
1501 * @msg: the message
1502 * @str1: extra parameter for the message display
1503 * @str2: extra parameter for the message display
1504 * @str3: extra parameter for the message display
1505 * @str4: extra parameter for the message display
1506 * @str5: extra parameter for the message display
1507 *
1508 * Handle a parser error
1509 */
1510static void
1511xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1512 const xmlChar * strData1, const xmlChar * strData2,
1513 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1514 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1515 const xmlChar * str5)
1516{
1517
1518 xmlGenericErrorFunc channel = NULL;
1519 xmlStructuredErrorFunc schannel = NULL;
1520 void *data = NULL;
1521
1522 if (ctxt != NULL) {
1523 ctxt->nberrors++;
1524 channel = ctxt->error;
1525 data = ctxt->userData;
1526 schannel = ctxt->serror;
1527 }
1528 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1529 error, XML_ERR_ERROR, NULL, 0,
1530 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001531 (const char *) strData3, 0, 0, msg, str1, str2,
1532 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001533}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001534
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001535/************************************************************************
1536 * *
1537 * Allround error functions *
1538 * *
1539 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001540
1541/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 * xmlSchemaVTypeErrMemory:
1543 * @node: a context node
1544 * @extra: extra informations
1545 *
1546 * Handle an out of memory condition
1547 */
1548static void
1549xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1550 const char *extra, xmlNodePtr node)
1551{
1552 if (ctxt != NULL) {
1553 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001554 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001555 }
1556 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1557 extra);
1558}
1559
1560/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001561 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562 * @ctxt: the validation context
1563 * @node: the context node
1564 * @error: the error code
1565 * @msg: the error message
1566 * @str1: extra data
1567 * @str2: extra data
1568 * @str3: extra data
1569 *
1570 * Handle a validation error
1571 */
1572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001573xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1574 int error, xmlNodePtr node, const char *msg,
1575 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001577 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 xmlGenericErrorFunc channel = NULL;
1579 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001580
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 if (ctxt != NULL) {
1582 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1583 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001584 int line = 0;
1585 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001586
1587 vctxt->nberrors++;
1588 vctxt->err = error;
1589 channel = vctxt->error;
1590 schannel = vctxt->serror;
1591 data = vctxt->userData;
1592 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001595 }
1596 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1597 (vctxt->parserCtxt->input != NULL)) {
1598 file = vctxt->parserCtxt->input->filename;
1599 line = vctxt->parserCtxt->input->line;
1600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 __xmlRaiseError(schannel, channel, data, ctxt,
1602 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001603 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001604 (const char *) str1, (const char *) str2,
1605 (const char *) str3, 0, 0, msg, str1, str2, str3);
1606
1607 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1608 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1609
1610 pctxt->nberrors++;
1611 pctxt->err = error;
1612 channel = pctxt->error;
1613 schannel = pctxt->serror;
1614 data = pctxt->userData;
1615 __xmlRaiseError(schannel, channel, data, ctxt,
1616 node, XML_FROM_SCHEMASP,
1617 error, XML_ERR_ERROR, NULL, 0,
1618 (const char *) str1, (const char *) str2,
1619 (const char *) str3, 0, 0, msg, str1, str2, str3);
1620 } else {
1621 TODO
1622 }
1623 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001624}
1625
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001626static void
1627xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1628 int error, xmlNodePtr node, const char *msg,
1629 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001630{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001632}
1633
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001634static xmlChar *
1635xmlSchemaFormatNodeForError(xmlChar ** msg,
1636 xmlSchemaAbstractCtxtPtr actxt,
1637 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001638{
1639 xmlChar *str = NULL;
1640
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001641 if (node != NULL) {
1642 /*
1643 * Work on tree nodes.
1644 */
1645 if (node->type == XML_ATTRIBUTE_NODE) {
1646 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001648 *msg = xmlStrdup(BAD_CAST "Element '");
1649 if (elem->ns != NULL)
1650 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1651 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001652 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001653 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1654 NULL, elem->name));
1655 FREE_AND_NULL(str);
1656 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1657 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1658 } else {
1659 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001660 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001661 if (node->ns != NULL)
1662 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1663 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001664 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001665 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1666 NULL, node->name));
1667 FREE_AND_NULL(str);
1668 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1669 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1670 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1671 /*
1672 * Work on node infos.
1673 */
1674 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1675 xmlSchemaNodeInfoPtr ielem =
1676 vctxt->elemInfos[vctxt->depth];
1677
1678 *msg = xmlStrdup(BAD_CAST "Element '");
1679 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1680 ielem->nsName, ielem->localName));
1681 FREE_AND_NULL(str);
1682 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1683 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1684 } else {
1685 *msg = xmlStrdup(BAD_CAST "Element '");
1686 }
1687 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1688 vctxt->inode->nsName, vctxt->inode->localName));
1689 FREE_AND_NULL(str);
1690 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1691 } else {
1692 TODO
1693 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001694 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001695 /*
1696 * VAL TODO: The output of the given schema component is currently
1697 * disabled.
1698 */
1699#if 0
1700 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1701 *msg = xmlStrcat(*msg, BAD_CAST " [");
1702 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1703 NULL, type, NULL, 0));
1704 FREE_AND_NULL(str)
1705 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001706 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001707#endif
1708 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001709}
1710
Daniel Veillardc0826a72004-08-10 14:17:33 +00001711static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001712xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001713 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001714 const char *message,
1715 const xmlChar *str1,
1716 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001717{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001718 xmlChar *msg = NULL;
1719
1720 msg = xmlStrdup(BAD_CAST "Internal error: ");
1721 msg = xmlStrcat(msg, BAD_CAST funcName);
1722 msg = xmlStrcat(msg, BAD_CAST ", ");
1723 msg = xmlStrcat(msg, BAD_CAST message);
1724 msg = xmlStrcat(msg, BAD_CAST ".\n");
1725
1726 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1727 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001728 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001729
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001730 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001731 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001732 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001733
1734 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001735}
1736
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001737static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001738xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1739 const char *funcName,
1740 const char *message)
1741{
1742 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
1743}
1744
1745static void
1746xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
1747 const char *funcName,
1748 const char *message,
1749 const xmlChar *str1,
1750 const xmlChar *str2)
1751{
1752 xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message,
1753 str1, str2);
1754}
1755
1756static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001757xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1758 xmlParserErrors error,
1759 xmlNodePtr node,
1760 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1761 const char *message,
1762 const xmlChar *str1,
1763 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001766
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001767 xmlSchemaFormatNodeForError(&msg, actxt, node);
1768 msg = xmlStrcat(msg, (const xmlChar *) message);
1769 msg = xmlStrcat(msg, BAD_CAST ".\n");
1770 xmlSchemaErr(actxt, error, node,
1771 (const char *) msg, str1, str2);
1772 FREE_AND_NULL(msg)
1773}
1774
1775static int
1776xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1777 xmlNodePtr node)
1778{
1779 if (node != NULL)
1780 return (node->type);
1781 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1782 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1783 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1784 return (-1);
1785}
1786
1787static int
1788xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1789{
1790 switch (item->type) {
1791 case XML_SCHEMA_TYPE_COMPLEX:
1792 case XML_SCHEMA_TYPE_SIMPLE:
1793 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1794 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001795 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001796 case XML_SCHEMA_TYPE_GROUP:
1797 return (1);
1798 case XML_SCHEMA_TYPE_ELEMENT:
1799 if ( ((xmlSchemaElementPtr) item)->flags &
1800 XML_SCHEMAS_ELEM_GLOBAL)
1801 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001802 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001803 case XML_SCHEMA_TYPE_ATTRIBUTE:
1804 if ( ((xmlSchemaAttributePtr) item)->flags &
1805 XML_SCHEMAS_ATTR_GLOBAL)
1806 return(1);
1807 break;
1808 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001809 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001810 return(1);
1811 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001812 return (0);
1813}
1814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001815static void
1816xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1817 xmlParserErrors error,
1818 xmlNodePtr node,
1819 const xmlChar *value,
1820 xmlSchemaTypePtr type,
1821 int displayValue)
1822{
1823 xmlChar *msg = NULL;
1824
1825 xmlSchemaFormatNodeForError(&msg, actxt, node);
1826
1827 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1828 XML_ATTRIBUTE_NODE))
1829 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1830 else
1831 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1832 "value of ");
1833
1834 if (! xmlSchemaIsGlobalItem(type))
1835 msg = xmlStrcat(msg, BAD_CAST "the local ");
1836 else
1837 msg = xmlStrcat(msg, BAD_CAST "the ");
1838
1839 if (VARIETY_ATOMIC(type))
1840 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1841 else if (VARIETY_LIST(type))
1842 msg = xmlStrcat(msg, BAD_CAST "list type");
1843 else if (VARIETY_UNION(type))
1844 msg = xmlStrcat(msg, BAD_CAST "union type");
1845
1846 if (xmlSchemaIsGlobalItem(type)) {
1847 xmlChar *str = NULL;
1848 msg = xmlStrcat(msg, BAD_CAST " '");
1849 if (type->builtInType != 0) {
1850 msg = xmlStrcat(msg, BAD_CAST "xs:");
1851 msg = xmlStrcat(msg, type->name);
1852 } else
1853 msg = xmlStrcat(msg,
1854 xmlSchemaFormatQName(&str,
1855 type->targetNamespace, type->name));
1856 msg = xmlStrcat(msg, BAD_CAST "'");
1857 FREE_AND_NULL(str);
1858 }
1859 msg = xmlStrcat(msg, BAD_CAST ".\n");
1860 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1861 XML_ATTRIBUTE_NODE))
1862 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1863 else
1864 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1865 FREE_AND_NULL(msg)
1866}
1867
Daniel Veillardc0826a72004-08-10 14:17:33 +00001868static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001869xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1870 xmlSchemaNodeInfoPtr ni,
1871 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001872{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001873 if (node != NULL) {
1874 if (node->ns != NULL)
1875 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1876 else
1877 return (xmlSchemaFormatQName(str, NULL, node->name));
1878 } else if (ni != NULL)
1879 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1880 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001881}
1882
Daniel Veillardc0826a72004-08-10 14:17:33 +00001883static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1885 xmlParserErrors error,
1886 xmlSchemaAttrInfoPtr ni,
1887 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001888{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001889 xmlChar *msg = NULL, *str = NULL;
1890
1891 xmlSchemaFormatNodeForError(&msg, actxt, node);
1892 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1893 xmlSchemaErr(actxt, error, node, (const char *) msg,
1894 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1895 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001896 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001897 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001898}
1899
Daniel Veillardc0826a72004-08-10 14:17:33 +00001900static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001901xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1902 xmlParserErrors error,
1903 xmlNodePtr node,
1904 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001905 const char *message,
1906 int nbval,
1907 int nbneg,
1908 xmlChar **values)
1909{
1910 xmlChar *str = NULL, *msg = NULL;
1911 xmlChar *localName, *nsName;
1912 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00001913 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001915 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001916 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001917 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001918 /*
1919 * Note that is does not make sense to report that we have a
1920 * wildcard here, since the wildcard might be unfolded into
1921 * multiple transitions.
1922 */
1923 if (nbval + nbneg > 0) {
1924 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001925 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001926 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001927 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001928 nsName = NULL;
1929
1930 for (i = 0; i < nbval + nbneg; i++) {
1931 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00001932 if (cur == NULL)
1933 continue;
1934 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
1935 (cur[3] == ' ')) {
1936 is_not = 1;
1937 cur += 4;
1938 str = xmlStrcat(str, BAD_CAST "not ");
1939 } else {
1940 is_not = 0;
1941 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001942 /*
1943 * Get the local name.
1944 */
1945 localName = NULL;
1946
1947 end = cur;
1948 if (*end == '*') {
1949 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001950 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001951 } else {
1952 while ((*end != 0) && (*end != '|'))
1953 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001954 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001955 }
1956 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001957 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001958 /*
1959 * Skip "*|*" if they come with negated expressions, since
1960 * they represent the same negated wildcard.
1961 */
1962 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1963 /*
1964 * Get the namespace name.
1965 */
1966 cur = end;
1967 if (*end == '*') {
1968 nsName = xmlStrdup(BAD_CAST "{*}");
1969 } else {
1970 while (*end != 0)
1971 end++;
1972
1973 if (i >= nbval)
1974 nsName = xmlStrdup(BAD_CAST "{##other:");
1975 else
1976 nsName = xmlStrdup(BAD_CAST "{");
1977
1978 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1979 nsName = xmlStrcat(nsName, BAD_CAST "}");
1980 }
1981 str = xmlStrcat(str, BAD_CAST nsName);
1982 FREE_AND_NULL(nsName)
1983 } else {
1984 FREE_AND_NULL(localName);
1985 continue;
1986 }
1987 }
1988 str = xmlStrcat(str, BAD_CAST localName);
1989 FREE_AND_NULL(localName);
1990
1991 if (i < nbval + nbneg -1)
1992 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001993 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001994 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001995 msg = xmlStrcat(msg, BAD_CAST str);
1996 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001997 } else
1998 msg = xmlStrcat(msg, BAD_CAST "\n");
1999 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002000 xmlFree(msg);
2001}
2002
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002003static void
2004xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2005 xmlParserErrors error,
2006 xmlNodePtr node,
2007 const xmlChar *value,
2008 unsigned long length,
2009 xmlSchemaTypePtr type,
2010 xmlSchemaFacetPtr facet,
2011 const char *message,
2012 const xmlChar *str1,
2013 const xmlChar *str2)
2014{
2015 xmlChar *str = NULL, *msg = NULL;
2016 xmlSchemaTypeType facetType;
2017 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2018
2019 xmlSchemaFormatNodeForError(&msg, actxt, node);
2020 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2021 facetType = XML_SCHEMA_FACET_ENUMERATION;
2022 /*
2023 * If enumerations are validated, one must not expect the
2024 * facet to be given.
2025 */
2026 } else
2027 facetType = facet->type;
2028 msg = xmlStrcat(msg, BAD_CAST "[");
2029 msg = xmlStrcat(msg, BAD_CAST "facet '");
2030 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2031 msg = xmlStrcat(msg, BAD_CAST "'] ");
2032 if (message == NULL) {
2033 /*
2034 * Use a default message.
2035 */
2036 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2037 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2038 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2039
2040 char len[25], actLen[25];
2041
2042 /* FIXME, TODO: What is the max expected string length of the
2043 * this value?
2044 */
2045 if (nodeType == XML_ATTRIBUTE_NODE)
2046 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2047 else
2048 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2049
2050 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2051 snprintf(actLen, 24, "%lu", length);
2052
2053 if (facetType == XML_SCHEMA_FACET_LENGTH)
2054 msg = xmlStrcat(msg,
2055 BAD_CAST "this differs from the allowed length of '%s'.\n");
2056 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2057 msg = xmlStrcat(msg,
2058 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2059 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2060 msg = xmlStrcat(msg,
2061 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2062
2063 if (nodeType == XML_ATTRIBUTE_NODE)
2064 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2065 value, (const xmlChar *) actLen, (const xmlChar *) len);
2066 else
2067 xmlSchemaErr(actxt, error, node, (const char *) msg,
2068 (const xmlChar *) actLen, (const xmlChar *) len);
2069
2070 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2071 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2072 "of the set {%s}.\n");
2073 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2074 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2075 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2076 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2077 "by the pattern '%s'.\n");
2078 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2079 facet->value);
2080 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2081 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2082 "minimum value allowed ('%s').\n");
2083 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2084 facet->value);
2085 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2086 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2087 "maximum value allowed ('%s').\n");
2088 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2089 facet->value);
2090 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2091 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2092 "'%s'.\n");
2093 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2094 facet->value);
2095 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2096 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2097 "'%s'.\n");
2098 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2099 facet->value);
2100 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2101 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2102 "digits than are allowed ('%s').\n");
2103 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2104 facet->value);
2105 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2106 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2107 "digits than are allowed ('%s').\n");
2108 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2109 facet->value);
2110 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2111 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2112 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2113 } else {
2114 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2115 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2116 }
2117 } else {
2118 msg = xmlStrcat(msg, (const xmlChar *) message);
2119 msg = xmlStrcat(msg, BAD_CAST ".\n");
2120 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2121 }
2122 FREE_AND_NULL(str)
2123 xmlFree(msg);
2124}
2125
2126#define VERROR(err, type, msg) \
2127 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2128
2129#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2130
2131#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2132
2133#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2134
2135
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002136/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002137 * xmlSchemaPMissingAttrErr:
2138 * @ctxt: the schema validation context
2139 * @ownerDes: the designation of the owner
2140 * @ownerName: the name of the owner
2141 * @ownerItem: the owner as a schema object
2142 * @ownerElem: the owner as an element node
2143 * @node: the parent element node of the missing attribute node
2144 * @type: the corresponding type of the attribute node
2145 *
2146 * Reports an illegal attribute.
2147 */
2148static void
2149xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002151 xmlSchemaTypePtr ownerItem,
2152 xmlNodePtr ownerElem,
2153 const char *name,
2154 const char *message)
2155{
2156 xmlChar *des = NULL;
2157
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002158 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2159
Daniel Veillardc0826a72004-08-10 14:17:33 +00002160 if (message != NULL)
2161 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 else
2163 xmlSchemaPErr(ctxt, ownerElem, error,
2164 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002167}
2168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002169
Daniel Veillardc0826a72004-08-10 14:17:33 +00002170/**
2171 * xmlSchemaPResCompAttrErr:
2172 * @ctxt: the schema validation context
2173 * @error: the error code
2174 * @ownerDes: the designation of the owner
2175 * @ownerItem: the owner as a schema object
2176 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002177 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002178 * @refName: the referenced local name
2179 * @refURI: the referenced namespace URI
2180 * @message: optional message
2181 *
2182 * Used to report QName attribute values that failed to resolve
2183 * to schema components.
2184 */
2185static void
2186xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002187 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002188 xmlSchemaTypePtr ownerItem,
2189 xmlNodePtr ownerElem,
2190 const char *name,
2191 const xmlChar *refName,
2192 const xmlChar *refURI,
2193 xmlSchemaTypeType refType,
2194 const char *refTypeStr)
2195{
2196 xmlChar *des = NULL, *strA = NULL;
2197
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002200 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2201 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2204 "%s.\n", BAD_CAST des, BAD_CAST name,
2205 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002206 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002207 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002208 FREE_AND_NULL(strA)
2209}
2210
William M. Brack2f2a6632004-08-20 23:09:47 +00002211/**
2212 * xmlSchemaPCustomAttrErr:
2213 * @ctxt: the schema parser context
2214 * @error: the error code
2215 * @ownerDes: the designation of the owner
2216 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002217 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002218 *
2219 * Reports an illegal attribute during the parse.
2220 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221static void
2222xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002223 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002224 xmlChar **ownerDes,
2225 xmlSchemaTypePtr ownerItem,
2226 xmlAttrPtr attr,
2227 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002228{
2229 xmlChar *des = NULL;
2230
2231 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002235 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002236 } else
2237 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002238 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002239 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002240 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2241 if (ownerDes == NULL)
2242 FREE_AND_NULL(des);
2243}
2244
2245/**
2246 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002247 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002248 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002249 * @ownerDes: the designation of the attribute's owner
2250 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002251 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002253 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002254 */
2255static void
2256xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002257 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002258 xmlChar **ownerDes,
2259 xmlSchemaTypePtr ownerItem,
2260 xmlAttrPtr attr)
2261{
2262 xmlChar *des = NULL, *strA = NULL;
2263
2264 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002265 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002266 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002267 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002268 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002269 } else
2270 des = *ownerDes;
2271 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2272 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2273 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002274 if (ownerDes == NULL)
2275 FREE_AND_NULL(des);
2276 FREE_AND_NULL(strA);
2277}
2278
William M. Brack2f2a6632004-08-20 23:09:47 +00002279/**
2280 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002281 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002282 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002283 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002284 * @itemElem: the node of the schema item
2285 *
2286 * Creates a designation for an item.
2287 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288static void
2289xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002290 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002291 xmlSchemaTypePtr item,
2292 xmlNodePtr itemElem)
2293{
2294 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002297 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002298 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299 } else
2300 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002301}
2302
William M. Brack2f2a6632004-08-20 23:09:47 +00002303/**
2304 * xmlSchemaPCustomErr:
2305 * @ctxt: the schema parser context
2306 * @error: the error code
2307 * @itemDes: the designation of the schema item
2308 * @item: the schema item
2309 * @itemElem: the node of the schema item
2310 * @message: the error message
2311 * @str1: an optional param for the error message
2312 * @str2: an optional param for the error message
2313 * @str3: an optional param for the error message
2314 *
2315 * Reports an error during parsing.
2316 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002317static void
2318xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002319 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002320 xmlChar **itemDes,
2321 xmlSchemaTypePtr item,
2322 xmlNodePtr itemElem,
2323 const char *message,
2324 const xmlChar *str1,
2325 const xmlChar *str2,
2326 const xmlChar *str3)
2327{
2328 xmlChar *des = NULL, *msg = NULL;
2329
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002330 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002331 msg = xmlStrdup(BAD_CAST "%s: ");
2332 msg = xmlStrcat(msg, (const xmlChar *) message);
2333 msg = xmlStrcat(msg, BAD_CAST ".\n");
2334 if ((itemElem == NULL) && (item != NULL))
2335 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002336 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002337 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2338 if (itemDes == NULL)
2339 FREE_AND_NULL(des);
2340 FREE_AND_NULL(msg);
2341}
2342
William M. Brack2f2a6632004-08-20 23:09:47 +00002343/**
2344 * xmlSchemaPCustomErr:
2345 * @ctxt: the schema parser context
2346 * @error: the error code
2347 * @itemDes: the designation of the schema item
2348 * @item: the schema item
2349 * @itemElem: the node of the schema item
2350 * @message: the error message
2351 * @str1: the optional param for the error message
2352 *
2353 * Reports an error during parsing.
2354 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002355static void
2356xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002357 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002358 xmlChar **itemDes,
2359 xmlSchemaTypePtr item,
2360 xmlNodePtr itemElem,
2361 const char *message,
2362 const xmlChar *str1)
2363{
2364 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2365 str1, NULL, NULL);
2366}
2367
William M. Brack2f2a6632004-08-20 23:09:47 +00002368/**
2369 * xmlSchemaPAttrUseErr:
2370 * @ctxt: the schema parser context
2371 * @error: the error code
2372 * @itemDes: the designation of the schema type
2373 * @item: the schema type
2374 * @itemElem: the node of the schema type
2375 * @attr: the invalid schema attribute
2376 * @message: the error message
2377 * @str1: the optional param for the error message
2378 *
2379 * Reports an attribute use error during parsing.
2380 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002381static void
2382xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002383 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002384 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002385 const xmlSchemaAttributePtr attr,
2386 const char *message,
2387 const xmlChar *str1)
2388{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 xmlChar *str = NULL, *msg = NULL;
2390 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2391 msg = xmlStrcat(msg, BAD_CAST ", ");
2392 msg = xmlStrcat(msg,
2393 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2394 (xmlSchemaTypePtr) attr, NULL));
2395 FREE_AND_NULL(str);
2396 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002397 msg = xmlStrcat(msg, (const xmlChar *) message);
2398 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 xmlSchemaPErr(ctxt, attr->node, error,
2400 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002401 xmlFree(msg);
2402}
2403
William M. Brack2f2a6632004-08-20 23:09:47 +00002404/**
2405 * xmlSchemaPIllegalFacetAtomicErr:
2406 * @ctxt: the schema parser context
2407 * @error: the error code
2408 * @itemDes: the designation of the type
2409 * @item: the schema type
2410 * @baseItem: the base type of type
2411 * @facet: the illegal facet
2412 *
2413 * Reports an illegal facet for atomic simple types.
2414 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002415static void
2416xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002417 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002418 xmlChar **itemDes,
2419 xmlSchemaTypePtr item,
2420 xmlSchemaTypePtr baseItem,
2421 xmlSchemaFacetPtr facet)
2422{
2423 xmlChar *des = NULL, *strT = NULL;
2424
2425 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2426 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2427 "%s: The facet '%s' is not allowed on types derived from the "
2428 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002429 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002430 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002431 NULL, NULL);
2432 if (itemDes == NULL)
2433 FREE_AND_NULL(des);
2434 FREE_AND_NULL(strT);
2435}
2436
William M. Brack2f2a6632004-08-20 23:09:47 +00002437/**
2438 * xmlSchemaPIllegalFacetListUnionErr:
2439 * @ctxt: the schema parser context
2440 * @error: the error code
2441 * @itemDes: the designation of the schema item involved
2442 * @item: the schema item involved
2443 * @facet: the illegal facet
2444 *
2445 * Reports an illegal facet for <list> and <union>.
2446 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447static void
2448xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002449 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002450 xmlChar **itemDes,
2451 xmlSchemaTypePtr item,
2452 xmlSchemaFacetPtr facet)
2453{
2454 xmlChar *des = NULL, *strT = NULL;
2455
2456 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002457 xmlSchemaPErr(ctxt, item->node, error,
2458 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002459 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002460 if (itemDes == NULL)
2461 FREE_AND_NULL(des);
2462 FREE_AND_NULL(strT);
2463}
2464
2465/**
2466 * xmlSchemaPMutualExclAttrErr:
2467 * @ctxt: the schema validation context
2468 * @error: the error code
2469 * @elemDes: the designation of the parent element node
2470 * @attr: the bad attribute node
2471 * @type: the corresponding type of the attribute node
2472 *
2473 * Reports an illegal attribute.
2474 */
2475static void
2476xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2477 xmlParserErrors error,
2478 xmlChar **ownerDes,
2479 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002480 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002481 const char *name1,
2482 const char *name2)
2483{
2484 xmlChar *des = NULL;
2485
2486 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002487 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002488 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002489 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002490 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002491 } else
2492 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002493 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002494 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002495 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2496 if (ownerDes == NULL)
2497 FREE_AND_NULL(des)
2498}
2499
2500/**
2501 * xmlSchemaPSimpleTypeErr:
2502 * @ctxt: the schema validation context
2503 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002504 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002505 * @ownerDes: the designation of the owner
2506 * @ownerItem: the schema object if existent
2507 * @node: the validated node
2508 * @value: the validated value
2509 *
2510 * Reports a simple type validation error.
2511 * TODO: Should this report the value of an element as well?
2512 */
2513static void
2514xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2515 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002516 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002517 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002518 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002519 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002520 const xmlChar *value,
2521 const char *message,
2522 const xmlChar *str1,
2523 const xmlChar *str2)
2524{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002525 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002526
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002527 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002528 if (message == NULL) {
2529 /*
2530 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002531 */
2532 if (type != NULL) {
2533 if (node->type == XML_ATTRIBUTE_NODE)
2534 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2535 else
2536 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2537 "valid value of ");
2538 if (! xmlSchemaIsGlobalItem(type))
2539 msg = xmlStrcat(msg, BAD_CAST "the local ");
2540 else
2541 msg = xmlStrcat(msg, BAD_CAST "the ");
2542
2543 if (VARIETY_ATOMIC(type))
2544 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2545 else if (VARIETY_LIST(type))
2546 msg = xmlStrcat(msg, BAD_CAST "list type");
2547 else if (VARIETY_UNION(type))
2548 msg = xmlStrcat(msg, BAD_CAST "union type");
2549
2550 if (xmlSchemaIsGlobalItem(type)) {
2551 xmlChar *str = NULL;
2552 msg = xmlStrcat(msg, BAD_CAST " '");
2553 if (type->builtInType != 0) {
2554 msg = xmlStrcat(msg, BAD_CAST "xs:");
2555 msg = xmlStrcat(msg, type->name);
2556 } else
2557 msg = xmlStrcat(msg,
2558 xmlSchemaFormatQName(&str,
2559 type->targetNamespace, type->name));
2560 msg = xmlStrcat(msg, BAD_CAST "'.");
2561 FREE_AND_NULL(str);
2562 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002563 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002564 if (node->type == XML_ATTRIBUTE_NODE)
2565 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2566 else
2567 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2568 "valid.");
2569 }
2570 if (expected) {
2571 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2572 msg = xmlStrcat(msg, BAD_CAST expected);
2573 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2574 } else
2575 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2578 else
2579 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2580 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002581 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00002582 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002584 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002586 /* Cleanup. */
2587 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002588}
2589
William M. Brack2f2a6632004-08-20 23:09:47 +00002590/**
2591 * xmlSchemaPContentErr:
2592 * @ctxt: the schema parser context
2593 * @error: the error code
2594 * @onwerDes: the designation of the holder of the content
2595 * @ownerItem: the owner item of the holder of the content
2596 * @ownerElem: the node of the holder of the content
2597 * @child: the invalid child node
2598 * @message: the optional error message
2599 * @content: the optional string describing the correct content
2600 *
2601 * Reports an error concerning the content of a schema element.
2602 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002603static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002604xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002605 xmlParserErrors error,
2606 xmlChar **ownerDes,
2607 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002608 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002609 xmlNodePtr child,
2610 const char *message,
2611 const char *content)
2612{
2613 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002614
Daniel Veillardc0826a72004-08-10 14:17:33 +00002615 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002616 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002617 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002618 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002619 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002620 } else
2621 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002622 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002623 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2624 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002625 BAD_CAST des, BAD_CAST message);
2626 else {
2627 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002628 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2629 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002630 BAD_CAST des, BAD_CAST content);
2631 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002632 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2633 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002634 BAD_CAST des, NULL);
2635 }
2636 }
2637 if (ownerDes == NULL)
2638 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002639}
2640
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002641/************************************************************************
2642 * *
2643 * Streamable error functions *
2644 * *
2645 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002646
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002647
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002648
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002649
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002650/************************************************************************
2651 * *
2652 * Validation helper functions *
2653 * *
2654 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002655
Daniel Veillardc0826a72004-08-10 14:17:33 +00002656
Daniel Veillard4255d502002-04-16 15:50:10 +00002657/************************************************************************
2658 * *
2659 * Allocation functions *
2660 * *
2661 ************************************************************************/
2662
2663/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002664 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002665 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002666 *
2667 * Allocate a new Schema structure.
2668 *
2669 * Returns the newly allocated structure or NULL in case or error
2670 */
2671static xmlSchemaPtr
2672xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2673{
2674 xmlSchemaPtr ret;
2675
2676 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2677 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002678 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002679 return (NULL);
2680 }
2681 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002682 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002683 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002684
2685 return (ret);
2686}
2687
2688/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002689 * xmlSchemaNewSchema:
2690 * @ctxt: a schema validation context
2691 *
2692 * Allocate a new Schema structure.
2693 *
2694 * Returns the newly allocated structure or NULL in case or error
2695 */
2696static xmlSchemaAssemblePtr
2697xmlSchemaNewAssemble(void)
2698{
2699 xmlSchemaAssemblePtr ret;
2700
2701 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2702 if (ret == NULL) {
2703 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2704 return (NULL);
2705 }
2706 memset(ret, 0, sizeof(xmlSchemaAssemble));
2707 ret->items = NULL;
2708 return (ret);
2709}
2710
2711/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002712 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002713 *
2714 * Allocate a new Facet structure.
2715 *
2716 * Returns the newly allocated structure or NULL in case or error
2717 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002718xmlSchemaFacetPtr
2719xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002720{
2721 xmlSchemaFacetPtr ret;
2722
2723 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2724 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002725 return (NULL);
2726 }
2727 memset(ret, 0, sizeof(xmlSchemaFacet));
2728
2729 return (ret);
2730}
2731
2732/**
2733 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002734 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002735 * @node: a node
2736 *
2737 * Allocate a new annotation structure.
2738 *
2739 * Returns the newly allocated structure or NULL in case or error
2740 */
2741static xmlSchemaAnnotPtr
2742xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2743{
2744 xmlSchemaAnnotPtr ret;
2745
2746 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2747 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002748 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 return (NULL);
2750 }
2751 memset(ret, 0, sizeof(xmlSchemaAnnot));
2752 ret->content = node;
2753 return (ret);
2754}
2755
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002756static xmlSchemaItemListPtr
2757xmlSchemaNewItemList(void)
2758{
2759 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002760
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002761 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2762 if (ret == NULL) {
2763 xmlSchemaPErrMemory(NULL,
2764 "allocating an item list structure", NULL);
2765 return (NULL);
2766 }
2767 memset(ret, 0, sizeof(xmlSchemaItemList));
2768 return (ret);
2769}
2770
2771/**
2772 * xmlSchemaAddElementSubstitutionMember:
2773 * @pctxt: a schema parser context
2774 * @head: the head of the substitution group
2775 * @member: the new member of the substitution group
2776 *
2777 * Allocate a new annotation structure.
2778 *
2779 * Returns the newly allocated structure or NULL in case or error
2780 */
2781static int
2782xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2783 xmlSchemaElementPtr head,
2784 xmlSchemaElementPtr member)
2785{
2786 xmlSchemaSubstGroupPtr substGroup;
2787
2788 if (pctxt == NULL)
2789 return (-1);
2790
2791 if (pctxt->substGroups == NULL) {
2792 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2793 if (pctxt->substGroups == NULL)
2794 return (-1);
2795 }
2796 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2797 head->targetNamespace);
2798 if (substGroup == NULL) {
2799 int res;
2800
2801 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2802 if (substGroup == NULL) {
2803 xmlSchemaPErrMemory(NULL,
2804 "xmlSchemaAddElementSubstitution, allocating a substitution "
2805 "group container",
2806 NULL);
2807 return (-1);
2808 }
2809 substGroup->members = xmlSchemaNewItemList();
2810 if (substGroup->members == NULL) {
2811 xmlFree(substGroup);
2812 return (-1);
2813 }
2814 substGroup->head = head;
2815
2816 res = xmlHashAddEntry2(pctxt->substGroups,
2817 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002818 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002819 xmlFree(substGroup->members);
2820 xmlFree(substGroup);
2821 xmlSchemaPErr(pctxt, member->node,
2822 XML_SCHEMAP_INTERNAL,
2823 "Internal error: xmlSchemaAddElementSubstitution, "
2824 "failed to add a new substitution group container for "
2825 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002826 return (-1);
2827 }
2828 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002829 if (substGroup->members->items == NULL) {
2830 substGroup->members->items = (void **) xmlMalloc(
2831 5 * sizeof(xmlSchemaElementPtr));
2832 if (substGroup->members->items == NULL) {
2833 xmlSchemaPErrMemory(NULL,
2834 "allocating list of substitution group members", NULL);
2835 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002837 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002838 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002839 substGroup->members->nbItems) {
2840 substGroup->members->sizeItems *= 2;
2841 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002842 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002843 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2844 if (substGroup->members->items == NULL) {
2845 xmlSchemaPErrMemory(NULL,
2846 "re-allocating list of substitution group members", NULL);
2847 substGroup->members->sizeItems = 0;
2848 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002849 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002850 }
2851 ((xmlSchemaElementPtr *) substGroup->members->items)
2852 [substGroup->members->nbItems++] = (void *) member;
2853 return (0);
2854}
2855
2856/**
2857 * xmlSchemaGetElementSubstitutionGroup:
2858 * @pctxt: a schema parser context
2859 * @head: the head of the substitution group
2860 * @member: the new member of the substitution group
2861 *
2862 * Allocate a new annotation structure.
2863 *
2864 * Returns the newly allocated structure or NULL in case or error
2865 */
2866static xmlSchemaSubstGroupPtr
2867xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2868 xmlSchemaElementPtr head)
2869{
2870 if (pctxt == NULL)
2871 return (NULL);
2872
2873 if (pctxt->substGroups == NULL)
2874 return (NULL);
2875
2876 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2877 head->name, head->targetNamespace));
2878}
2879
2880/**
2881 * xmlSchemaFreeItemList:
2882 * @annot: a schema type structure
2883 *
2884 * Deallocate a annotation structure
2885 */
2886static void
2887xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2888{
2889 if (list == NULL)
2890 return;
2891 if (list->items != NULL)
2892 xmlFree(list->items);
2893 xmlFree(list);
2894}
2895
Daniel Veillard4255d502002-04-16 15:50:10 +00002896/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002897 * xmlSchemaFreeAnnot:
2898 * @annot: a schema type structure
2899 *
2900 * Deallocate a annotation structure
2901 */
2902static void
2903xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2904{
2905 if (annot == NULL)
2906 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00002907 if (annot->next == NULL) {
2908 xmlFree(annot);
2909 } else {
2910 xmlSchemaAnnotPtr prev;
2911
2912 do {
2913 prev = annot;
2914 annot = annot->next;
2915 xmlFree(prev);
2916 } while (annot != NULL);
2917 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00002918}
2919
2920/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002921 * xmlSchemaFreeImport:
2922 * @import: a schema import structure
2923 *
2924 * Deallocate an import structure
2925 */
2926static void
2927xmlSchemaFreeImport(xmlSchemaImportPtr import)
2928{
2929 if (import == NULL)
2930 return;
2931
2932 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002933 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002934 xmlFree(import);
2935}
2936
2937/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002938 * xmlSchemaFreeInclude:
2939 * @include: a schema include structure
2940 *
2941 * Deallocate an include structure
2942 */
2943static void
2944xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2945{
2946 if (include == NULL)
2947 return;
2948
2949 xmlFreeDoc(include->doc);
2950 xmlFree(include);
2951}
2952
2953/**
2954 * xmlSchemaFreeIncludeList:
2955 * @includes: a schema include list
2956 *
2957 * Deallocate an include structure
2958 */
2959static void
2960xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2961{
2962 xmlSchemaIncludePtr next;
2963
2964 while (includes != NULL) {
2965 next = includes->next;
2966 xmlSchemaFreeInclude(includes);
2967 includes = next;
2968 }
2969}
2970
2971/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002972 * xmlSchemaFreeNotation:
2973 * @schema: a schema notation structure
2974 *
2975 * Deallocate a Schema Notation structure.
2976 */
2977static void
2978xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2979{
2980 if (nota == NULL)
2981 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002982 xmlFree(nota);
2983}
2984
2985/**
2986 * xmlSchemaFreeAttribute:
2987 * @schema: a schema attribute structure
2988 *
2989 * Deallocate a Schema Attribute structure.
2990 */
2991static void
2992xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2993{
2994 if (attr == NULL)
2995 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002996 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002997 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002998 if (attr->defVal != NULL)
2999 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003000 xmlFree(attr);
3001}
3002
3003/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003004 * xmlSchemaFreeWildcardNsSet:
3005 * set: a schema wildcard namespace
3006 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003007 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003008 */
3009static void
3010xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3011{
3012 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003013
Daniel Veillard3646d642004-06-02 19:19:14 +00003014 while (set != NULL) {
3015 next = set->next;
3016 xmlFree(set);
3017 set = next;
3018 }
3019}
3020
3021/**
3022 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003023 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003024 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003025 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003026 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003027void
Daniel Veillard3646d642004-06-02 19:19:14 +00003028xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3029{
3030 if (wildcard == NULL)
3031 return;
3032 if (wildcard->annot != NULL)
3033 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003034 if (wildcard->nsSet != NULL)
3035 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3036 if (wildcard->negNsSet != NULL)
3037 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003038 xmlFree(wildcard);
3039}
3040
3041/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 * xmlSchemaFreeAttributeGroup:
3043 * @schema: a schema attribute group structure
3044 *
3045 * Deallocate a Schema Attribute Group structure.
3046 */
3047static void
3048xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3049{
3050 if (attr == NULL)
3051 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003052 if (attr->annot != NULL)
3053 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003054 xmlFree(attr);
3055}
3056
3057/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003058 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003059 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003060 *
3061 * Deallocate a list of schema attribute uses.
3062 */
3063static void
3064xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3065{
3066 xmlSchemaAttributeLinkPtr next;
3067
3068 while (attrUse != NULL) {
3069 next = attrUse->next;
3070 xmlFree(attrUse);
3071 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003073}
3074
3075/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003076 * xmlSchemaFreeQNameRef:
3077 * @item: a QName reference structure
3078 *
3079 * Deallocatea a QName reference structure.
3080 */
3081static void
3082xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3083{
3084 xmlFree(item);
3085}
3086
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003087/**
3088 * xmlSchemaFreeQNameRef:
3089 * @item: a QName reference structure
3090 *
3091 * Deallocatea a QName reference structure.
3092 */
3093static void
3094xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3095{
3096 if (item == NULL)
3097 return;
3098 if (item->members != NULL)
3099 xmlSchemaFreeItemList(item->members);
3100 xmlFree(item);
3101}
3102
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003103static int
3104xmlSchemaAddVolatile(xmlSchemaPtr schema,
3105 xmlSchemaBasicItemPtr item)
3106{
3107 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003108
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003109 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003110 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003111 if (schema->volatiles == NULL) {
3112 xmlSchemaPErrMemory(NULL,
3113 "allocating list of volatiles", NULL);
3114 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003115 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003116 }
3117 list = (xmlSchemaItemListPtr) schema->volatiles;
3118 if (list->items == NULL) {
3119 list->items = (void **) xmlMalloc(
3120 20 * sizeof(xmlSchemaBasicItemPtr));
3121 if (list->items == NULL) {
3122 xmlSchemaPErrMemory(NULL,
3123 "allocating new volatile item buffer", NULL);
3124 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003126 list->sizeItems = 20;
3127 } else if (list->sizeItems <= list->nbItems) {
3128 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003129 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003130 list->sizeItems * sizeof(xmlSchemaTypePtr));
3131 if (list->items == NULL) {
3132 xmlSchemaPErrMemory(NULL,
3133 "growing volatile item buffer", NULL);
3134 list->sizeItems = 0;
3135 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003137 }
3138 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3139 return (0);
3140}
3141
3142/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003143 * xmlSchemaFreeTypeLinkList:
3144 * @alink: a type link
3145 *
3146 * Deallocate a list of types.
3147 */
3148static void
3149xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3150{
3151 xmlSchemaTypeLinkPtr next;
3152
3153 while (link != NULL) {
3154 next = link->next;
3155 xmlFree(link);
3156 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003157 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003158}
3159
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003160static void
3161xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3162{
3163 xmlSchemaIDCStateObjPtr next;
3164 while (sto != NULL) {
3165 next = sto->next;
3166 if (sto->history != NULL)
3167 xmlFree(sto->history);
3168 if (sto->xpathCtxt != NULL)
3169 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3170 xmlFree(sto);
3171 sto = next;
3172 }
3173}
3174
3175/**
3176 * xmlSchemaFreeIDC:
3177 * @idc: a identity-constraint definition
3178 *
3179 * Deallocates an identity-constraint definition.
3180 */
3181static void
3182xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3183{
3184 xmlSchemaIDCSelectPtr cur, prev;
3185
3186 if (idcDef == NULL)
3187 return;
3188 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003189 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003190 /* Selector */
3191 if (idcDef->selector != NULL) {
3192 if (idcDef->selector->xpathComp != NULL)
3193 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3194 xmlFree(idcDef->selector);
3195 }
3196 /* Fields */
3197 if (idcDef->fields != NULL) {
3198 cur = idcDef->fields;
3199 do {
3200 prev = cur;
3201 cur = cur->next;
3202 if (prev->xpathComp != NULL)
3203 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003204 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003205 } while (cur != NULL);
3206 }
3207 xmlFree(idcDef);
3208}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003209
Daniel Veillard01fa6152004-06-29 17:04:39 +00003210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 * xmlSchemaFreeElement:
3212 * @schema: a schema element structure
3213 *
3214 * Deallocate a Schema Element structure.
3215 */
3216static void
3217xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3218{
3219 if (elem == NULL)
3220 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003221 if (elem->annot != NULL)
3222 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003223 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003224 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003225 if (elem->defVal != NULL)
3226 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 xmlFree(elem);
3228}
3229
3230/**
3231 * xmlSchemaFreeFacet:
3232 * @facet: a schema facet structure
3233 *
3234 * Deallocate a Schema Facet structure.
3235 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003236void
Daniel Veillard4255d502002-04-16 15:50:10 +00003237xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3238{
3239 if (facet == NULL)
3240 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003241 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003242 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003243 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003244 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003245 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003246 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003247 xmlFree(facet);
3248}
3249
3250/**
3251 * xmlSchemaFreeType:
3252 * @type: a schema type structure
3253 *
3254 * Deallocate a Schema Type structure.
3255 */
3256void
3257xmlSchemaFreeType(xmlSchemaTypePtr type)
3258{
3259 if (type == NULL)
3260 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003261 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003262 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003263 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003264 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003265
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003266 facet = type->facets;
3267 while (facet != NULL) {
3268 next = facet->next;
3269 xmlSchemaFreeFacet(facet);
3270 facet = next;
3271 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003272 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003273 if (type->type != XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003274 /*
3275 * TODO: Why is this restricted to non built-in types?
3276 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003277 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003278 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003279 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003280 if (type->memberTypes != NULL)
3281 xmlSchemaFreeTypeLinkList(type->memberTypes);
3282 if (type->facetSet != NULL) {
3283 xmlSchemaFacetLinkPtr next, link;
3284
3285 link = type->facetSet;
3286 do {
3287 next = link->next;
3288 xmlFree(link);
3289 link = next;
3290 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003291 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003292 if (type->contModel != NULL)
3293 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003294 xmlFree(type);
3295}
3296
3297/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003298 * xmlSchemaFreeModelGroupDef:
3299 * @item: a schema model group definition
3300 *
3301 * Deallocates a schema model group definition.
3302 */
3303static void
3304xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3305{
3306 if (item->annot != NULL)
3307 xmlSchemaFreeAnnot(item->annot);
3308 xmlFree(item);
3309}
3310
3311/**
3312 * xmlSchemaFreeModelGroup:
3313 * @item: a schema model group
3314 *
3315 * Deallocates a schema model group structure.
3316 */
3317static void
3318xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3319{
3320 if (item->annot != NULL)
3321 xmlSchemaFreeAnnot(item->annot);
3322 xmlFree(item);
3323}
3324
3325/**
3326 * xmlSchemaFreeParticle:
3327 * @type: a schema type structure
3328 *
3329 * Deallocate a Schema Type structure.
3330 */
3331static void
3332xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3333{
3334 if (item->annot != NULL)
3335 xmlSchemaFreeAnnot(item->annot);
3336 xmlFree(item);
3337}
3338
3339/**
3340 * xmlSchemaFreeMiscComponents:
3341 * @item: a schema component
3342 *
3343 * Deallocates misc. schema component structures.
3344 */
3345static void
3346xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3347{
3348 if (item == NULL)
3349 return;
3350 switch (item->type) {
3351 case XML_SCHEMA_TYPE_PARTICLE:
3352 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3353 return;
3354 case XML_SCHEMA_TYPE_SEQUENCE:
3355 case XML_SCHEMA_TYPE_CHOICE:
3356 case XML_SCHEMA_TYPE_ALL:
3357 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3358 return;
3359 case XML_SCHEMA_TYPE_ANY:
3360 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3361 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3362 break;
3363 default:
3364 /* TODO: This should never be hit. */
3365 TODO
3366 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003367 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003368}
3369
3370static void
3371xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3372{
3373 if (schema->volatiles == NULL)
3374 return;
3375 {
3376 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3377 xmlSchemaTreeItemPtr item;
3378 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003379
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003380 for (i = 0; i < list->nbItems; i++) {
3381 if (list->items[i] != NULL) {
3382 item = (xmlSchemaTreeItemPtr) list->items[i];
3383 switch (item->type) {
3384 case XML_SCHEMA_EXTRA_QNAMEREF:
3385 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3386 break;
3387 default:
3388 xmlSchemaFreeMiscComponents(item);
3389 }
3390 }
3391 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003392 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003393 }
3394}
3395/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003396 * xmlSchemaFreeTypeList:
3397 * @type: a schema type structure
3398 *
3399 * Deallocate a Schema Type structure.
3400 */
3401static void
3402xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3403{
3404 xmlSchemaTypePtr next;
3405
3406 while (type != NULL) {
3407 next = type->redef;
3408 xmlSchemaFreeType(type);
3409 type = next;
3410 }
3411}
3412
3413/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003414 * xmlSchemaFree:
3415 * @schema: a schema structure
3416 *
3417 * Deallocate a Schema structure.
3418 */
3419void
3420xmlSchemaFree(xmlSchemaPtr schema)
3421{
3422 if (schema == NULL)
3423 return;
3424
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003425 if (schema->volatiles != NULL)
3426 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003427 if (schema->notaDecl != NULL)
3428 xmlHashFree(schema->notaDecl,
3429 (xmlHashDeallocator) xmlSchemaFreeNotation);
3430 if (schema->attrDecl != NULL)
3431 xmlHashFree(schema->attrDecl,
3432 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3433 if (schema->attrgrpDecl != NULL)
3434 xmlHashFree(schema->attrgrpDecl,
3435 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3436 if (schema->elemDecl != NULL)
3437 xmlHashFree(schema->elemDecl,
3438 (xmlHashDeallocator) xmlSchemaFreeElement);
3439 if (schema->typeDecl != NULL)
3440 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003441 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003442 if (schema->groupDecl != NULL)
3443 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003444 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003445 if (schema->idcDef != NULL)
3446 xmlHashFree(schema->idcDef,
3447 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003448 if (schema->schemasImports != NULL)
3449 xmlHashFree(schema->schemasImports,
3450 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003451 if (schema->includes != NULL) {
3452 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3453 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003454 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003455 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003456 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003457 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003458 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003459 xmlFree(schema);
3460}
3461
3462/************************************************************************
3463 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003464 * Debug functions *
3465 * *
3466 ************************************************************************/
3467
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003468#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003469
Daniel Veillard4255d502002-04-16 15:50:10 +00003470/**
3471 * xmlSchemaElementDump:
3472 * @elem: an element
3473 * @output: the file output
3474 *
3475 * Dump the element
3476 */
3477static void
3478xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003479 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003480 const xmlChar * namespace ATTRIBUTE_UNUSED,
3481 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003482{
3483 if (elem == NULL)
3484 return;
3485
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003486 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3487 fprintf(output, "Particle: %s", name);
3488 fprintf(output, ", term element: %s", elem->ref);
3489 if (elem->refNs != NULL)
3490 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003491 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003492 fprintf(output, "Element");
3493 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3494 fprintf(output, " (global)");
3495 fprintf(output, ": %s ", elem->name);
3496 if (namespace != NULL)
3497 fprintf(output, "ns %s", namespace);
3498 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003499 fprintf(output, "\n");
3500 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003501 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003502 if (elem->maxOccurs >= UNBOUNDED)
3503 fprintf(output, "max: unbounded\n");
3504 else if (elem->maxOccurs != 1)
3505 fprintf(output, "max: %d\n", elem->maxOccurs);
3506 else
3507 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003508 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003509 /*
3510 * Misc other properties.
3511 */
3512 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3513 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3514 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3515 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3516 (elem->id != NULL)) {
3517 fprintf(output, " props: ");
3518 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3519 fprintf(output, "[fixed] ");
3520 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3521 fprintf(output, "[default] ");
3522 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3523 fprintf(output, "[abstract] ");
3524 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3525 fprintf(output, "[nillable] ");
3526 if (elem->id != NULL)
3527 fprintf(output, "[id: '%s'] ", elem->id);
3528 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003529 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003530 /*
3531 * Default/fixed value.
3532 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003533 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003534 fprintf(output, " value: '%s'\n", elem->value);
3535 /*
3536 * Type.
3537 */
3538 if (elem->namedType != NULL) {
3539 fprintf(output, " type: %s ", elem->namedType);
3540 if (elem->namedTypeNs != NULL)
3541 fprintf(output, "ns %s\n", elem->namedTypeNs);
3542 else
3543 fprintf(output, "\n");
3544 }
3545 /*
3546 * Substitution group.
3547 */
3548 if (elem->substGroup != NULL) {
3549 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3550 if (elem->substGroupNs != NULL)
3551 fprintf(output, "ns %s\n", elem->substGroupNs);
3552 else
3553 fprintf(output, "\n");
3554 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003555}
3556
3557/**
3558 * xmlSchemaAnnotDump:
3559 * @output: the file output
3560 * @annot: a annotation
3561 *
3562 * Dump the annotation
3563 */
3564static void
3565xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3566{
3567 xmlChar *content;
3568
3569 if (annot == NULL)
3570 return;
3571
3572 content = xmlNodeGetContent(annot->content);
3573 if (content != NULL) {
3574 fprintf(output, " Annot: %s\n", content);
3575 xmlFree(content);
3576 } else
3577 fprintf(output, " Annot: empty\n");
3578}
3579
3580/**
3581 * xmlSchemaTypeDump:
3582 * @output: the file output
3583 * @type: a type structure
3584 *
3585 * Dump a SchemaType structure
3586 */
3587static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003588xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3589{
3590 xmlChar *str = NULL;
3591 xmlSchemaTreeItemPtr term;
3592 char shift[100];
3593 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003594
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003595 if (particle == NULL)
3596 return;
3597 for (i = 0;((i < depth) && (i < 25));i++)
3598 shift[2 * i] = shift[2 * i + 1] = ' ';
3599 shift[2 * i] = shift[2 * i + 1] = 0;
3600 fprintf(output, shift);
3601 if (particle->children == NULL) {
3602 fprintf(output, "MISSING particle term\n");
3603 return;
3604 }
3605 term = particle->children;
3606 switch (term->type) {
3607 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003608 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003609 ((xmlSchemaElementPtr)term)->targetNamespace,
3610 ((xmlSchemaElementPtr)term)->name));
3611 break;
3612 case XML_SCHEMA_TYPE_SEQUENCE:
3613 fprintf(output, "SEQUENCE");
3614 break;
3615 case XML_SCHEMA_TYPE_CHOICE:
3616 fprintf(output, "CHOICE");
3617 break;
3618 case XML_SCHEMA_TYPE_ALL:
3619 fprintf(output, "ALL");
3620 break;
3621 case XML_SCHEMA_TYPE_ANY:
3622 fprintf(output, "ANY");
3623 break;
3624 default:
3625 fprintf(output, "UNKNOWN\n");
3626 return;
3627 }
3628 if (particle->minOccurs != 1)
3629 fprintf(output, " min: %d", particle->minOccurs);
3630 if (particle->maxOccurs >= UNBOUNDED)
3631 fprintf(output, " max: unbounded");
3632 else if (particle->maxOccurs != 1)
3633 fprintf(output, " max: %d", particle->maxOccurs);
3634 fprintf(output, "\n");
3635 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3636 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3637 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3638 (term->children != NULL)) {
3639 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3640 output, depth +1);
3641 }
3642 if (particle->next != NULL)
3643 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3644 output, depth);
3645}
3646/**
3647 * xmlSchemaTypeDump:
3648 * @output: the file output
3649 * @type: a type structure
3650 *
3651 * Dump a SchemaType structure
3652 */
3653static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003654xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3655{
3656 if (type == NULL) {
3657 fprintf(output, "Type: NULL\n");
3658 return;
3659 }
3660 fprintf(output, "Type: ");
3661 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003662 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003663 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "no name ");
3665 if (type->targetNamespace != NULL)
3666 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 switch (type->type) {
3668 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003669 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 break;
3671 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003672 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 break;
3674 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003675 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 break;
3677 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003678 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 break;
3680 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003681 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003682 break;
3683 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003684 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 break;
3686 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003687 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 break;
3689 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003690 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003691 break;
3692 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003693 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 break;
3695 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003696 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003698 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003699 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003700 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003701 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003702 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003703 break;
3704 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003705 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003706 break;
3707 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003708 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709 break;
3710 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003711 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003712 break;
3713 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003714 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003715 break;
3716 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003717 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003718 break;
3719 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003720 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 break;
3722 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003723 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003724 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 }
3726 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003727 if (type->base != NULL) {
3728 fprintf(output, " base type: %s", type->base);
3729 if (type->baseNs != NULL)
3730 fprintf(output, " ns %s\n", type->baseNs);
3731 else
3732 fprintf(output, "\n");
3733 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 if (type->annot != NULL)
3735 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003736#ifdef DUMP_CONTENT_MODEL
3737 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3738 (type->subtypes != NULL)) {
3739 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3740 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003741 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003742#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003743}
3744
3745/**
3746 * xmlSchemaDump:
3747 * @output: the file output
3748 * @schema: a schema structure
3749 *
3750 * Dump a Schema structure.
3751 */
3752void
3753xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3754{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003755 if (output == NULL)
3756 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003757 if (schema == NULL) {
3758 fprintf(output, "Schemas: NULL\n");
3759 return;
3760 }
3761 fprintf(output, "Schemas: ");
3762 if (schema->name != NULL)
3763 fprintf(output, "%s, ", schema->name);
3764 else
3765 fprintf(output, "no name, ");
3766 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003767 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 else
3769 fprintf(output, "no target namespace");
3770 fprintf(output, "\n");
3771 if (schema->annot != NULL)
3772 xmlSchemaAnnotDump(output, schema->annot);
3773
3774 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3775 output);
3776 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003778}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003779
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003780#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003781/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003782 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003783 * @vctxt: the WXS validation context
3784 *
3785 * Displays the current IDC table for debug purposes.
3786 */
3787static void
3788xmlSchemaDebugDumpIDCTable(FILE * output,
3789 const xmlChar *namespaceName,
3790 const xmlChar *localName,
3791 xmlSchemaPSVIIDCBindingPtr bind)
3792{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003794 xmlSchemaPSVIIDCNodePtr tab;
3795 xmlSchemaPSVIIDCKeyPtr key;
3796 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003797
3798 fprintf(output, "IDC: TABLES on %s\n",
3799 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003800 FREE_AND_NULL(str)
3801
3802 if (bind == NULL)
3803 return;
3804 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003805 fprintf(output, "IDC: BINDING %s\n",
3806 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003807 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003808 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003809 for (i = 0; i < bind->nbNodes; i++) {
3810 tab = bind->nodeTable[i];
3811 fprintf(output, " ( ");
3812 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003813 key = tab->keys[j];
3814 if ((key != NULL) && (key->val != NULL)) {
3815 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003816 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003817 fprintf(output, "\"%s\" ", value);
3818 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003819 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003820 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003821 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003822 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003823 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003824 else
3825 fprintf(output, "(key missing), ");
3826 }
3827 fprintf(output, ")\n");
3828 }
3829 bind = bind->next;
3830 } while (bind != NULL);
3831}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003832#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003833#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003834
3835/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003836 * *
3837 * Utilities *
3838 * *
3839 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003840
Daniel Veillardc0826a72004-08-10 14:17:33 +00003841/**
3842 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003843 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003844 * @name: the name of the attribute
3845 *
3846 * Seeks an attribute with a name of @name in
3847 * no namespace.
3848 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003849 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003850 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003851static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003852xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003853{
3854 xmlAttrPtr prop;
3855
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003856 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003857 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003858 prop = node->properties;
3859 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003860 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003861 return(prop);
3862 prop = prop->next;
3863 }
3864 return (NULL);
3865}
3866
3867/**
3868 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003869 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003870 * @uri: the uri
3871 * @name: the name of the attribute
3872 *
3873 * Seeks an attribute with a local name of @name and
3874 * a namespace URI of @uri.
3875 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003876 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003877 */
3878static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003879xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003880{
3881 xmlAttrPtr prop;
3882
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003883 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003884 return(NULL);
3885 prop = node->properties;
3886 while (prop != NULL) {
3887 if ((prop->ns != NULL) &&
3888 xmlStrEqual(prop->name, BAD_CAST name) &&
3889 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003890 return(prop);
3891 prop = prop->next;
3892 }
3893 return (NULL);
3894}
3895
3896static const xmlChar *
3897xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3898{
3899 xmlChar *val;
3900 const xmlChar *ret;
3901
3902 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003904 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003905 ret = xmlDictLookup(ctxt->dict, val, -1);
3906 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003907 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003908}
3909
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003910/**
3911 * xmlSchemaGetProp:
3912 * @ctxt: the parser context
3913 * @node: the node
3914 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003916 * Read a attribute value and internalize the string
3917 *
3918 * Returns the string or NULL if not present.
3919 */
3920static const xmlChar *
3921xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3922 const char *name)
3923{
3924 xmlChar *val;
3925 const xmlChar *ret;
3926
3927 val = xmlGetProp(node, BAD_CAST name);
3928 if (val == NULL)
3929 return(NULL);
3930 ret = xmlDictLookup(ctxt->dict, val, -1);
3931 xmlFree(val);
3932 return(ret);
3933}
3934
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003935/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003936 * *
3937 * Parsing functions *
3938 * *
3939 ************************************************************************/
3940
3941/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003943 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003944 * @name: the element name
3945 * @ns: the element namespace
3946 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003947 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003949 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003950 */
3951static xmlSchemaElementPtr
3952xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003953 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003954{
3955 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003956
3957 if ((name == NULL) || (schema == NULL))
3958 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003959
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003960 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003961 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003962 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003963 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003964 } else
3965 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003966 /*
3967 * This one was removed, since top level element declarations have
3968 * the target namespace specified in targetNamespace of the <schema>
3969 * information element, even if elementFormDefault is "unqualified".
3970 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003971
William M. Bracke7091952004-05-11 15:09:58 +00003972 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003973 if (xmlStrEqual(namespace, schema->targetNamespace))
3974 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3975 else
3976 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003977 if ((ret != NULL) &&
3978 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003979 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003980 }
William M. Bracke7091952004-05-11 15:09:58 +00003981 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982
William M. Brack2f2a6632004-08-20 23:09:47 +00003983 /*
3984 * Removed since imported components will be hold by the main schema only.
3985 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003986 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003987 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003988 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003989 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003990 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003991 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003992 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3993 return (ret);
3994 } else
3995 ret = NULL;
3996 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003997 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003998#ifdef DEBUG
3999 if (ret == NULL) {
4000 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004001 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004002 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004003 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004004 namespace);
4005 }
4006#endif
4007 return (ret);
4008}
4009
4010/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004011 * xmlSchemaGetType:
4012 * @schema: the schemas context
4013 * @name: the type name
4014 * @ns: the type namespace
4015 *
4016 * Lookup a type in the schemas or the predefined types
4017 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004018 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004019 */
4020static xmlSchemaTypePtr
4021xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004022 const xmlChar * namespace)
4023{
Daniel Veillard4255d502002-04-16 15:50:10 +00004024 xmlSchemaTypePtr ret;
4025
4026 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004027 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004028 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004029 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004031 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 }
4033 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00004034 if (ret != NULL)
4035 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 /*
4037 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004040 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004042 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004043 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004044 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004045 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4046 return (ret);
4047 } else
4048 ret = NULL;
4049 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004050 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004051#ifdef DEBUG
4052 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004053 if (namespace == NULL)
4054 fprintf(stderr, "Unable to lookup type %s", name);
4055 else
4056 fprintf(stderr, "Unable to lookup type %s:%s", name,
4057 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 }
4059#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004060 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004061}
4062
Daniel Veillard3646d642004-06-02 19:19:14 +00004063/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004064 * xmlSchemaGetAttributeDecl:
4065 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004066 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004067 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004068 *
4069 * Lookup a an attribute in the schema or imported schemas
4070 *
4071 * Returns the attribute declaration or NULL if not found.
4072 */
4073static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004074xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004075 const xmlChar * namespace)
4076{
4077 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004078
4079 if ((name == NULL) || (schema == NULL))
4080 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081
4082
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4084 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004085 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004086 else
4087 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 /*
4089 * Removed, since imported components will be hold by the main schema only.
4090 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004092 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004093 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004094 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004095 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004096 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004097 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4098 return (ret);
4099 } else
4100 ret = NULL;
4101 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004102 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004103#ifdef DEBUG
4104 if (ret == NULL) {
4105 if (namespace == NULL)
4106 fprintf(stderr, "Unable to lookup attribute %s", name);
4107 else
4108 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4109 namespace);
4110 }
4111#endif
4112 return (ret);
4113}
4114
4115/**
4116 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004117 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004118 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004119 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004120 *
4121 * Lookup a an attribute group in the schema or imported schemas
4122 *
4123 * Returns the attribute group definition or NULL if not found.
4124 */
4125static xmlSchemaAttributeGroupPtr
4126xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4127 const xmlChar * namespace)
4128{
4129 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004130
4131 if ((name == NULL) || (schema == NULL))
4132 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004133
4134
Daniel Veillard3646d642004-06-02 19:19:14 +00004135 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4136 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004137 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004138 else
4139 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004140 /*
4141 * Removed since imported components will be hold by the main schema only.
4142 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004143 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004144 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004145 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004146 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004147 if (import != NULL) {
4148 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4149 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4150 return (ret);
4151 else
4152 ret = NULL;
4153 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004154 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004155#ifdef DEBUG
4156 if (ret == NULL) {
4157 if (namespace == NULL)
4158 fprintf(stderr, "Unable to lookup attribute group %s", name);
4159 else
4160 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4161 namespace);
4162 }
4163#endif
4164 return (ret);
4165}
4166
4167/**
4168 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004169 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004170 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004171 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004172 *
4173 * Lookup a group in the schema or imported schemas
4174 *
4175 * Returns the group definition or NULL if not found.
4176 */
4177static xmlSchemaTypePtr
4178xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4179 const xmlChar * namespace)
4180{
4181 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004182
4183 if ((name == NULL) || (schema == NULL))
4184 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004185
Daniel Veillard3646d642004-06-02 19:19:14 +00004186 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004187 /*
4188 * Removed since imported components will be hold by the main schema only.
4189 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004190 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004191 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004192 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004194 if (import != NULL) {
4195 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4196 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4197 return (ret);
4198 else
4199 ret = NULL;
4200 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004201 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004202#ifdef DEBUG
4203 if (ret == NULL) {
4204 if (namespace == NULL)
4205 fprintf(stderr, "Unable to lookup group %s", name);
4206 else
4207 fprintf(stderr, "Unable to lookup group %s:%s", name,
4208 namespace);
4209 }
4210#endif
4211 return (ret);
4212}
4213
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004214/**
4215 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004216 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004217 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004218 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004219 *
4220 * Lookup a group in the schema or imported schemas
4221 *
4222 * Returns the group definition or NULL if not found.
4223 */
4224static xmlSchemaTreeItemPtr
4225xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4226 xmlSchemaTypeType itemType,
4227 const xmlChar *name,
4228 const xmlChar *targetNs)
4229{
4230 switch (itemType) {
4231 case XML_SCHEMA_TYPE_GROUP:
4232 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4233 name, targetNs));
4234 case XML_SCHEMA_TYPE_ELEMENT:
4235 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4236 name, targetNs));
4237 default:
4238 return (NULL);
4239 }
4240}
4241
Daniel Veillard4255d502002-04-16 15:50:10 +00004242/************************************************************************
4243 * *
4244 * Parsing functions *
4245 * *
4246 ************************************************************************/
4247
4248#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004249 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004250
4251/**
4252 * xmlSchemaIsBlank:
4253 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004254 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 *
4256 * Check if a string is ignorable
4257 *
4258 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4259 */
4260static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004261xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004262{
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004265 if (len < 0) {
4266 while (*str != 0) {
4267 if (!(IS_BLANK_CH(*str)))
4268 return (0);
4269 str++;
4270 }
4271 } else while ((*str != 0) && (len != 0)) {
4272 if (!(IS_BLANK_CH(*str)))
4273 return (0);
4274 str++;
4275 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004276 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004277
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004278 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004279}
4280
4281/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004282 * xmlSchemaAddAssembledItem:
4283 * @ctxt: a schema parser context
4284 * @schema: the schema being built
4285 * @item: the item
4286 *
4287 * Add a item to the schema's list of current items.
4288 * This is used if the schema was already constructed and
4289 * new schemata need to be added to it.
4290 * *WARNING* this interface is highly subject to change.
4291 *
4292 * Returns 0 if suceeds and -1 if an internal error occurs.
4293 */
4294static int
4295xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4296 xmlSchemaTypePtr item)
4297{
4298 static int growSize = 100;
4299 xmlSchemaAssemblePtr ass;
4300
4301 ass = ctxt->assemble;
4302 if (ass->sizeItems < 0) {
4303 /* If disabled. */
4304 return (0);
4305 }
4306 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004307 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004308 if (ass->items == NULL) {
4309 xmlSchemaPErrMemory(ctxt,
4310 "allocating new item buffer", NULL);
4311 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004312 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004313 ass->sizeItems = growSize;
4314 } else if (ass->sizeItems <= ass->nbItems) {
4315 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004316 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004317 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4318 if (ass->items == NULL) {
4319 xmlSchemaPErrMemory(ctxt,
4320 "growing item buffer", NULL);
4321 ass->sizeItems = 0;
4322 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004323 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004324 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004325 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004326 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4327 return (0);
4328}
4329
4330/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004332 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 * @schema: the schema being built
4334 * @name: the item name
4335 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004336 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004337 * *WARNING* this interface is highly subject to change
4338 *
4339 * Returns the new struture or NULL in case of error
4340 */
4341static xmlSchemaNotationPtr
4342xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004343 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004344{
4345 xmlSchemaNotationPtr ret = NULL;
4346 int val;
4347
4348 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4349 return (NULL);
4350
4351 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004352 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 if (schema->notaDecl == NULL)
4354 return (NULL);
4355
4356 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4357 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004358 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 return (NULL);
4360 }
4361 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004362 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4364 ret);
4365 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004366 /*
4367 * TODO: This should never happen, since a unique name will be computed.
4368 * If it fails, then an other internal error must have occured.
4369 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004370 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4371 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004372 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004373 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004374 xmlFree(ret);
4375 return (NULL);
4376 }
4377 return (ret);
4378}
4379
4380
4381/**
4382 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004383 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 * @schema: the schema being built
4385 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004386 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 *
4388 * Add an XML schema Attrribute declaration
4389 * *WARNING* this interface is highly subject to change
4390 *
4391 * Returns the new struture or NULL in case of error
4392 */
4393static xmlSchemaAttributePtr
4394xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004395 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004396 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004397{
4398 xmlSchemaAttributePtr ret = NULL;
4399 int val;
4400
4401 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4402 return (NULL);
4403
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004404#ifdef DEBUG
4405 fprintf(stderr, "Adding attribute %s\n", name);
4406 if (namespace != NULL)
4407 fprintf(stderr, " target namespace %s\n", namespace);
4408#endif
4409
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004411 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004412 if (schema->attrDecl == NULL)
4413 return (NULL);
4414
4415 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4416 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 return (NULL);
4419 }
4420 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004421 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004422 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004423 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004424 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004425 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004426 if (topLevel) {
4427 xmlSchemaPCustomErr(ctxt,
4428 XML_SCHEMAP_REDEFINED_ATTR,
4429 NULL, NULL, node,
4430 "A global attribute declaration with the name '%s' does "
4431 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004432 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004433 return (NULL);
4434 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004435 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004436 /*
4437 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4438 * in the scenario:
4439 * 1. multiple top-level complex types have different target
4440 * namespaces but have the SAME NAME; this can happen if
4441 * schemata are imported
4442 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004443 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004444 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004445 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004446 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004447 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004448 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004449
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004450 if (val != 0) {
4451 xmlSchemaPCustomErr(ctxt,
4452 XML_SCHEMAP_INTERNAL,
4453 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004454 "Internal error: xmlSchemaAddAttribute, "
4455 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004456 "could not be added to the hash.", name);
4457 xmlFree(ret);
4458 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004459 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004460 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004461 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004462 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004463 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 return (ret);
4465}
4466
4467/**
4468 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004469 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 * @schema: the schema being built
4471 * @name: the item name
4472 *
4473 * Add an XML schema Attrribute Group declaration
4474 *
4475 * Returns the new struture or NULL in case of error
4476 */
4477static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004478xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004479 xmlSchemaPtr schema, const xmlChar * name,
4480 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004481{
4482 xmlSchemaAttributeGroupPtr ret = NULL;
4483 int val;
4484
4485 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4486 return (NULL);
4487
4488 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004489 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 if (schema->attrgrpDecl == NULL)
4491 return (NULL);
4492
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004493 ret =
4494 (xmlSchemaAttributeGroupPtr)
4495 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004497 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (NULL);
4499 }
4500 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
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->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 xmlSchemaPCustomErr(ctxt,
4506 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4507 NULL, NULL, node,
4508 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004509 xmlFree(ret);
4510 return (NULL);
4511 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004512 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004513 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 return (ret);
4515}
4516
4517/**
4518 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004519 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004520 * @schema: the schema being built
4521 * @name: the type name
4522 * @namespace: the type namespace
4523 *
4524 * Add an XML schema Element declaration
4525 * *WARNING* this interface is highly subject to change
4526 *
4527 * Returns the new struture or NULL in case of error
4528 */
4529static xmlSchemaElementPtr
4530xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004531 const xmlChar * name, const xmlChar * namespace,
4532 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004533{
4534 xmlSchemaElementPtr ret = NULL;
4535 int val;
4536
4537 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4538 return (NULL);
4539
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004540#ifdef DEBUG
4541 fprintf(stderr, "Adding element %s\n", name);
4542 if (namespace != NULL)
4543 fprintf(stderr, " target namespace %s\n", namespace);
4544#endif
4545
Daniel Veillard4255d502002-04-16 15:50:10 +00004546 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004547 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004548 if (schema->elemDecl == NULL)
4549 return (NULL);
4550
4551 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4552 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004553 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004554 return (NULL);
4555 }
4556 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004557 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004558 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004559 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004561 if (topLevel) {
4562 xmlSchemaPCustomErr(ctxt,
4563 XML_SCHEMAP_REDEFINED_ELEMENT,
4564 NULL, NULL, node,
4565 "A global element declaration with the name '%s' does "
4566 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004567 xmlFree(ret);
4568 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004569 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004570 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004571
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004572 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004573 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004574 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004575 if (val != 0) {
4576 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004577 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004578 NULL, NULL, node,
4579 "Internal error: xmlSchemaAddElement, "
4580 "a dublicate element declaration with the name '%s' "
4581 "could not be added to the hash.", name);
4582 xmlFree(ret);
4583 return (NULL);
4584 }
4585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004586
Daniel Veillard4255d502002-04-16 15:50:10 +00004587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004588 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004589 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 return (ret);
4591}
4592
4593/**
4594 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004595 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004596 * @schema: the schema being built
4597 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004598 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004599 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004600 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004601 * *WARNING* this interface is highly subject to change
4602 *
4603 * Returns the new struture or NULL in case of error
4604 */
4605static xmlSchemaTypePtr
4606xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004607 const xmlChar * name, const xmlChar * namespace,
4608 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004609{
4610 xmlSchemaTypePtr ret = NULL;
4611 int val;
4612
4613 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4614 return (NULL);
4615
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004616#ifdef DEBUG
4617 fprintf(stderr, "Adding type %s\n", name);
4618 if (namespace != NULL)
4619 fprintf(stderr, " target namespace %s\n", namespace);
4620#endif
4621
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004623 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 if (schema->typeDecl == NULL)
4625 return (NULL);
4626
4627 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4628 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 return (NULL);
4631 }
4632 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004633 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004634 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004635 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004636 if (val != 0) {
4637 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004638 xmlSchemaPCustomErr(ctxt,
4639 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004640 NULL, NULL, node,
4641 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004642 xmlFree(ret);
4643 return (NULL);
4644 } else {
4645 xmlSchemaTypePtr prev;
4646
4647 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4648 if (prev == NULL) {
4649 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004650 XML_ERR_INTERNAL_ERROR,
4651 "Internal error: xmlSchemaAddType, on type "
4652 "'%s'.\n",
4653 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004654 xmlFree(ret);
4655 return (NULL);
4656 }
4657 ret->redef = prev->redef;
4658 prev->redef = ret;
4659 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004661 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004662 ret->minOccurs = 1;
4663 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004664 ret->attributeUses = NULL;
4665 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004666 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004667 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004668 return (ret);
4669}
4670
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004671static xmlSchemaQNameRefPtr
4672xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4673 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004674 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004675 const xmlChar *refNs)
4676{
4677 xmlSchemaQNameRefPtr ret;
4678
4679 ret = (xmlSchemaQNameRefPtr)
4680 xmlMalloc(sizeof(xmlSchemaQNameRef));
4681 if (ret == NULL) {
4682 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4683 NULL);
4684 return (NULL);
4685 }
4686 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4687 ret->name = refName;
4688 ret->targetNamespace = refNs;
4689 ret->item = NULL;
4690 ret->itemType = refType;
4691 /*
4692 * Store the reference item in the schema.
4693 */
4694 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4695 return (ret);
4696}
4697
4698/**
4699 * xmlSchemaAddModelGroup:
4700 * @ctxt: a schema parser context
4701 * @schema: the schema being built
4702 * @type: the "compositor" type of the model group
4703 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004704 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004705 *
4706 * Adds a schema model group
4707 * *WARNING* this interface is highly subject to change
4708 *
4709 * Returns the new struture or NULL in case of error
4710 */
4711static xmlSchemaModelGroupPtr
4712xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4713 xmlSchemaTypeType type, const xmlChar **container,
4714 xmlNodePtr node)
4715{
4716 xmlSchemaModelGroupPtr ret = NULL;
4717 xmlChar buf[30];
4718
4719 if ((ctxt == NULL) || (schema == NULL))
4720 return (NULL);
4721
4722#ifdef DEBUG
4723 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004724#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004725 ret = (xmlSchemaModelGroupPtr)
4726 xmlMalloc(sizeof(xmlSchemaModelGroup));
4727 if (ret == NULL) {
4728 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4729 NULL);
4730 return (NULL);
4731 }
4732 ret->type = type;
4733 ret->annot = NULL;
4734 ret->node = node;
4735 ret->children = NULL;
4736 ret->next = NULL;
4737 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4738 if (container != NULL)
4739 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4740 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004741 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004742 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4743 } else {
4744 if (container != NULL)
4745 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4746 }
4747 if (container != NULL)
4748 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4749 /*
4750 * Add to volatile items.
4751 * TODO: this should be changed someday.
4752 */
4753 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4754 xmlFree(ret);
4755 return (NULL);
4756 }
4757 return (ret);
4758}
4759
4760
4761/**
4762 * xmlSchemaAddParticle:
4763 * @ctxt: a schema parser context
4764 * @schema: the schema being built
4765 * @node: the corresponding node in the schema doc
4766 * @min: the minOccurs
4767 * @max: the maxOccurs
4768 *
4769 * Adds an XML schema particle component.
4770 * *WARNING* this interface is highly subject to change
4771 *
4772 * Returns the new struture or NULL in case of error
4773 */
4774static xmlSchemaParticlePtr
4775xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4776 xmlNodePtr node, int min, int max)
4777{
4778 xmlSchemaParticlePtr ret = NULL;
4779 if ((ctxt == NULL) || (schema == NULL))
4780 return (NULL);
4781
4782#ifdef DEBUG
4783 fprintf(stderr, "Adding particle component\n");
4784#endif
4785 ret = (xmlSchemaParticlePtr)
4786 xmlMalloc(sizeof(xmlSchemaParticle));
4787 if (ret == NULL) {
4788 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4789 NULL);
4790 return (NULL);
4791 }
4792 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4793 ret->annot = NULL;
4794 ret->node = node;
4795 ret->minOccurs = min;
4796 ret->maxOccurs = max;
4797 ret->next = NULL;
4798 ret->children = NULL;
4799
4800 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4801 xmlFree(ret);
4802 return (NULL);
4803 }
4804 return (ret);
4805}
4806
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004807/**
4808 * xmlSchemaAddGroup:
4809 * @ctxt: a schema validation context
4810 * @schema: the schema being built
4811 * @name: the group name
4812 *
4813 * Add an XML schema Group definition
4814 *
4815 * Returns the new struture or NULL in case of error
4816 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004817static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004818xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004819 const xmlChar *name, const xmlChar *namespaceName,
4820 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004821{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004822 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004823 int val;
4824
4825 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4826 return (NULL);
4827
4828 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004829 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004830 if (schema->groupDecl == NULL)
4831 return (NULL);
4832
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004833 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004834 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004835 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004836 return (NULL);
4837 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004838 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004839 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004840 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004841 ret->node = node;
4842 ret->targetNamespace = namespaceName;
4843 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004844 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004845 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004846 XML_SCHEMAP_REDEFINED_GROUP,
4847 NULL, NULL, node,
4848 "A global model group definition with the name '%s' does already "
4849 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004850 xmlFree(ret);
4851 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004852 }
4853 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004854 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 return (ret);
4856}
4857
Daniel Veillard3646d642004-06-02 19:19:14 +00004858/**
4859 * xmlSchemaNewWildcardNs:
4860 * @ctxt: a schema validation context
4861 *
4862 * Creates a new wildcard namespace constraint.
4863 *
4864 * Returns the new struture or NULL in case of error
4865 */
4866static xmlSchemaWildcardNsPtr
4867xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4868{
4869 xmlSchemaWildcardNsPtr ret;
4870
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004871 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004872 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4873 if (ret == NULL) {
4874 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004875 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004876 }
4877 ret->value = NULL;
4878 ret->next = NULL;
4879 return (ret);
4880}
4881
4882/**
4883 * xmlSchemaAddWildcard:
4884 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004885 * @schema: a schema
4886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004887 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004888 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004889 *
4890 * Returns the new struture or NULL in case of error
4891 */
4892static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004893xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4894 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004895{
4896 xmlSchemaWildcardPtr ret = NULL;
4897
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004898 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004899 return (NULL);
4900
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004901#ifdef DEBUG
4902 fprintf(stderr, "Adding wildcard component\n");
4903#endif
4904
Daniel Veillard3646d642004-06-02 19:19:14 +00004905 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4906 if (ret == NULL) {
4907 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4908 return (NULL);
4909 }
4910 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004911 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004912 ret->minOccurs = 1;
4913 ret->maxOccurs = 1;
4914
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004915 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4916 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4917 "Failed to add a wildcard component to the list", NULL);
4918 xmlFree(ret);
4919 return (NULL);
4920 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004921 return (ret);
4922}
4923
Daniel Veillard4255d502002-04-16 15:50:10 +00004924/************************************************************************
4925 * *
4926 * Utilities for parsing *
4927 * *
4928 ************************************************************************/
4929
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004930#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004931/**
4932 * xmlGetQNameProp:
4933 * @ctxt: a schema validation context
4934 * @node: a subtree containing XML Schema informations
4935 * @name: the attribute name
4936 * @namespace: the result namespace if any
4937 *
4938 * Extract a QName Attribute value
4939 *
4940 * Returns the NCName or NULL if not found, and also update @namespace
4941 * with the namespace URI
4942 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004943static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004944xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004945 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004946{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004947 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004948 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004949 const xmlChar *ret, *prefix;
4950 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004951 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004952
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004953 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004954 attr = xmlSchemaGetPropNode(node, name);
4955 if (attr == NULL)
4956 return (NULL);
4957 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004958
Daniel Veillard4255d502002-04-16 15:50:10 +00004959 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004960 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004961
Daniel Veillardba0153a2004-04-01 10:42:31 +00004962 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004963 ns = xmlSearchNs(node->doc, node, 0);
4964 if (ns) {
4965 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4966 return (val);
4967 }
4968 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004969 ret = xmlSplitQName3(val, &len);
4970 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004972 }
4973 ret = xmlDictLookup(ctxt->dict, ret, -1);
4974 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004975
4976 ns = xmlSearchNs(node->doc, node, prefix);
4977 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4979 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004980 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004981 "The QName value '%s' has no corresponding namespace "
4982 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004983 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004984 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004985 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004986 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004987}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004988#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004989
4990/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 * xmlSchemaPValAttrNodeQNameValue:
4992 * @ctxt: a schema parser context
4993 * @schema: the schema context
4994 * @ownerDes: the designation of the parent element
4995 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004996 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004997 * @local: the resulting local part if found, the attribute value otherwise
4998 * @uri: the resulting namespace URI if found
4999 *
5000 * Extracts the local name and the URI of a QName value and validates it.
5001 * This one is intended to be used on attribute values that
5002 * should resolve to schema components.
5003 *
5004 * Returns 0, in case the QName is valid, a positive error code
5005 * if not valid and -1 if an internal error occurs.
5006 */
5007static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005008xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005009 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005010 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 xmlSchemaTypePtr ownerItem,
5012 xmlAttrPtr attr,
5013 const xmlChar *value,
5014 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005015 const xmlChar **local)
5016{
5017 const xmlChar *pref;
5018 xmlNsPtr ns;
5019 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005020
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 *uri = NULL;
5022 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005023 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005024 if (ret > 0) {
5025 xmlSchemaPSimpleTypeErr(ctxt,
5026 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5027 ownerItem, (xmlNodePtr) attr,
5028 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5029 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005030 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005031 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005032 } else if (ret < 0)
5033 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005034
5035 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005036 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005037 if (ns)
5038 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5039 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5040 /*
5041 * This one takes care of included schemas with no
5042 * target namespace.
5043 */
5044 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005045 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005046 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005047 return (0);
5048 }
5049 /*
5050 * At this point xmlSplitQName3 has to return a local name.
5051 */
5052 *local = xmlSplitQName3(value, &len);
5053 *local = xmlDictLookup(ctxt->dict, *local, -1);
5054 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005055 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5056 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005057 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005058 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005059 ownerItem, (xmlNodePtr) attr,
5060 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5061 "The value '%s' of simple type 'xs:QName' has no "
5062 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005063 return (ctxt->err);
5064 } else {
5065 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005066 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 return (0);
5068}
5069
5070/**
5071 * xmlSchemaPValAttrNodeQName:
5072 * @ctxt: a schema parser context
5073 * @schema: the schema context
5074 * @ownerDes: the designation of the owner element
5075 * @ownerItem: the owner as a schema object
5076 * @attr: the attribute node
5077 * @local: the resulting local part if found, the attribute value otherwise
5078 * @uri: the resulting namespace URI if found
5079 *
5080 * Extracts and validates the QName of an attribute value.
5081 * This one is intended to be used on attribute values that
5082 * should resolve to schema components.
5083 *
5084 * Returns 0, in case the QName is valid, a positive error code
5085 * if not valid and -1 if an internal error occurs.
5086 */
5087static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005088xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005089 xmlSchemaPtr schema,
5090 xmlChar **ownerDes,
5091 xmlSchemaTypePtr ownerItem,
5092 xmlAttrPtr attr,
5093 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005094 const xmlChar **local)
5095{
5096 const xmlChar *value;
5097
5098 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005099 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5100 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005101}
5102
5103/**
5104 * xmlSchemaPValAttrQName:
5105 * @ctxt: a schema parser context
5106 * @schema: the schema context
5107 * @ownerDes: the designation of the parent element
5108 * @ownerItem: the owner as a schema object
5109 * @ownerElem: the parent node of the attribute
5110 * @name: the name of the attribute
5111 * @local: the resulting local part if found, the attribute value otherwise
5112 * @uri: the resulting namespace URI if found
5113 *
5114 * Extracts and validates the QName of an attribute value.
5115 *
5116 * Returns 0, in case the QName is valid, a positive error code
5117 * if not valid and -1 if an internal error occurs.
5118 */
5119static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005120xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5121 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005122 xmlChar **ownerDes,
5123 xmlSchemaTypePtr ownerItem,
5124 xmlNodePtr ownerElem,
5125 const char *name,
5126 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005127 const xmlChar **local)
5128{
5129 xmlAttrPtr attr;
5130
5131 attr = xmlSchemaGetPropNode(ownerElem, name);
5132 if (attr == NULL) {
5133 *local = NULL;
5134 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005135 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005136 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005137 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5138 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005139}
5140
5141/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005142 * xmlSchemaPValAttrID:
5143 * @ctxt: a schema parser context
5144 * @schema: the schema context
5145 * @ownerDes: the designation of the parent element
5146 * @ownerItem: the owner as a schema object
5147 * @ownerElem: the parent node of the attribute
5148 * @name: the name of the attribute
5149 *
5150 * Extracts and validates the ID of an attribute value.
5151 *
5152 * Returns 0, in case the ID is valid, a positive error code
5153 * if not valid and -1 if an internal error occurs.
5154 */
5155static int
5156xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005157 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005158 xmlSchemaTypePtr ownerItem,
5159 xmlNodePtr ownerElem,
5160 const xmlChar *name)
5161{
5162 int ret;
5163 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005164 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005165
5166 value = xmlGetNoNsProp(ownerElem, name);
5167 if (value == NULL)
5168 return (0);
5169
5170 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5171 if (attr == NULL)
5172 return (-1);
5173
5174 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005175 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005176 /*
5177 * NOTE: the IDness might have already be declared in the DTD
5178 */
5179 if (attr->atype != XML_ATTRIBUTE_ID) {
5180 xmlIDPtr res;
5181 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005182
5183 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005184 * TODO: Use xmlSchemaStrip here; it's not exported at this
5185 * moment.
5186 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005187 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005188 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005189 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005190 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5191 if (res == NULL) {
5192 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 xmlSchemaPSimpleTypeErr(ctxt,
5194 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5195 ownerItem, (xmlNodePtr) attr,
5196 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5197 NULL, NULL, "Duplicate value '%s' of simple "
5198 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005199 } else
5200 attr->atype = XML_ATTRIBUTE_ID;
5201 if (strip != NULL)
5202 xmlFree(strip);
5203 }
5204 } else if (ret > 0) {
5205 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005206 xmlSchemaPSimpleTypeErr(ctxt,
5207 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5208 ownerItem, (xmlNodePtr) attr,
5209 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5210 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5211 "not a valid 'xs:NCName'",
5212 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005213 }
5214 xmlFree(value);
5215
5216 return (ret);
5217}
5218
5219/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005220 * xmlGetMaxOccurs:
5221 * @ctxt: a schema validation context
5222 * @node: a subtree containing XML Schema informations
5223 *
5224 * Get the maxOccurs property
5225 *
5226 * Returns the default if not found, or the value
5227 */
5228static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005229xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5230 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005231{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005232 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005234 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005235
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005236 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5237 if (attr == NULL)
5238 return (def);
5239 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005240
5241 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005242 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005243 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005244 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5245 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005246 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005247 val, NULL, NULL, NULL);
5248 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005249 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005250 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 }
5252
5253 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005254 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005255 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005256 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005257 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005258 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5259 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005260 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005261 val, NULL, NULL, NULL);
5262 return (def);
5263 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005264 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 ret = ret * 10 + (*cur - '0');
5266 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 }
William M. Brack76e95df2003-10-18 16:20:14 +00005268 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005270 /*
5271 * TODO: Restrict the maximal value to Integer.
5272 */
5273 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005274 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005275 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5276 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005277 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005278 val, NULL, NULL, NULL);
5279 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005280 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005281 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005282}
5283
5284/**
5285 * xmlGetMinOccurs:
5286 * @ctxt: a schema validation context
5287 * @node: a subtree containing XML Schema informations
5288 *
5289 * Get the minOccurs property
5290 *
5291 * Returns the default if not found, or the value
5292 */
5293static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005294xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005295 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005296{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005297 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005298 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005299 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005300
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005301 attr = xmlSchemaGetPropNode(node, "minOccurs");
5302 if (attr == NULL)
5303 return (def);
5304 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005305 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005306 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005307 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005308 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005310 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5311 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005312 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005313 val, NULL, NULL, NULL);
5314 return (def);
5315 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005316 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005317 ret = ret * 10 + (*cur - '0');
5318 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 }
William M. Brack76e95df2003-10-18 16:20:14 +00005320 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005321 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005322 /*
5323 * TODO: Restrict the maximal value to Integer.
5324 */
5325 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005326 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005327 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5328 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005329 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005330 val, NULL, NULL, NULL);
5331 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005332 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005334}
5335
5336/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005337 * xmlSchemaPGetBoolNodeValue:
5338 * @ctxt: a schema validation context
5339 * @ownerDes: owner designation
5340 * @ownerItem: the owner as a schema item
5341 * @node: the node holding the value
5342 *
5343 * Converts a boolean string value into 1 or 0.
5344 *
5345 * Returns 0 or 1.
5346 */
5347static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005348xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5349 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005350 xmlSchemaTypePtr ownerItem,
5351 xmlNodePtr node)
5352{
5353 xmlChar *value = NULL;
5354 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005355
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005356 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005357 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005358 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005359 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005360 * can have the following legal literals {true, false, 1, 0}.
5361 */
5362 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5363 res = 1;
5364 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5365 res = 0;
5366 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5367 res = 1;
5368 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005370 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005371 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005372 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005373 ownerItem, node,
5374 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5375 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005376 NULL, NULL, NULL);
5377 }
5378 if (value != NULL)
5379 xmlFree(value);
5380 return (res);
5381}
5382
5383/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005384 * xmlGetBooleanProp:
5385 * @ctxt: a schema validation context
5386 * @node: a subtree containing XML Schema informations
5387 * @name: the attribute name
5388 * @def: the default value
5389 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005390 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 *
5392 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005393 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005394 */
5395static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005396xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5397 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005398 xmlSchemaTypePtr ownerItem,
5399 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005400 const char *name, int def)
5401{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005402 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005403
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005404 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005405 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005406 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005407 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005408 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005409 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005410 * can have the following legal literals {true, false, 1, 0}.
5411 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005412 if (xmlStrEqual(val, BAD_CAST "true"))
5413 def = 1;
5414 else if (xmlStrEqual(val, BAD_CAST "false"))
5415 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005416 else if (xmlStrEqual(val, BAD_CAST "1"))
5417 def = 1;
5418 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005419 def = 0;
5420 else {
5421 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005422 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005423 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005424 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005425 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5426 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005427 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005428 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005429}
5430
5431/************************************************************************
5432 * *
5433 * Shema extraction from an Infoset *
5434 * *
5435 ************************************************************************/
5436static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5437 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005438 xmlNodePtr node,
5439 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005440static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5441 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005442 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005443 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005444 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005445static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5446 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005447 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005448 xmlNodePtr node,
5449 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005450static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5451 ctxt,
5452 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005453 xmlNodePtr node,
5454 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005455static xmlSchemaAttributeGroupPtr
5456xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005457 xmlSchemaPtr schema, xmlNodePtr node,
5458 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005459static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5460 xmlSchemaPtr schema,
5461 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005462static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5464 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005465
5466/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005467 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005468 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005469 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005470 * @ownerDes: the designation of the parent element
5471 * @ownerItem: the schema object owner if existent
5472 * @attr: the schema attribute node being validated
5473 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005474 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005475 *
5476 * Validates a value against the given built-in type.
5477 * This one is intended to be used internally for validation
5478 * of schema attribute values during parsing of the schema.
5479 *
5480 * Returns 0 if the value is valid, a positive error code
5481 * number otherwise and -1 in case of an internal or API error.
5482 */
5483static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005484xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5485 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5486 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005487 xmlAttrPtr attr,
5488 const xmlChar *value,
5489 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005490{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005491
5492 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005493
5494 /*
5495 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5496 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005497 */
5498 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005499 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005500 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5501 PERROR_INT("xmlSchemaPValAttrNodeValue",
5502 "the given type is not a built-in type");
5503 return (-1);
5504 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005505 switch (type->builtInType) {
5506 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005507 case XML_SCHEMAS_QNAME:
5508 case XML_SCHEMAS_ANYURI:
5509 case XML_SCHEMAS_TOKEN:
5510 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5512 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005513 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005514 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 PERROR_INT("xmlSchemaPValAttrNodeValue",
5516 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005517 return (-1);
5518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005519 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005520 /*
5521 * TODO: Should we use the S4S error codes instead?
5522 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005523 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005524 PERROR_INT("xmlSchemaPValAttrNodeValue",
5525 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005526 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005527 } else if (ret > 0) {
5528 if (VARIETY_LIST(type))
5529 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5530 else
5531 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5532 xmlSchemaPSimpleTypeErr(pctxt,
5533 ret, ownerItem, (xmlNodePtr) attr,
5534 type, NULL, value, NULL, NULL, NULL);
5535 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005536 return (ret);
5537}
5538
5539/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005540 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 * @ctxt: a schema parser context
5543 * @ownerDes: the designation of the parent element
5544 * @ownerItem: the schema object owner if existent
5545 * @attr: the schema attribute node being validated
5546 * @type: the built-in type to be validated against
5547 * @value: the resulting value if any
5548 *
5549 * Extracts and validates a value against the given built-in type.
5550 * This one is intended to be used internally for validation
5551 * of schema attribute values during parsing of the schema.
5552 *
5553 * Returns 0 if the value is valid, a positive error code
5554 * number otherwise and -1 in case of an internal or API error.
5555 */
5556static int
5557xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5558 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 xmlSchemaTypePtr ownerItem,
5560 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 xmlSchemaTypePtr type,
5562 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005563{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005564 const xmlChar *val;
5565
5566 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005567 return (-1);
5568
Daniel Veillardc0826a72004-08-10 14:17:33 +00005569 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5570 if (value != NULL)
5571 *value = val;
5572
5573 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005574 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575}
5576
5577/**
5578 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005579 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005580 * @ctxt: a schema parser context
5581 * @node: the element node of the attribute
5582 * @ownerDes: the designation of the parent element
5583 * @ownerItem: the schema object owner if existent
5584 * @ownerElem: the owner element node
5585 * @name: the name of the schema attribute node
5586 * @type: the built-in type to be validated against
5587 * @value: the resulting value if any
5588 *
5589 * Extracts and validates a value against the given built-in type.
5590 * This one is intended to be used internally for validation
5591 * of schema attribute values during parsing of the schema.
5592 *
5593 * Returns 0 if the value is valid, a positive error code
5594 * number otherwise and -1 in case of an internal or API error.
5595 */
5596static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005597xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005598 xmlChar **ownerDes,
5599 xmlSchemaTypePtr ownerItem,
5600 xmlNodePtr ownerElem,
5601 const char *name,
5602 xmlSchemaTypePtr type,
5603 const xmlChar **value)
5604{
5605 xmlAttrPtr attr;
5606
5607 if ((ctxt == NULL) || (type == NULL)) {
5608 if (value != NULL)
5609 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005610 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005611 }
5612 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5613 if (value != NULL)
5614 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005615 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005616 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005617 "Internal error: xmlSchemaPValAttr, the given "
5618 "type '%s' is not a built-in type.\n",
5619 type->name, NULL);
5620 return (-1);
5621 }
5622 attr = xmlSchemaGetPropNode(ownerElem, name);
5623 if (attr == NULL) {
5624 if (value != NULL)
5625 *value = NULL;
5626 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005627 }
5628 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 type, value));
5630}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005631
5632static int
5633xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5634 xmlSchemaPtr schema,
5635 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005636 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005637 const xmlChar *namespaceName)
5638{
5639 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005640 return (1);
5641 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5642 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005643 if (pctxt->localImports != NULL) {
5644 int i;
5645 for (i = 0; i < pctxt->nbLocalImports; i++)
5646 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5647 return (1);
5648 }
5649 if (namespaceName == NULL)
5650 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005651 NULL, (xmlSchemaTypePtr) item, node,
5652 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005653 "namespace are not valid, since not indicated by an import "
5654 "statement", NULL);
5655 else
5656 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005657 NULL, (xmlSchemaTypePtr) item, node,
5658 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005659 "namespace '%s' are not valid, since not indicated by an import "
5660 "statement", namespaceName);
5661 return (0);
5662}
5663
Daniel Veillardc0826a72004-08-10 14:17:33 +00005664/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005665 * xmlSchemaParseAttrDecls:
5666 * @ctxt: a schema validation context
5667 * @schema: the schema being built
5668 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005669 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 *
5671 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005672 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005673 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5674 */
5675static xmlNodePtr
5676xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5677 xmlNodePtr child, xmlSchemaTypePtr type)
5678{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005679 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005680
Daniel Veillard4255d502002-04-16 15:50:10 +00005681 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005682 (IS_SCHEMA(child, "attributeGroup"))) {
5683 attr = NULL;
5684 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005685 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005686 } else if (IS_SCHEMA(child, "attributeGroup")) {
5687 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005688 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005689 }
5690 if (attr != NULL) {
5691 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005692 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5693 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5694 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005695 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005696 lastattr = attr;
5697 } else {
5698 lastattr->next = attr;
5699 lastattr = attr;
5700 }
5701 }
5702 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005703 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005704 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005705}
5706
5707/**
5708 * xmlSchemaParseAnnotation:
5709 * @ctxt: a schema validation context
5710 * @schema: the schema being built
5711 * @node: a subtree containing XML Schema informations
5712 *
5713 * parse a XML schema Attrribute declaration
5714 * *WARNING* this interface is highly subject to change
5715 *
William M. Bracke7091952004-05-11 15:09:58 +00005716 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005717 * 1 in case of success.
5718 */
5719static xmlSchemaAnnotPtr
5720xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5721 xmlNodePtr node)
5722{
5723 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 xmlNodePtr child = NULL;
5725 xmlAttrPtr attr;
5726 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005727
Daniel Veillardc0826a72004-08-10 14:17:33 +00005728 /*
5729 * INFO: S4S completed.
5730 */
5731 /*
5732 * id = ID
5733 * {any attributes with non-schema namespace . . .}>
5734 * Content: (appinfo | documentation)*
5735 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005736 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5737 return (NULL);
5738 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 attr = node->properties;
5740 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005741 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005742 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005743 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005744 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005745
5746 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5748 NULL, NULL, attr);
5749 }
5750 attr = attr->next;
5751 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005752 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753 /*
5754 * And now for the children...
5755 */
5756 child = node->children;
5757 while (child != NULL) {
5758 if (IS_SCHEMA(child, "appinfo")) {
5759 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005760 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005761 * source = anyURI
5762 * {any attributes with non-schema namespace . . .}>
5763 * Content: ({any})*
5764 */
5765 attr = child->properties;
5766 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005767 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005768 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005770 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005771
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005772 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005773 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5774 NULL, NULL, attr);
5775 }
5776 attr = attr->next;
5777 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005778 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5779 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005780 child = child->next;
5781 } else if (IS_SCHEMA(child, "documentation")) {
5782 /* TODO: make available the content of "documentation". */
5783 /*
5784 * source = anyURI
5785 * {any attributes with non-schema namespace . . .}>
5786 * Content: ({any})*
5787 */
5788 attr = child->properties;
5789 while (attr != NULL) {
5790 if (attr->ns == NULL) {
5791 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005792 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5794 NULL, NULL, attr);
5795 }
5796 } else {
5797 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5798 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5799 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005800
5801 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005802 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5803 NULL, NULL, attr);
5804 }
5805 }
5806 attr = attr->next;
5807 }
5808 /*
5809 * Attribute "xml:lang".
5810 */
5811 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5812 if (attr != NULL)
5813 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005814 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 child = child->next;
5816 } else {
5817 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005818 xmlSchemaPContentErr(ctxt,
5819 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005820 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5821 barked = 1;
5822 child = child->next;
5823 }
5824 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005825
Daniel Veillard4255d502002-04-16 15:50:10 +00005826 return (ret);
5827}
5828
5829/**
5830 * xmlSchemaParseFacet:
5831 * @ctxt: a schema validation context
5832 * @schema: the schema being built
5833 * @node: a subtree containing XML Schema informations
5834 *
5835 * parse a XML schema Facet declaration
5836 * *WARNING* this interface is highly subject to change
5837 *
5838 * Returns the new type structure or NULL in case of error
5839 */
5840static xmlSchemaFacetPtr
5841xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005842 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005843{
5844 xmlSchemaFacetPtr facet;
5845 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005846 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005847
5848 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5849 return (NULL);
5850
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005851 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005852 if (facet == NULL) {
5853 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5854 return (NULL);
5855 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005857 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005858 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005859 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5860 "Facet %s has no value\n", node->name, NULL);
5861 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005862 return (NULL);
5863 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005864 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005865 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005866 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005867 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005868 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005869 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005870 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005871 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005872 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005873 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005874 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005875 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005877 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005878 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005879 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005880 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005881 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005882 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005883 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005884 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005885 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5886 } else if (IS_SCHEMA(node, "minLength")) {
5887 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5888 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005889 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5890 "Unknown facet type %s\n", node->name, NULL);
5891 xmlSchemaFreeFacet(facet);
5892 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005893 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005894 xmlSchemaPValAttrID(ctxt, NULL,
5895 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005896 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005897 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5898 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5899 const xmlChar *fixed;
5900
5901 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5902 if (fixed != NULL) {
5903 if (xmlStrEqual(fixed, BAD_CAST "true"))
5904 facet->fixed = 1;
5905 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005906 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005907 child = node->children;
5908
5909 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005910 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5911 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005912 }
5913 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005914 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5915 "Facet %s has unexpected child content\n",
5916 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005917 }
5918 return (facet);
5919}
5920
5921/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005922 * xmlSchemaParseWildcardNs:
5923 * @ctxt: a schema parser context
5924 * @wildc: the wildcard, already created
5925 * @node: a subtree containing XML Schema informations
5926 *
5927 * Parses the attribute "processContents" and "namespace"
5928 * of a xsd:anyAttribute and xsd:any.
5929 * *WARNING* this interface is highly subject to change
5930 *
5931 * Returns 0 if everything goes fine, a positive error code
5932 * if something is not valid and -1 if an internal error occurs.
5933 */
5934static int
5935xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5936 xmlSchemaPtr schema,
5937 xmlSchemaWildcardPtr wildc,
5938 xmlNodePtr node)
5939{
5940 const xmlChar *pc, *ns, *dictnsItem;
5941 int ret = 0;
5942 xmlChar *nsItem;
5943 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5944 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005945
Daniel Veillardc0826a72004-08-10 14:17:33 +00005946 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5947 if ((pc == NULL)
5948 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5949 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5950 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5951 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5952 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5953 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5954 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005955 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005956 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005957 NULL, node,
5958 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005959 NULL, NULL, NULL);
5960 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005961 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005962 }
5963 /*
5964 * Build the namespace constraints.
5965 */
5966 attr = xmlSchemaGetPropNode(node, "namespace");
5967 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005968 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 wildc->any = 1;
5970 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5971 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005972 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005973 return (-1);
5974 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005975 wildc->negNsSet->value = schema->targetNamespace;
5976 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005977 const xmlChar *end, *cur;
5978
5979 cur = ns;
5980 do {
5981 while (IS_BLANK_CH(*cur))
5982 cur++;
5983 end = cur;
5984 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5985 end++;
5986 if (end == cur)
5987 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005988 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005989 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5990 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005992 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005993 NULL, (xmlNodePtr) attr,
5994 NULL,
5995 "((##any | ##other) | List of (xs:anyURI | "
5996 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005997 nsItem, NULL, NULL, NULL);
5998 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5999 } else {
6000 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6001 dictnsItem = schema->targetNamespace;
6002 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6003 dictnsItem = NULL;
6004 } else {
6005 /*
6006 * Validate the item (anyURI).
6007 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006008 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006009 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6010 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6011 }
6012 /*
6013 * Avoid dublicate namespaces.
6014 */
6015 tmp = wildc->nsSet;
6016 while (tmp != NULL) {
6017 if (dictnsItem == tmp->value)
6018 break;
6019 tmp = tmp->next;
6020 }
6021 if (tmp == NULL) {
6022 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6023 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006024 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006025 return (-1);
6026 }
6027 tmp->value = dictnsItem;
6028 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006029 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006030 wildc->nsSet = tmp;
6031 else
6032 lastNs->next = tmp;
6033 lastNs = tmp;
6034 }
6035
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006036 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006037 xmlFree(nsItem);
6038 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006039 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006040 }
6041 return (ret);
6042}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006043
6044static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006045xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6046 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006047 xmlNodePtr node,
6048 int minOccurs,
6049 int maxOccurs) {
6050
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 if ((maxOccurs == 0) && ( minOccurs == 0))
6052 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006053 if (maxOccurs != UNBOUNDED) {
6054 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006055 * TODO: Maybe we should better not create the particle,
6056 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006057 * content model.
6058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006059 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006060 * 3.9.6 Schema Component Constraint: Particle Correct
6061 *
6062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006063 if (maxOccurs < 1) {
6064 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006065 * 2.2 {max occurs} must be greater than or equal to 1.
6066 */
6067 xmlSchemaPCustomAttrErr(ctxt,
6068 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006069 NULL, NULL,
6070 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006071 "The value must be greater than or equal to 1");
6072 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6073 } else if (minOccurs > maxOccurs) {
6074 /*
6075 * 2.1 {min occurs} must not be greater than {max occurs}.
6076 */
6077 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006078 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006079 NULL, NULL,
6080 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006081 "The value must not be greater than the value of 'maxOccurs'");
6082 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6083 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006084 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006085 return (0);
6086}
6087
Daniel Veillardc0826a72004-08-10 14:17:33 +00006088/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006089 * xmlSchemaParseAny:
6090 * @ctxt: a schema validation context
6091 * @schema: the schema being built
6092 * @node: a subtree containing XML Schema informations
6093 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006094 * Parsea a XML schema <any> element. A particle and wildcard
6095 * will be created (except if minOccurs==maxOccurs==0, in this case
6096 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006097 * *WARNING* this interface is highly subject to change
6098 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006099 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006102xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6103 xmlNodePtr node)
6104{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006107 xmlSchemaWildcardPtr wild;
6108 int min, max;
6109 xmlAttrPtr attr;
6110 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006111
6112 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6113 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006114 /*
6115 * Check for illegal attributes.
6116 */
6117 attr = node->properties;
6118 while (attr != NULL) {
6119 if (attr->ns == NULL) {
6120 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6121 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6122 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6123 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6124 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006125 xmlSchemaPIllegalAttrErr(ctxt,
6126 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6127 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006128 }
6129 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006130 xmlSchemaPIllegalAttrErr(ctxt,
6131 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6132 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006133 }
6134 attr = attr->next;
6135 }
6136 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6137 /*
6138 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006139 */
6140 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6141 "(xs:nonNegativeInteger | unbounded)");
6142 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6143 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006144 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6145 /*
6146 * Create & parse the wildcard.
6147 */
6148 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6149 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006150 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006151 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006152 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006153 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006154 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006155 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006156 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006157 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 }
6160 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006161 xmlSchemaPContentErr(ctxt,
6162 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006163 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006164 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006165 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006166 /*
6167 * No component if minOccurs==maxOccurs==0.
6168 */
6169 if ((min == 0) && (max == 0)) {
6170 /* Don't free the wildcard, since it's already on the list. */
6171 return (NULL);
6172 }
6173 /*
6174 * Create the particle.
6175 */
6176 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6177 if (particle == NULL)
6178 return (NULL);
6179 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006180 wild->minOccurs = min;
6181 wild->maxOccurs = max;
6182 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006183
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006184 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006185}
6186
6187/**
6188 * xmlSchemaParseNotation:
6189 * @ctxt: a schema validation context
6190 * @schema: the schema being built
6191 * @node: a subtree containing XML Schema informations
6192 *
6193 * parse a XML schema Notation declaration
6194 *
6195 * Returns the new structure or NULL in case of error
6196 */
6197static xmlSchemaNotationPtr
6198xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006199 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006200{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006201 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlSchemaNotationPtr ret;
6203 xmlNodePtr child = NULL;
6204
6205 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6206 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006207 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006208 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006209 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6210 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006211 return (NULL);
6212 }
6213 ret = xmlSchemaAddNotation(ctxt, schema, name);
6214 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006215 return (NULL);
6216 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006217 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006218
6219 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6220 node, BAD_CAST "id");
6221
6222 if (IS_SCHEMA(child, "annotation")) {
6223 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6224 child = child->next;
6225 }
6226
Daniel Veillard4255d502002-04-16 15:50:10 +00006227 child = node->children;
6228 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006231 }
6232 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006233 xmlSchemaPContentErr(ctxt,
6234 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006235 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006236 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 }
6238
6239 return (ret);
6240}
6241
6242/**
6243 * xmlSchemaParseAnyAttribute:
6244 * @ctxt: a schema validation context
6245 * @schema: the schema being built
6246 * @node: a subtree containing XML Schema informations
6247 *
6248 * parse a XML schema AnyAttrribute declaration
6249 * *WARNING* this interface is highly subject to change
6250 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006251 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006252 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006253static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006254xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6255 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006256{
Daniel Veillard3646d642004-06-02 19:19:14 +00006257 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006258 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006259 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006260
6261 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6262 return (NULL);
6263
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006264 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6265 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006266 if (ret == NULL) {
6267 return (NULL);
6268 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006269 /*
6270 * Check for illegal attributes.
6271 */
6272 attr = node->properties;
6273 while (attr != NULL) {
6274 if (attr->ns == NULL) {
6275 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6276 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6277 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006278 xmlSchemaPIllegalAttrErr(ctxt,
6279 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6280 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006281 }
6282 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283 xmlSchemaPIllegalAttrErr(ctxt,
6284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6285 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006286 }
6287 attr = attr->next;
6288 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006289 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6290 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006291 /*
6292 * Parse the namespace list.
6293 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006296 /*
6297 * And now for the children...
6298 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006299 child = node->children;
6300 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006301 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6302 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006303 }
6304 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006306 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006307 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006308 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006309 }
6310
6311 return (ret);
6312}
6313
6314
6315/**
6316 * xmlSchemaParseAttribute:
6317 * @ctxt: a schema validation context
6318 * @schema: the schema being built
6319 * @node: a subtree containing XML Schema informations
6320 *
6321 * parse a XML schema Attrribute declaration
6322 * *WARNING* this interface is highly subject to change
6323 *
William M. Bracke7091952004-05-11 15:09:58 +00006324 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006325 */
6326static xmlSchemaAttributePtr
6327xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006328 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006329{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 const xmlChar *name, *attrValue;
6331 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006332 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006334 xmlAttrPtr attr, nameAttr;
6335 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006336
6337 /*
6338 * Note that the w3c spec assumes the schema to be validated with schema
6339 * for schemas beforehand.
6340 *
6341 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006342 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006343
6344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6345 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006346 attr = xmlSchemaGetPropNode(node, "ref");
6347 nameAttr = xmlSchemaGetPropNode(node, "name");
6348
6349 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006351 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006352 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006353 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006354 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6355 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006356 "One of the attributes 'ref' or 'name' must be present");
6357 return (NULL);
6358 }
6359 if ((topLevel) || (attr == NULL)) {
6360 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006361 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6362 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006363 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006365 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 isRef = 1;
6367
Daniel Veillardc0826a72004-08-10 14:17:33 +00006368 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006369 char buf[50];
6370 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006371
6372 /*
6373 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 */
6375 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6376 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6377 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006379 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006380 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006381 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006382 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006383 if (ret == NULL) {
6384 if (repName != NULL)
6385 xmlFree(repName);
6386 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006387 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006388 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6389 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006390 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006391 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006392 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6393 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006394 /*
6395 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6396 */
6397 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006398 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6399 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006400 "ref", "name");
6401 /*
6402 * Check for illegal attributes.
6403 */
6404 attr = node->properties;
6405 while (attr != NULL) {
6406 if (attr->ns == NULL) {
6407 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6408 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006409 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006410 * 3.2.3 : 3.2
6411 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006412 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006414 xmlSchemaPIllegalAttrErr(ctxt,
6415 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006416 (xmlSchemaTypePtr) ret, attr);
6417 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6418 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6419 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006420 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6421 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006422 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006423 xmlSchemaPIllegalAttrErr(ctxt,
6424 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6425 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006426 }
6427 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006428 xmlSchemaPIllegalAttrErr(ctxt,
6429 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6430 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006431 }
6432 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006433 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006434 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006435 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006436
Daniel Veillardc0826a72004-08-10 14:17:33 +00006437 /*
6438 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006439 */
6440 if (xmlSchemaPValAttrNode(ctxt,
6441 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006442 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6443 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006444 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006445 /*
6446 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006448 /*
6449 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6450 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006451 */
6452 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006453 xmlSchemaPSimpleTypeErr(ctxt,
6454 XML_SCHEMAP_NO_XMLNS,
6455 NULL, (xmlNodePtr) nameAttr,
6456 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6457 "The value of type 'xs:NCName' must not match 'xmlns'",
6458 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006459 if (repName != NULL)
6460 xmlFree(repName);
6461 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006462 }
6463 /*
6464 * Evaluate the target namespace
6465 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006466 if (topLevel) {
6467 ns = schema->targetNamespace;
6468 } else {
6469 attr = xmlSchemaGetPropNode(node, "form");
6470 if (attr != NULL) {
6471 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6472 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6473 ns = schema->targetNamespace;
6474 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 xmlSchemaPSimpleTypeErr(ctxt,
6476 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6477 NULL, (xmlNodePtr) attr,
6478 NULL, "(qualified | unqualified)",
6479 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006480 }
6481 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482 ns = schema->targetNamespace;
6483 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006484 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 if (ret == NULL) {
6486 if (repName != NULL)
6487 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006488 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006489 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006491 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 if (topLevel)
6493 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006494 /*
6495 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6496 * TODO: Move this to the component layer.
6497 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006498 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006499 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 XML_SCHEMAP_NO_XSI,
6501 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502 "The target namespace must not match '%s'",
6503 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006504 }
6505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006506 * Check for illegal attributes.
6507 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006508 attr = node->properties;
6509 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006510 if (attr->ns == NULL) {
6511 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6512 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6513 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6515 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006516 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006517 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6518 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006519 xmlSchemaPIllegalAttrErr(ctxt,
6520 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6521 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 }
6523 }
6524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006525 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6526 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 }
6528 attr = attr->next;
6529 }
6530 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 node, "type", &ret->typeNs, &ret->typeName);
6532 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006533 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6534 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006535 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006537 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6539 if (ret->defValue != NULL)
6540 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006541 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006542 * Attribute "default".
6543 */
6544 attr = xmlSchemaGetPropNode(node, "default");
6545 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 */
6550 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6551 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6552 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6553 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6555 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006557 /*
6558 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 */
6560 attr = xmlSchemaGetPropNode(node, "use");
6561 if (attr != NULL) {
6562 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6563 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6564 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6565 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6566 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6567 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6568 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6569 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006570 xmlSchemaPSimpleTypeErr(ctxt,
6571 XML_SCHEMAP_INVALID_ATTR_USE,
6572 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6573 NULL, "(optional | prohibited | required)",
6574 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006575 } else
6576 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006577 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006578 * 3.2.3 : 2
6579 * If default and use are both present, use must have
6580 * the actual value optional.
6581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006582 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6583 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006584 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006585 xmlSchemaPSimpleTypeErr(ctxt,
6586 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6587 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6588 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006589 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006590 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006591 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006592 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006593 /*
6594 * And now for the children...
6595 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006596 child = node->children;
6597 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006598 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6599 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006600 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006601 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006602 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006603 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006604 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006605 * 3.2.3 : 3.2
6606 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006607 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608 */
6609 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6610 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6611 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006612 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006613 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6614 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006616 }
6617 } else {
6618 if (IS_SCHEMA(child, "simpleType")) {
6619 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006621 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006622 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006623 */
6624 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6625 &repName, (xmlSchemaTypePtr) ret, node, child,
6626 "The attribute 'type' and the <simpleType> child "
6627 "are mutually exclusive", NULL);
6628 } else
6629 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6630 child = child->next;
6631 }
6632 if (child != NULL)
6633 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6634 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6635 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006636 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006637 /*
6638 * Cleanup.
6639 */
6640 if (repName != NULL)
6641 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006642 return (ret);
6643}
6644
6645/**
6646 * xmlSchemaParseAttributeGroup:
6647 * @ctxt: a schema validation context
6648 * @schema: the schema being built
6649 * @node: a subtree containing XML Schema informations
6650 *
6651 * parse a XML schema Attribute Group declaration
6652 * *WARNING* this interface is highly subject to change
6653 *
6654 * Returns the attribute group or NULL in case of error.
6655 */
6656static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006657xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006658 xmlSchemaPtr schema, xmlNodePtr node,
6659 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006660{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006662 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006663 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006664 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006665 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006666
6667 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6668 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006669
6670 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006671 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006672 if ((topLevel) || (attr == NULL)) {
6673 /*
6674 * Parse as an attribute group definition.
6675 * Note that those are allowed at top level only.
6676 */
6677 if (nameAttr == NULL) {
6678 xmlSchemaPMissingAttrErr(ctxt,
6679 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006680 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006681 return (NULL);
6682 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006683 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006684 * (xmlNodePtr) nameAttr);
6685 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006686 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006687 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006688 */
6689 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006690 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006691 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6692 return (NULL);
6693 }
6694 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6695 if (ret == NULL)
6696 return (NULL);
6697 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6698 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6699 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006700 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006701 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006702 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006703 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006704
6705 /*
6706 * Parse as an attribute group definition reference.
6707 */
6708 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 xmlSchemaPMissingAttrErr(ctxt,
6710 XML_SCHEMAP_S4S_ATTR_MISSING,
6711 NULL, node, "ref", NULL);
6712 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006713 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006714 NULL, NULL, attr, &refNs,&ref);
6715
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006716 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006717 name = (const xmlChar *) buf;
6718 if (name == NULL) {
6719 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6720 "attribute group definition reference", node);
6721 return (NULL);
6722 }
6723 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6724 if (ret == NULL)
6725 return (NULL);
6726 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6727 ret->ref = ref;
6728 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006729 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006730 xmlSchemaCheckReference(ctxt, schema, node,
6731 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006732 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006733 /*
6734 * Check for illegal attributes.
6735 */
6736 attr = node->properties;
6737 while (attr != NULL) {
6738 if (attr->ns == NULL) {
6739 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6740 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006741 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006742 {
6743 xmlSchemaPIllegalAttrErr(ctxt,
6744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6745 NULL, NULL, attr);
6746 }
6747 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6748 xmlSchemaPIllegalAttrErr(ctxt,
6749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6750 NULL, NULL, attr);
6751 }
6752 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006753 }
6754 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006755 /*
6756 * And now for the children...
6757 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006758 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006759 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006760 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006761 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006762 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6763 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006764 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006765 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006766 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006767 if (IS_SCHEMA(child, "anyAttribute")) {
6768 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6769 child = child->next;
6770 }
6771 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006772 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006773 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006774 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6775 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006776 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006777 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006778 ctxt->container = oldcontainer;
6779 return (ret);
6780}
6781
6782/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006783 * xmlSchemaPValAttrFormDefault:
6784 * @value: the value
6785 * @flags: the flags to be modified
6786 * @flagQualified: the specific flag for "qualified"
6787 *
6788 * Returns 0 if the value is valid, 1 otherwise.
6789 */
6790static int
6791xmlSchemaPValAttrFormDefault(const xmlChar *value,
6792 int *flags,
6793 int flagQualified)
6794{
6795 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6796 if ((*flags & flagQualified) == 0)
6797 *flags |= flagQualified;
6798 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006799 return (1);
6800
William M. Brack2f2a6632004-08-20 23:09:47 +00006801 return (0);
6802}
6803
6804/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 * xmlSchemaPValAttrBlockFinal:
6806 * @value: the value
6807 * @flags: the flags to be modified
6808 * @flagAll: the specific flag for "#all"
6809 * @flagExtension: the specific flag for "extension"
6810 * @flagRestriction: the specific flag for "restriction"
6811 * @flagSubstitution: the specific flag for "substitution"
6812 * @flagList: the specific flag for "list"
6813 * @flagUnion: the specific flag for "union"
6814 *
6815 * Validates the value of the attribute "final" and "block". The value
6816 * is converted into the specified flag values and returned in @flags.
6817 *
6818 * Returns 0 if the value is valid, 1 otherwise.
6819 */
6820
6821static int
6822xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006823 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824 int flagAll,
6825 int flagExtension,
6826 int flagRestriction,
6827 int flagSubstitution,
6828 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006829 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006830{
6831 int ret = 0;
6832
6833 /*
6834 * TODO: This does not check for dublicate entries.
6835 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006836 if ((flags == NULL) || (value == NULL))
6837 return (-1);
6838 if (value[0] == 0)
6839 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006840 if (xmlStrEqual(value, BAD_CAST "#all")) {
6841 if (flagAll != -1)
6842 *flags |= flagAll;
6843 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006844 if (flagExtension != -1)
6845 *flags |= flagExtension;
6846 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006847 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006848 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006849 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006851 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 *flags |= flagUnion;
6854 }
6855 } else {
6856 const xmlChar *end, *cur = value;
6857 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006858
Daniel Veillardc0826a72004-08-10 14:17:33 +00006859 do {
6860 while (IS_BLANK_CH(*cur))
6861 cur++;
6862 end = cur;
6863 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6864 end++;
6865 if (end == cur)
6866 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006867 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006868 if (xmlStrEqual(item, BAD_CAST "extension")) {
6869 if (flagExtension != -1) {
6870 if ((*flags & flagExtension) == 0)
6871 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006872 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006873 ret = 1;
6874 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6875 if (flagRestriction != -1) {
6876 if ((*flags & flagRestriction) == 0)
6877 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006878 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006879 ret = 1;
6880 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6881 if (flagSubstitution != -1) {
6882 if ((*flags & flagSubstitution) == 0)
6883 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006884 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006885 ret = 1;
6886 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6887 if (flagList != -1) {
6888 if ((*flags & flagList) == 0)
6889 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006890 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006891 ret = 1;
6892 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6893 if (flagUnion != -1) {
6894 if ((*flags & flagUnion) == 0)
6895 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006896 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006897 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006898 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006899 ret = 1;
6900 if (item != NULL)
6901 xmlFree(item);
6902 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006903 } while ((ret == 0) && (*cur != 0));
6904 }
6905
Daniel Veillardc0826a72004-08-10 14:17:33 +00006906 return (ret);
6907}
6908
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006909static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006910xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006911 xmlSchemaIDCPtr idc,
6912 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006913 xmlAttrPtr attr,
6914 int isField)
6915{
6916 xmlNodePtr node;
6917
6918 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006919 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006920 * Schema Component Constraint: Selector Value OK
6921 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006922 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006923 * in [XPath].
6924 */
6925 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006926 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006927 XML_SCHEMAP_INTERNAL,
6928 "Internal error: xmlSchemaCheckCSelectorXPath, "
6929 "the selector is not specified.\n", NULL, NULL);
6930 return (-1);
6931 }
6932 if (attr == NULL)
6933 node = idc->node;
6934 else
6935 node = (xmlNodePtr) attr;
6936 if (selector->xpath == NULL) {
6937 xmlSchemaPCustomErr(ctxt,
6938 /* 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 of the selector is not valid", NULL);
6942 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6943 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006944 const xmlChar **nsArray = NULL;
6945 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006946 /*
6947 * Compile the XPath expression.
6948 */
6949 /*
6950 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006951 * TODO: Call xmlPatterncompile with different options for selector/
6952 * field.
6953 */
6954 nsList = xmlGetNsList(attr->doc, attr->parent);
6955 /*
6956 * Build an array of prefixes and namespaces.
6957 */
6958 if (nsList != NULL) {
6959 int i, count = 0;
6960 xmlNsPtr ns;
6961
6962 for (i = 0; nsList[i] != NULL; i++)
6963 count++;
6964
6965 nsArray = (const xmlChar **) xmlMalloc(
6966 (count * 2 + 1) * sizeof(const xmlChar *));
6967 if (nsArray == NULL) {
6968 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6969 NULL);
6970 return (-1);
6971 }
6972 for (i = 0; i < count; i++) {
6973 ns = nsList[i];
6974 nsArray[2 * i] = nsList[i]->href;
6975 nsArray[2 * i + 1] = nsList[i]->prefix;
6976 }
6977 nsArray[count * 2] = NULL;
6978 xmlFree(nsList);
6979 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006980 /*
6981 * TODO: Differentiate between "selector" and "field".
6982 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006983 if (isField)
6984 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006985 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006986 else
6987 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006988 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006989 if (nsArray != NULL)
6990 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006991
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006992 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006993 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006994 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006995 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6996 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006997 "The XPath expression '%s' could not be "
6998 "compiled", selector->xpath);
6999 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007000 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007001 }
7002 return (0);
7003}
7004
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007005#define ADD_ANNOTATION(annot) \
7006 xmlSchemaAnnotPtr cur = item->annot; \
7007 if (item->annot == NULL) { \
7008 item->annot = annot; \
7009 return (annot); \
7010 } \
7011 cur = item->annot; \
7012 if (cur->next != NULL) { \
7013 cur = cur->next; \
7014 } \
7015 cur->next = annot;
7016
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007017/**
7018 * xmlSchemaAssignAnnotation:
7019 * @item: the schema component
7020 * @annot: the annotation
7021 *
7022 * Adds the annotation to the given schema component.
7023 *
7024 * Returns the given annotaion.
7025 */
7026static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007027xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7028 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007029{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007030 if ((annItem == NULL) || (annot == NULL))
7031 return (NULL);
7032 switch (annItem->type) {
7033 case XML_SCHEMA_TYPE_ELEMENT: {
7034 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7035 ADD_ANNOTATION(annot)
7036 }
7037 break;
7038 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7039 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7040 ADD_ANNOTATION(annot)
7041 }
7042 break;
7043 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7044 case XML_SCHEMA_TYPE_ANY: {
7045 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7046 ADD_ANNOTATION(annot)
7047 }
7048 break;
7049 case XML_SCHEMA_TYPE_PARTICLE:
7050 case XML_SCHEMA_TYPE_IDC_KEY:
7051 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007052 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007053 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7054 ADD_ANNOTATION(annot)
7055 }
7056 break;
7057 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7058 xmlSchemaAttributeGroupPtr item =
7059 (xmlSchemaAttributeGroupPtr) annItem;
7060 ADD_ANNOTATION(annot)
7061 }
7062 break;
7063 case XML_SCHEMA_TYPE_NOTATION: {
7064 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7065 ADD_ANNOTATION(annot)
7066 }
7067 break;
7068 case XML_SCHEMA_FACET_MININCLUSIVE:
7069 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7070 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7071 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7072 case XML_SCHEMA_FACET_TOTALDIGITS:
7073 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7074 case XML_SCHEMA_FACET_PATTERN:
7075 case XML_SCHEMA_FACET_ENUMERATION:
7076 case XML_SCHEMA_FACET_WHITESPACE:
7077 case XML_SCHEMA_FACET_LENGTH:
7078 case XML_SCHEMA_FACET_MAXLENGTH:
7079 case XML_SCHEMA_FACET_MINLENGTH: {
7080 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7081 ADD_ANNOTATION(annot)
7082 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007083 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007084 case XML_SCHEMA_TYPE_SIMPLE:
7085 case XML_SCHEMA_TYPE_COMPLEX: {
7086 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7087 ADD_ANNOTATION(annot)
7088 }
7089 break;
7090 case XML_SCHEMA_TYPE_GROUP: {
7091 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7092 ADD_ANNOTATION(annot)
7093 }
7094 break;
7095 case XML_SCHEMA_TYPE_SEQUENCE:
7096 case XML_SCHEMA_TYPE_CHOICE:
7097 case XML_SCHEMA_TYPE_ALL: {
7098 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7099 ADD_ANNOTATION(annot)
7100 }
7101 break;
7102 default:
7103 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007104 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007105 NULL, NULL, NULL,
7106 "Internal error: xmlSchemaAddAnnotation, "
7107 "The item is not a annotated schema component", NULL);
7108 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007110 return (annot);
7111}
7112
7113/**
7114 * xmlSchemaParseIDCSelectorAndField:
7115 * @ctxt: a schema validation context
7116 * @schema: the schema being built
7117 * @node: a subtree containing XML Schema informations
7118 *
7119 * Parses a XML Schema identity-contraint definition's
7120 * <selector> and <field> elements.
7121 *
7122 * Returns the parsed identity-constraint definition.
7123 */
7124static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007125xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007126 xmlSchemaPtr schema,
7127 xmlSchemaIDCPtr idc,
7128 xmlNodePtr node,
7129 int isField)
7130{
7131 xmlSchemaIDCSelectPtr item;
7132 xmlNodePtr child = NULL;
7133 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007134
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007135 /*
7136 * Check for illegal attributes.
7137 */
7138 attr = node->properties;
7139 while (attr != NULL) {
7140 if (attr->ns == NULL) {
7141 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7142 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007143 xmlSchemaPIllegalAttrErr(ctxt,
7144 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7145 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007146 }
7147 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007148 xmlSchemaPIllegalAttrErr(ctxt,
7149 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7150 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007151 }
7152 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007153 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007154 /*
7155 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007156 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007157 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7158 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007159 xmlSchemaPErrMemory(ctxt,
7160 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007161 NULL);
7162 return (NULL);
7163 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007164 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007165 /*
7166 * Attribute "xpath" (mandatory).
7167 */
7168 attr = xmlSchemaGetPropNode(node, "xpath");
7169 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007170 xmlSchemaPMissingAttrErr(ctxt,
7171 XML_SCHEMAP_S4S_ATTR_MISSING,
7172 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007173 "name", NULL);
7174 } else {
7175 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7176 /*
7177 * URGENT TODO: "field"s have an other syntax than "selector"s.
7178 */
7179
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007180 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7181 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007182 xmlSchemaPErr(ctxt,
7183 (xmlNodePtr) attr,
7184 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007185 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007186 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007187 NULL, NULL);
7188 }
7189
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007190 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007191 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 /*
7193 * And now for the children...
7194 */
7195 child = node->children;
7196 if (IS_SCHEMA(child, "annotation")) {
7197 /*
7198 * Add the annotation to the parent IDC.
7199 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007200 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007201 xmlSchemaParseAnnotation(ctxt, schema, child));
7202 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007203 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007204 if (child != NULL) {
7205 xmlSchemaPContentErr(ctxt,
7206 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007207 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007208 NULL, "(annotation?)");
7209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007210
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 return (item);
7212}
7213
7214/**
7215 * xmlSchemaParseIDC:
7216 * @ctxt: a schema validation context
7217 * @schema: the schema being built
7218 * @node: a subtree containing XML Schema informations
7219 *
7220 * Parses a XML Schema identity-contraint definition.
7221 *
7222 * Returns the parsed identity-constraint definition.
7223 */
7224static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007225xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007226 xmlSchemaPtr schema,
7227 xmlNodePtr node,
7228 xmlSchemaTypeType idcCategory,
7229 const xmlChar *targetNamespace)
7230{
7231 xmlSchemaIDCPtr item = NULL;
7232 xmlNodePtr child = NULL;
7233 xmlAttrPtr attr;
7234 const xmlChar *name = NULL;
7235 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7236 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007237
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007238 /*
7239 * Check for illegal attributes.
7240 */
7241 attr = node->properties;
7242 while (attr != NULL) {
7243 if (attr->ns == NULL) {
7244 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7245 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7246 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7247 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 xmlSchemaPIllegalAttrErr(ctxt,
7249 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7250 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007251 }
7252 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007253 xmlSchemaPIllegalAttrErr(ctxt,
7254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7255 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007256 }
7257 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007258 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007259 /*
7260 * Attribute "name" (mandatory).
7261 */
7262 attr = xmlSchemaGetPropNode(node, "name");
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 "name", NULL);
7268 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007269 } else if (xmlSchemaPValAttrNode(ctxt,
7270 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007271 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7272 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007273 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007274 /*
7275 * Create the component.
7276 */
7277 if (schema->idcDef == NULL)
7278 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007279 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007280 return (NULL);
7281
7282 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7283 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007284 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007285 "allocating an identity-constraint definition", NULL);
7286 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007287 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007288 /*
7289 * Add the IDC to the list of IDCs on the schema component.
7290 */
7291 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007292 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007293 xmlSchemaPCustomErrExt(ctxt,
7294 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007295 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007296 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007297 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007298 name, targetNamespace, NULL);
7299 xmlFree(item);
7300 return (NULL);
7301 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007302 memset(item, 0, sizeof(xmlSchemaIDC));
7303 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007304 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007306 if (ctxt->assemble != NULL)
7307 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007308 /*
7309 * The target namespace of the parent element declaration.
7310 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007311 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007312 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7313 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007314 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7315 /*
7316 * Attribute "refer" (mandatory).
7317 */
7318 attr = xmlSchemaGetPropNode(node, "refer");
7319 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007320 xmlSchemaPMissingAttrErr(ctxt,
7321 XML_SCHEMAP_S4S_ATTR_MISSING,
7322 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007323 "refer", NULL);
7324 } else {
7325 /*
7326 * Create a reference item.
7327 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007328 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007329 NULL, NULL);
7330 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007331 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007333 NULL, NULL, attr,
7334 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007335 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007336 xmlSchemaCheckReference(ctxt, schema, node,
7337 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007338 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007339 }
7340 }
7341 /*
7342 * And now for the children...
7343 */
7344 child = node->children;
7345 if (IS_SCHEMA(child, "annotation")) {
7346 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7347 child = child->next;
7348 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007349 if (child == NULL) {
7350 xmlSchemaPContentErr(ctxt,
7351 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007352 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007353 "A child element is missing",
7354 "(annotation?, (selector, field+))");
7355 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007356 /*
7357 * Child element <selector>.
7358 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007359 if (IS_SCHEMA(child, "selector")) {
7360 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007361 item, child, 0);
7362 child = child->next;
7363 /*
7364 * Child elements <field>.
7365 */
7366 if (IS_SCHEMA(child, "field")) {
7367 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007368 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007369 item, child, 1);
7370 if (field != NULL) {
7371 field->index = item->nbFields;
7372 item->nbFields++;
7373 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007375 else
7376 item->fields = field;
7377 lastField = field;
7378 }
7379 child = child->next;
7380 } while (IS_SCHEMA(child, "field"));
7381 } else {
7382 xmlSchemaPContentErr(ctxt,
7383 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007384 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007385 NULL, "(annotation?, (selector, field+))");
7386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007387 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007388 if (child != NULL) {
7389 xmlSchemaPContentErr(ctxt,
7390 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007391 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007392 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007393 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007394
7395 return (item);
7396}
7397
Daniel Veillardc0826a72004-08-10 14:17:33 +00007398/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007399 * xmlSchemaParseElement:
7400 * @ctxt: a schema validation context
7401 * @schema: the schema being built
7402 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007403 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007404 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007405 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007406 * *WARNING* this interface is highly subject to change
7407 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007408 * Returns the element declaration or a particle; NULL in case
7409 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007410 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007411static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007412xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007413 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007414{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007415 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007416 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007417 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007418 xmlNodePtr child = NULL;
7419 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 int min, max, isRef = 0;
7421 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007422
7423 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7424 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007425
Daniel Veillard4255d502002-04-16 15:50:10 +00007426 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007427 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007428 /*
7429 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007430 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007431 * robust.
7432 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007433 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007434 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007435 if ((topLevel) || (attr == NULL)) {
7436 if (nameAttr == NULL) {
7437 xmlSchemaPMissingAttrErr(ctxt,
7438 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007439 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007440 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007441 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007442 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007443 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007444
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007445 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007446 child = node->children;
7447 if (IS_SCHEMA(child, "annotation")) {
7448 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7449 child = child->next;
7450 }
7451 /*
7452 * Skip particle part if a global declaration.
7453 */
7454 if (topLevel)
7455 goto declaration_part;
7456 /*
7457 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007458 */
7459 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7460 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7461 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007462 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7463 if (particle == NULL)
7464 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007465
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007466 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7467
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007468 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007469 const xmlChar *refNs = NULL, *ref = NULL;
7470 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007472 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007473 */
7474 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007475 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007476 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007477 /*
7478 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007479 */
7480 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007481 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007482 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007483 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007485 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007486 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007487 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007488 attr = node->properties;
7489 while (attr != NULL) {
7490 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007491 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7492 xmlStrEqual(attr->name, BAD_CAST "name") ||
7493 xmlStrEqual(attr->name, BAD_CAST "id") ||
7494 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7495 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7496 {
7497 attr = attr->next;
7498 continue;
7499 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007500 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007501 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007502 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007503 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007504 "Only the attributes 'minOccurs', 'maxOccurs' and "
7505 "'id' are allowed in addition to 'ref'");
7506 break;
7507 }
7508 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7509 xmlSchemaPIllegalAttrErr(ctxt,
7510 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007511 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007512 }
7513 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007514 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007515 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007516 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007517 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007518 if (child != NULL) {
7519 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7520 NULL, NULL, node, child, NULL, "(annotation?)");
7521 }
7522 if ((min == 0) && (max == 0))
7523 goto return_null;
7524 /*
7525 * Create the reference item.
7526 */
7527 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7528 ref, refNs);
7529 if (refer == NULL)
7530 goto return_null;
7531 particle->children = (xmlSchemaTreeItemPtr) refer;
7532 particle->annot = annot;
7533 /*
7534 * Add to assembled items; the reference need to be resolved.
7535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007537 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7538
7539 return ((xmlSchemaBasicItemPtr) particle);
7540 }
7541 /*
7542 * The declaration part ===============================================
7543 */
7544declaration_part:
7545 {
7546 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7547 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7548
7549 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007551 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007552 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007553 * Evaluate the target namespace.
7554 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007555 if (topLevel) {
7556 ns = schema->targetNamespace;
7557 } else {
7558 attr = xmlSchemaGetPropNode(node, "form");
7559 if (attr != NULL) {
7560 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7561 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007562 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007563 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007564 xmlSchemaPSimpleTypeErr(ctxt,
7565 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7566 NULL, (xmlNodePtr) attr,
7567 NULL, "(qualified | unqualified)",
7568 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007569 }
7570 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007571 ns = schema->targetNamespace;
7572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007573 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007574 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007575 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007577 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7578 decl->node = node;
7579 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007580 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007581 * Check for illegal attributes.
7582 */
William M. Bracke7091952004-05-11 15:09:58 +00007583 attr = node->properties;
7584 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007585 if (attr->ns == NULL) {
7586 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7587 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007590 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007592 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7593 {
7594 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007595 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007596 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007597 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007598 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007599 xmlSchemaPIllegalAttrErr(ctxt,
7600 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7601 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007603 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7604 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7606
7607 xmlSchemaPIllegalAttrErr(ctxt,
7608 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007610 }
7611 }
7612 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007613
Daniel Veillardc0826a72004-08-10 14:17:33 +00007614 xmlSchemaPIllegalAttrErr(ctxt,
7615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007616 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007617 }
7618 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007619 }
William M. Bracke7091952004-05-11 15:09:58 +00007620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 * Extract/validate attributes.
7622 */
7623 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007624 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007625 * Process top attributes of global element declarations here.
7626 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007627 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7628 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007629 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7630 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7631 &(decl->substGroupNs), &(decl->substGroup));
7632 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007633 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007634 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007635 /*
7636 * Attribute "final".
7637 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007638 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007639 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007640 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7641 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7642 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7643 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007644 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007645 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7646 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007647 -1,
7648 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7649 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007650 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007652 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7653 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007654 attrValue, NULL, NULL, NULL);
7655 }
7656 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007657 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007658 /*
7659 * Attribute "block".
7660 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007661 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007662 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007663 /*
7664 * Apply default "block" values.
7665 */
7666 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7667 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7668 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7669 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7670 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7671 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007672 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007673 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7674 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007675 -1,
7676 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007678 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7679 xmlSchemaPSimpleTypeErr(ctxt,
7680 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007681 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007682 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007683 "restriction | substitution))", attrValue,
7684 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 }
7686 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007689 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007690
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007691 attr = xmlSchemaGetPropNode(node, "type");
7692 if (attr != NULL) {
7693 xmlSchemaPValAttrNodeQName(ctxt, schema,
7694 NULL, (xmlSchemaTypePtr) decl, attr,
7695 &(decl->namedTypeNs), &(decl->namedType));
7696 xmlSchemaCheckReference(ctxt, schema, node,
7697 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7698 }
7699 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7700 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007701 if (attr != NULL) {
7702 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007703 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007704 /*
7705 * 3.3.3 : 1
7706 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 */
7708 xmlSchemaPMutualExclAttrErr(ctxt,
7709 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007710 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007711 "default", "fixed");
7712 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007713 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7714 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007715 }
William M. Bracke7091952004-05-11 15:09:58 +00007716 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007717 /*
7718 * And now for the children...
7719 */
7720 oldcontainer = ctxt->container;
7721 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007722 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007723 /*
7724 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007726 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007728 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007729 xmlSchemaPContentErr(ctxt,
7730 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007731 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007733 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007734 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007735 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007736 child = child->next;
7737 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007738 /*
7739 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007740 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007741 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007742 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007743 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007744 xmlSchemaPContentErr(ctxt,
7745 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007747 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007748 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007749 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007750 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007751 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007752 }
William M. Bracke7091952004-05-11 15:09:58 +00007753 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007754 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007755 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007757 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007758 } else if (IS_SCHEMA(child, "key")) {
7759 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007760 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007761 } else if (IS_SCHEMA(child, "keyref")) {
7762 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007763 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007764 }
7765 if (lastIDC != NULL)
7766 lastIDC->next = curIDC;
7767 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007768 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007769 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007770 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007771 }
7772 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007773 xmlSchemaPContentErr(ctxt,
7774 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007775 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007776 NULL, "(annotation?, ((simpleType | complexType)?, "
7777 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007778 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007779 ctxt->container = oldcontainer;
7780 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007781 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007782 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007783 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007784 * different layer.
7785 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007786 FREE_AND_NULL(des)
7787 if (topLevel)
7788 return ((xmlSchemaBasicItemPtr) decl);
7789 else {
7790 particle->children = (xmlSchemaTreeItemPtr) decl;
7791 return ((xmlSchemaBasicItemPtr) particle);
7792 }
7793
7794return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007795 FREE_AND_NULL(des);
7796 if (annot != NULL) {
7797 if (particle != NULL)
7798 particle->annot = NULL;
7799 if (decl != NULL)
7800 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007801 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007803 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007804}
7805
7806/**
7807 * xmlSchemaParseUnion:
7808 * @ctxt: a schema validation context
7809 * @schema: the schema being built
7810 * @node: a subtree containing XML Schema informations
7811 *
7812 * parse a XML schema Union definition
7813 * *WARNING* this interface is highly subject to change
7814 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007815 * Returns -1 in case of internal error, 0 in case of success and a positive
7816 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007817 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007819xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007820 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007821{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007822 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007823 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007824 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007825 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007826
7827 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007828 return (-1);
7829 /* Not a component, don't create it. */
7830 type = ctxt->ctxtType;
7831 /*
7832 * Mark the simple type as being of variety "union".
7833 */
7834 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007835 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007836 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7837 * then the ·simple ur-type definition·."
7838 */
7839 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007840 /*
7841 * Check for illegal attributes.
7842 */
7843 attr = node->properties;
7844 while (attr != NULL) {
7845 if (attr->ns == NULL) {
7846 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7847 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007848 xmlSchemaPIllegalAttrErr(ctxt,
7849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7850 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007851 }
7852 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 xmlSchemaPIllegalAttrErr(ctxt,
7854 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7855 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007856 }
7857 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007858 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007859 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007860 /*
7861 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007862 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007864 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007865 if (attr != NULL) {
7866 const xmlChar *end;
7867 xmlChar *tmp;
7868 const xmlChar *localName, *nsName;
7869 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7870 xmlSchemaQNameRefPtr ref;
7871
7872 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007874 do {
7875 while (IS_BLANK_CH(*cur))
7876 cur++;
7877 end = cur;
7878 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7879 end++;
7880 if (end == cur)
7881 break;
7882 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007883 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7884 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007885 /*
7886 * Create the member type link.
7887 */
7888 link = (xmlSchemaTypeLinkPtr)
7889 xmlMalloc(sizeof(xmlSchemaTypeLink));
7890 if (link == NULL) {
7891 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7892 "allocating a type link", NULL);
7893 return (-1);
7894 }
7895 link->type = NULL;
7896 link->next = NULL;
7897 if (lastLink == NULL)
7898 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007899 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007900 lastLink->next = link;
7901 lastLink = link;
7902 /*
7903 * Create a reference item.
7904 */
7905 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7906 localName, nsName);
7907 if (ref == NULL) {
7908 FREE_AND_NULL(tmp)
7909 return (-1);
7910 }
7911 /*
7912 * Assign the reference to the link, it will be resolved
7913 * later during fixup of the union simple type.
7914 */
7915 link->type = (xmlSchemaTypePtr) ref;
7916 }
7917 FREE_AND_NULL(tmp)
7918 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007920
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007921 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007922 /*
7923 * And now for the children...
7924 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007925 child = node->children;
7926 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007927 /*
7928 * Add the annotation to the simple type ancestor.
7929 */
7930 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7931 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007932 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007933 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007934 if (IS_SCHEMA(child, "simpleType")) {
7935 xmlSchemaTypePtr subtype, last = NULL;
7936
7937 /*
7938 * Anchor the member types in the "subtypes" field of the
7939 * simple type.
7940 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007941 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007942 subtype = (xmlSchemaTypePtr)
7943 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7944 if (subtype != NULL) {
7945 if (last == NULL) {
7946 type->subtypes = subtype;
7947 last = subtype;
7948 } else {
7949 last->next = subtype;
7950 last = subtype;
7951 }
7952 last->next = NULL;
7953 }
7954 child = child->next;
7955 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007956 }
7957 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007958 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007960 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007961 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007962 if ((attr == NULL) && (type->subtypes == NULL)) {
7963 /*
7964 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007965 * Either the memberTypes [attribute] of the <union> element must
7966 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007967 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007968 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007969 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7970 NULL, NULL, node,
7971 "Either the attribute 'memberTypes' or "
7972 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007973 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007974 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007975}
7976
7977/**
7978 * xmlSchemaParseList:
7979 * @ctxt: a schema validation context
7980 * @schema: the schema being built
7981 * @node: a subtree containing XML Schema informations
7982 *
7983 * parse a XML schema List definition
7984 * *WARNING* this interface is highly subject to change
7985 *
William M. Bracke7091952004-05-11 15:09:58 +00007986 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007987 * 1 in case of success.
7988 */
7989static xmlSchemaTypePtr
7990xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007991 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007992{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007993 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007994 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007995 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007996
7997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7998 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 /* Not a component, don't create it. */
8000 type = ctxt->ctxtType;
8001 /*
8002 * Mark the type as being of variety "list".
8003 */
8004 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008005 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008006 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8007 * then the ·simple ur-type definition·."
8008 */
8009 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008010 /*
8011 * Check for illegal attributes.
8012 */
8013 attr = node->properties;
8014 while (attr != NULL) {
8015 if (attr->ns == NULL) {
8016 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8017 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008018 xmlSchemaPIllegalAttrErr(ctxt,
8019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8020 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008021 }
8022 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008023 xmlSchemaPIllegalAttrErr(ctxt,
8024 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8025 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008026 }
8027 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008028 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008029
8030 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8031
William M. Brack2f2a6632004-08-20 23:09:47 +00008032 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8034 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008035 */
8036 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008037 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008038 /*
8039 * And now for the children...
8040 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008041 child = node->children;
8042 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008043 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8044 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008045 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008046 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008047 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008048 /*
8049 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008050 * Either the itemType [attribute] or the <simpleType> [child] of
8051 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008052 */
8053 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008054 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008055 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008056 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008057 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008058 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008059 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008060 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008061 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008062 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008063 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008064 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008065 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008066 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008067 "Either the attribute 'itemType' or the <simpleType> child "
8068 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008069 }
8070 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008071 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008072 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008073 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008074 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008075 if ((type->ref == NULL) &&
8076 (type->subtypes == NULL) &&
8077 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008078 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008079 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008081 "Either the attribute 'itemType' or the <simpleType> child "
8082 "must be present", NULL);
8083 }
8084 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008085}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008086
Daniel Veillard4255d502002-04-16 15:50:10 +00008087/**
8088 * xmlSchemaParseSimpleType:
8089 * @ctxt: a schema validation context
8090 * @schema: the schema being built
8091 * @node: a subtree containing XML Schema informations
8092 *
8093 * parse a XML schema Simple Type definition
8094 * *WARNING* this interface is highly subject to change
8095 *
William M. Bracke7091952004-05-11 15:09:58 +00008096 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008097 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008098 */
8099static xmlSchemaTypePtr
8100xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008101 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008102{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008103 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008104 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008106 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008107
8108 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8109 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008110
Daniel Veillardc0826a72004-08-10 14:17:33 +00008111 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008112 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008114 xmlSchemaPMissingAttrErr(ctxt,
8115 XML_SCHEMAP_S4S_ATTR_MISSING,
8116 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008117 "name", NULL);
8118 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008119 } else {
8120 if (xmlSchemaPValAttrNode(ctxt,
8121 NULL, NULL, attr,
8122 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8123 return (NULL);
8124 /*
8125 * Skip built-in types.
8126 */
8127 if (ctxt->isS4S) {
8128 xmlSchemaTypePtr biType;
8129
8130 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8131 if (biType != NULL)
8132 return (biType);
8133 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008134 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008135 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008136
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008138 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008139
Daniel Veillard01fa6152004-06-29 17:04:39 +00008140 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008141 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008142 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008143 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008144 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008145 if (type == NULL)
8146 return (NULL);
8147 type->node = node;
8148 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008149 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008150 /*
8151 * Check for illegal attributes.
8152 */
8153 attr = node->properties;
8154 while (attr != NULL) {
8155 if (attr->ns == NULL) {
8156 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008157 xmlSchemaPIllegalAttrErr(ctxt,
8158 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8159 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008160 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008161 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162 xmlSchemaPIllegalAttrErr(ctxt,
8163 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8164 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008165 }
8166 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008167 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008169 /*
8170 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008171 *
8172 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008173 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008174 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008175 if (type == NULL)
8176 return (NULL);
8177 type->node = node;
8178 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008179 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008180 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8181 /*
8182 * Check for illegal attributes.
8183 */
8184 attr = node->properties;
8185 while (attr != NULL) {
8186 if (attr->ns == NULL) {
8187 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8188 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008189 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008190 xmlSchemaPIllegalAttrErr(ctxt,
8191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8192 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008193 }
8194 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008195 xmlSchemaPIllegalAttrErr(ctxt,
8196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8197 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008198 }
8199 attr = attr->next;
8200 }
8201 /*
8202 * Attribute "final".
8203 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008204 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008205 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8207 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8208 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8209 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8210 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8211 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008212 } else {
8213 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008214 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8215 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008216 XML_SCHEMAS_TYPE_FINAL_LIST,
8217 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8218
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008219 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008220 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008221 type, (xmlNodePtr) attr,
8222 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008223 attrValue, NULL, NULL, NULL);
8224 }
8225 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008227 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008228 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008229 /*
8230 * And now for the children...
8231 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008232 oldCtxtType = ctxt->ctxtType;
8233 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008234 ctxt->ctxtType = type;
8235 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008236 child = node->children;
8237 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008238 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8239 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008240 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8243 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008244 "(annotation?, (restriction | list | union))");
8245 } else if (IS_SCHEMA(child, "restriction")) {
8246 xmlSchemaParseRestriction(ctxt, schema, child,
8247 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008248 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008249 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008250 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008251 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008252 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008253 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008254 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008255 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8258 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008259 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008260 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008261 ctxt->parentItem = oldParentItem;
8262 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008263
Daniel Veillard4255d502002-04-16 15:50:10 +00008264 return (type);
8265}
8266
Daniel Veillard4255d502002-04-16 15:50:10 +00008267/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008269 * @ctxt: a schema validation context
8270 * @schema: the schema being built
8271 * @node: a subtree containing XML Schema informations
8272 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008274 * *WARNING* this interface is highly subject to change
8275 *
William M. Bracke7091952004-05-11 15:09:58 +00008276 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008277 * 1 in case of success.
8278 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279static xmlSchemaTreeItemPtr
8280xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8281 xmlSchemaPtr schema,
8282 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008283{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008284 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008285 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008286 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008287 const xmlChar *ref = NULL, *refNs = NULL;
8288 int min, max;
8289
8290 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292
8293 attr = xmlSchemaGetPropNode(node, "ref");
8294 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008295 xmlSchemaPMissingAttrErr(ctxt,
8296 XML_SCHEMAP_S4S_ATTR_MISSING,
8297 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008298 "ref", NULL);
8299 return (NULL);
8300 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008301 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008302 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008303 }
8304 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008305 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008306 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008307 /*
8308 * Check for illegal attributes.
8309 */
8310 attr = node->properties;
8311 while (attr != NULL) {
8312 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008313 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008314 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8315 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8316 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317 xmlSchemaPIllegalAttrErr(ctxt,
8318 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8319 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008320 }
8321 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008322 xmlSchemaPIllegalAttrErr(ctxt,
8323 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8324 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008325 }
8326 attr = attr->next;
8327 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008328 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8330 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008331 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008332 /*
8333 * Create a reference item as the term; it will be substituted for
8334 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 */
8336 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008337 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8338 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8339 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8340 /*
8341 * And now for the children...
8342 */
8343 child = node->children;
8344 /* TODO: Is annotation even allowed for a model group reference? */
8345 if (IS_SCHEMA(child, "annotation")) {
8346 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008347 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008348 */
8349 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8350 child = child->next;
8351 }
8352 if (child != NULL) {
8353 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008355 NULL, NULL, node, child, NULL,
8356 "(annotation?)");
8357 }
8358 /*
8359 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8360 */
8361 if ((min == 0) && (max == 0))
8362 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8365 return ((xmlSchemaTreeItemPtr) item);
8366}
8367
8368/**
8369 * xmlSchemaParseModelGroupDefinition:
8370 * @ctxt: a schema validation context
8371 * @schema: the schema being built
8372 * @node: a subtree containing XML Schema informations
8373 *
8374 * Parses a XML schema model group definition.
8375 * *WARNING* this interface is highly subject to change
8376 *
8377 * Returns -1 in case of error, 0 if the declaration is improper and
8378 * 1 in case of success.
8379 */
8380static xmlSchemaModelGroupDefPtr
8381xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8382 xmlSchemaPtr schema,
8383 xmlNodePtr node)
8384{
8385 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008387 xmlAttrPtr attr;
8388 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008389
8390 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008391 return (NULL);
8392
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008393 attr = xmlSchemaGetPropNode(node, "name");
8394 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 xmlSchemaPMissingAttrErr(ctxt,
8396 XML_SCHEMAP_S4S_ATTR_MISSING,
8397 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008398 "name", NULL);
8399 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008400 } else if (xmlSchemaPValAttrNode(ctxt,
8401 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008402 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8403 return (NULL);
8404 }
8405 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8406 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008408 /*
8409 * Check for illegal attributes.
8410 */
8411 attr = node->properties;
8412 while (attr != NULL) {
8413 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008414 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008415 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008416 xmlSchemaPIllegalAttrErr(ctxt,
8417 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8418 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008419 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008420 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008421 xmlSchemaPIllegalAttrErr(ctxt,
8422 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8423 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008425 attr = attr->next;
8426 }
8427 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8428 /*
8429 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008430 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008431 child = node->children;
8432 if (IS_SCHEMA(child, "annotation")) {
8433 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8434 child = child->next;
8435 }
8436 if (IS_SCHEMA(child, "all")) {
8437 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8438 XML_SCHEMA_TYPE_ALL, 0);
8439 child = child->next;
8440 } else if (IS_SCHEMA(child, "choice")) {
8441 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8442 XML_SCHEMA_TYPE_CHOICE, 0);
8443 child = child->next;
8444 } else if (IS_SCHEMA(child, "sequence")) {
8445 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8446 XML_SCHEMA_TYPE_SEQUENCE, 0);
8447 child = child->next;
8448 }
8449 if (child != NULL) {
8450 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008451 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8452 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008453 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008454 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008455
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008456 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008457}
8458
8459/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008460 * xmlSchemaCleanupDoc:
8461 * @ctxt: a schema validation context
8462 * @node: the root of the document.
8463 *
8464 * removes unwanted nodes in a schemas document tree
8465 */
8466static void
8467xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8468{
8469 xmlNodePtr delete, cur;
8470
8471 if ((ctxt == NULL) || (root == NULL)) return;
8472
8473 /*
8474 * Remove all the blank text nodes
8475 */
8476 delete = NULL;
8477 cur = root;
8478 while (cur != NULL) {
8479 if (delete != NULL) {
8480 xmlUnlinkNode(delete);
8481 xmlFreeNode(delete);
8482 delete = NULL;
8483 }
8484 if (cur->type == XML_TEXT_NODE) {
8485 if (IS_BLANK_NODE(cur)) {
8486 if (xmlNodeGetSpacePreserve(cur) != 1) {
8487 delete = cur;
8488 }
8489 }
8490 } else if ((cur->type != XML_ELEMENT_NODE) &&
8491 (cur->type != XML_CDATA_SECTION_NODE)) {
8492 delete = cur;
8493 goto skip_children;
8494 }
8495
8496 /*
8497 * Skip to next node
8498 */
8499 if (cur->children != NULL) {
8500 if ((cur->children->type != XML_ENTITY_DECL) &&
8501 (cur->children->type != XML_ENTITY_REF_NODE) &&
8502 (cur->children->type != XML_ENTITY_NODE)) {
8503 cur = cur->children;
8504 continue;
8505 }
8506 }
8507 skip_children:
8508 if (cur->next != NULL) {
8509 cur = cur->next;
8510 continue;
8511 }
8512
8513 do {
8514 cur = cur->parent;
8515 if (cur == NULL)
8516 break;
8517 if (cur == root) {
8518 cur = NULL;
8519 break;
8520 }
8521 if (cur->next != NULL) {
8522 cur = cur->next;
8523 break;
8524 }
8525 } while (cur != NULL);
8526 }
8527 if (delete != NULL) {
8528 xmlUnlinkNode(delete);
8529 xmlFreeNode(delete);
8530 delete = NULL;
8531 }
8532}
8533
William M. Brack2f2a6632004-08-20 23:09:47 +00008534
8535/**
8536 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008537 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008538 * @ctxt: a schema validation context
8539 * @schemaLocation: an URI defining where to find the imported schema
8540 *
8541 * import a XML schema
8542 * *WARNING* this interface is highly subject to change
8543 *
8544 * Returns -1 in case of error and 1 in case of success.
8545 */
8546#if 0
8547static xmlSchemaImportPtr
8548xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8549 const xmlChar *schemaLocation)
8550{
8551 xmlSchemaImportPtr import;
8552 xmlSchemaParserCtxtPtr newctxt;
8553
8554 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8555 if (newctxt == NULL) {
8556 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8557 NULL);
8558 return (NULL);
8559 }
8560 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8561 /* Keep the same dictionnary for parsing, really */
8562 xmlDictReference(ctxt->dict);
8563 newctxt->dict = ctxt->dict;
8564 newctxt->includes = 0;
8565 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8566
8567 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8568 ctxt->userData);
8569
8570 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8571 if (import == NULL) {
8572 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8573 NULL);
8574 xmlSchemaFreeParserCtxt(newctxt);
8575 return (NULL);
8576 }
8577
8578 memset(import, 0, sizeof(xmlSchemaImport));
8579 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8580 import->schema = xmlSchemaParse(newctxt);
8581
8582 if (import->schema == NULL) {
8583 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008584 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008585 "Failed to import schema from location \"%s\".\n",
8586 schemaLocation, NULL);
8587
8588 xmlSchemaFreeParserCtxt(newctxt);
8589 /* The schemaLocation is held by the dictionary.
8590 if (import->schemaLocation != NULL)
8591 xmlFree((xmlChar *)import->schemaLocation);
8592 */
8593 xmlFree(import);
8594 return NULL;
8595 }
8596
8597 xmlSchemaFreeParserCtxt(newctxt);
8598 return import;
8599}
8600#endif
8601
8602static void
8603xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8604{
8605 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8606 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8607
8608 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8609 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8610
8611 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8612 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8613 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8614 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8615 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8616 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8617 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8618 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8619
8620 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8621 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8623 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8625 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8626}
8627
8628static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008629xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 xmlSchemaPtr schema,
8631 xmlNodePtr node)
8632{
8633 xmlAttrPtr attr;
8634 const xmlChar *val;
8635
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008636 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8637 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008639 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8640 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008642 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8643
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008644 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008645 if (attr != NULL) {
8646 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008647 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008648 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008649 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008650 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008651 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008652 "(qualified | unqualified)", val, NULL, NULL, NULL);
8653 }
8654 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008655
8656 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008657 if (attr != NULL) {
8658 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008659 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008660 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008661 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008662 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008663 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008664 "(qualified | unqualified)", val, NULL, NULL, NULL);
8665 }
8666 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008667
8668 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008669 if (attr != NULL) {
8670 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8671 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8672 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8673 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8674 -1,
8675 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8676 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8677 xmlSchemaPSimpleTypeErr(ctxt,
8678 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008680 "(#all | List of (extension | restriction | list | union))",
8681 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008682 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008683 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008684
8685 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008686 if (attr != NULL) {
8687 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8688 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8689 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8690 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8691 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8692 xmlSchemaPSimpleTypeErr(ctxt,
8693 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008694 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008695 "(#all | List of (extension | restriction | substitution))",
8696 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008697 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008698 }
8699}
8700
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701/**
8702 * xmlSchemaParseSchemaTopLevel:
8703 * @ctxt: a schema validation context
8704 * @schema: the schemas
8705 * @nodes: the list of top level nodes
8706 *
8707 * Returns the internal XML Schema structure built from the resource or
8708 * NULL in case of error
8709 */
8710static void
8711xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8712 xmlSchemaPtr schema, xmlNodePtr nodes)
8713{
8714 xmlNodePtr child;
8715 xmlSchemaAnnotPtr annot;
8716
8717 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8718 return;
8719
8720 child = nodes;
8721 while ((IS_SCHEMA(child, "include")) ||
8722 (IS_SCHEMA(child, "import")) ||
8723 (IS_SCHEMA(child, "redefine")) ||
8724 (IS_SCHEMA(child, "annotation"))) {
8725 if (IS_SCHEMA(child, "annotation")) {
8726 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8727 if (schema->annot == NULL)
8728 schema->annot = annot;
8729 else
8730 xmlSchemaFreeAnnot(annot);
8731 } else if (IS_SCHEMA(child, "import")) {
8732 xmlSchemaParseImport(ctxt, schema, child);
8733 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008734 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008735 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008736 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008737 } else if (IS_SCHEMA(child, "redefine")) {
8738 TODO
8739 }
8740 child = child->next;
8741 }
8742 while (child != NULL) {
8743 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008744 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008745 child = child->next;
8746 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008747 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008748 child = child->next;
8749 } else if (IS_SCHEMA(child, "element")) {
8750 xmlSchemaParseElement(ctxt, schema, child, 1);
8751 child = child->next;
8752 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008753 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008754 child = child->next;
8755 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008756 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008757 child = child->next;
8758 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008759 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008760 child = child->next;
8761 } else if (IS_SCHEMA(child, "notation")) {
8762 xmlSchemaParseNotation(ctxt, schema, child);
8763 child = child->next;
8764 } else {
8765 xmlSchemaPErr2(ctxt, NULL, child,
8766 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008767 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008768 child->name, NULL);
8769 child = child->next;
8770 }
8771 while (IS_SCHEMA(child, "annotation")) {
8772 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8773 if (schema->annot == NULL)
8774 schema->annot = annot;
8775 else
8776 xmlSchemaFreeAnnot(annot);
8777 child = child->next;
8778 }
8779 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008780 ctxt->parentItem = NULL;
8781 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008782}
8783
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008784static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008785xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008786 xmlHashTablePtr *imports,
8787 const xmlChar *nsName)
8788{
8789 xmlSchemaImportPtr ret;
8790
8791 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008792 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008793 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008795 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8796 NULL, NULL, (xmlNodePtr) ctxt->doc,
8797 "Internal error: failed to build the import table",
8798 NULL);
8799 return (NULL);
8800 }
8801 }
8802 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8803 if (ret == NULL) {
8804 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8805 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008806 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008807 memset(ret, 0, sizeof(xmlSchemaImport));
8808 if (nsName == NULL)
8809 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008810 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008811
8812 return (ret);
8813}
8814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008815/**
8816 * xmlSchemaNewParserCtxtUseDict:
8817 * @URL: the location of the schema
8818 * @dict: the dictionary to be used
8819 *
8820 * Create an XML Schemas parse context for that file/resource expected
8821 * to contain an XML Schemas file.
8822 *
8823 * Returns the parser context or NULL in case of error
8824 */
8825static xmlSchemaParserCtxtPtr
8826xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8827{
8828 xmlSchemaParserCtxtPtr ret;
8829 /*
8830 if (URL == NULL)
8831 return (NULL);
8832 */
8833
8834 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8835 if (ret == NULL) {
8836 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8837 NULL);
8838 return (NULL);
8839 }
8840 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8841 ret->dict = dict;
8842 xmlDictReference(dict);
8843 if (URL != NULL)
8844 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8845 ret->includes = 0;
8846 return (ret);
8847}
8848
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008849static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8851{
8852 if (vctxt->pctxt == NULL) {
8853 if (vctxt->schema != NULL)
8854 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8855 else
8856 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8857 if (vctxt->pctxt == NULL) {
8858 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8859 "failed to create a temp. parser context");
8860 return (-1);
8861 }
8862 /* TODO: Pass user data. */
8863 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8864 }
8865 return (0);
8866}
8867
8868static int
8869xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008870 xmlSchemaPtr schema,
8871 xmlNodePtr node,
8872 const xmlChar *nsName,
8873 const xmlChar *location,
8874 xmlDocPtr *doc,
8875 const xmlChar **targetNamespace,
8876 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008878 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008879 xmlParserCtxtPtr parserCtxt;
8880 xmlSchemaImportPtr import;
8881 const xmlChar *ns;
8882 xmlNodePtr root;
8883
8884 /*
8885 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8886 * <xsi:noNamespaceSchemaLocation>.
8887 */
8888 *doc = NULL;
8889 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008890 * Given that the schemaLocation [attribute] is only a hint, it is open
8891 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008892 * namespace, regardless of the ·actual value· of schemaLocation, but
8893 * such a strategy risks missing useful information when new
8894 * schemaLocations are offered.
8895 *
8896 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8897 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8898 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008900 */
8901 if (location == NULL) {
8902 /*
8903 * Schema Document Location Strategy:
8904 *
8905 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008906 * either as a resource which is an XML document or a <schema> element
8907 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008908 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008909 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008910 *
8911 * NOTE: Those stategies are not supported, so we will skip.
8912 */
8913 return (0);
8914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916 ns = XML_SCHEMAS_NO_NAMESPACE;
8917 else
8918 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008922 /*
8923 * There was a valid resource for the specified namespace already
8924 * defined, so skip.
8925 * TODO: This might be changed someday to allow import of
8926 * components from multiple documents for a single target namespace.
8927 */
8928 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008929 }
8930 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8931 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8932 else {
8933 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8934 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8935 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008936 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008938 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008939 * 2 Based on the location URI, identify an existing schema document,
8940 * either as a resource which is an XML document or a <schema> element
8941 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008942 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008944 * web which is or contains or references a <schema> element;
8945 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8946 *
8947 */
8948 if ((absolute == 0) && (node != NULL)) {
8949 xmlChar *base, *URI;
8950
8951 base = xmlNodeGetBase(node->doc, node);
8952 if (base == NULL) {
8953 URI = xmlBuildURI(location, node->doc->URL);
8954 } else {
8955 URI = xmlBuildURI(location, base);
8956 xmlFree(base);
8957 }
8958 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFree(URI);
8961 }
8962 }
8963 parserCtxt = xmlNewParserCtxt();
8964 if (parserCtxt == NULL) {
8965 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8966 "allocating a parser context", NULL);
8967 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008968 }
8969 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008970 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008972 xmlDictReference(parserCtxt->dict);
8973 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008975 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008977 * 2.1 The referent is (a fragment of) a resource which is an
8978 * XML document (see clause 1.1), which in turn corresponds to
8979 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 * set, which in turn corresponds to a valid schema.
8981 * TODO: What to do with the "fragment" stuff?
8982 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008983 * 2.2 The referent is a <schema> element information item in
8984 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008986 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008987 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008988 */
8989 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 xmlErrorPtr lerr;
8991 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008994 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008995 * If the doc is NULL and the parser error is an IO error we
8996 * will assume that the resource could not be located or accessed.
8997 *
8998 * TODO: Try to find specific error codes to react only on
8999 * localisation failures.
9000 *
9001 * TODO, FIXME: Check the spec: is a namespace added to the imported
9002 * namespaces, even if the schemaLocation did not provide
9003 * a resource? I guess so, since omitting the "schemaLocation"
9004 * attribute, imports a namespace as well.
9005 */
9006 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 xmlFreeParserCtxt(parserCtxt);
9009 return(0);
9010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009013 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009014 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009015 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009016 xmlFreeParserCtxt(parserCtxt);
9017 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9018 }
9019 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009021 root = xmlDocGetRootElement(*doc);
9022 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009023 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009024 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009025 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009026 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009027 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009028 xmlFreeDoc(*doc);
9029 *doc = NULL;
9030 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009031 }
9032
9033 xmlSchemaCleanupDoc(pctxt, root);
9034
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009035 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009037 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009039 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009040 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009041 xmlFreeDoc(*doc);
9042 *doc = NULL;
9043 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009044 }
9045 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009046 /*
9047 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009049 if (nsName == NULL) {
9050 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009052 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009053 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009054 "The XML schema to be imported is not expected "
9055 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009056 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009057 xmlFreeDoc(*doc);
9058 *doc = NULL;
9059 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9060 }
9061 } else {
9062 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009063 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009064 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009065 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009066 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009067 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009068 xmlFreeDoc(*doc);
9069 *doc = NULL;
9070 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9071 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009072 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009073 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009074 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009075 "The XML schema to be imported is expected to have a "
9076 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009077 "its target namespace of '%s'",
9078 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009079 xmlFreeDoc(*doc);
9080 *doc = NULL;
9081 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9082 }
9083 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009084 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009085 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009086 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9087 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009088 xmlFreeDoc(*doc);
9089 *doc = NULL;
9090 return (-1);
9091 }
9092 import->schemaLocation = location;
9093 import->doc = *doc;
9094 return (0);
9095}
William M. Brack2f2a6632004-08-20 23:09:47 +00009096
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009097static void
9098xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9099 xmlSchemaPtr schema,
9100 const xmlChar *targetNamespace,
9101 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009103 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009104 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009105
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009106 /*
9107 * Save and reset the context & schema.
9108 */
9109 oldURL = pctxt->URL;
9110 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009111 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 oldLocImps = pctxt->localImports;
9113 pctxt->localImports = NULL;
9114 oldNumLocImps = pctxt->nbLocalImports;
9115 pctxt->nbLocalImports = 0;
9116 oldSizeLocImps = pctxt->sizeLocalImports;
9117 pctxt->sizeLocalImports = 0;
9118 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009119 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009120 xmlSchemaClearSchemaDefaults(schema);
9121 oldTNS = schema->targetNamespace;
9122 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009123 if ((targetNamespace != NULL) &&
9124 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9125 /*
9126 * We are parsing the schema for schema!
9127 */
9128 pctxt->isS4S = 1;
9129 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009130 /*
9131 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009132 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009133 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9134 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9135 /*
9136 * Restore the context & schema.
9137 */
9138 schema->flags = oldFlags;
9139 schema->targetNamespace = oldTNS;
9140 if (pctxt->localImports != NULL)
9141 xmlFree((xmlChar *) pctxt->localImports);
9142 pctxt->localImports = oldLocImps;
9143 pctxt->nbLocalImports = oldNumLocImps;
9144 pctxt->sizeLocalImports = oldSizeLocImps;
9145 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009146 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009147}
9148
William M. Brack2f2a6632004-08-20 23:09:47 +00009149/**
9150 * xmlSchemaParseImport:
9151 * @ctxt: a schema validation context
9152 * @schema: the schema being built
9153 * @node: a subtree containing XML Schema informations
9154 *
9155 * parse a XML schema Import definition
9156 * *WARNING* this interface is highly subject to change
9157 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009158 * Returns 0 in case of success, a positive error code if
9159 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009160 */
9161static int
9162xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9163 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009164{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009165 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009166 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009167 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009168 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009169 xmlAttrPtr attr;
9170 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009171 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009172
9173 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9174 return (-1);
9175
9176 /*
9177 * Check for illegal attributes.
9178 */
9179 attr = node->properties;
9180 while (attr != NULL) {
9181 if (attr->ns == NULL) {
9182 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9183 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9184 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009185 xmlSchemaPIllegalAttrErr(ctxt,
9186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9187 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 }
9189 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009190 xmlSchemaPIllegalAttrErr(ctxt,
9191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9192 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009193 }
9194 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009195 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009196 /*
9197 * Extract and validate attributes.
9198 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009199 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9200 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009201 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009202 xmlSchemaPSimpleTypeErr(ctxt,
9203 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9204 NULL, node,
9205 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009206 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009207 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9208 }
9209
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009210 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9211 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009212 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009213 xmlSchemaPSimpleTypeErr(ctxt,
9214 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9215 NULL, node,
9216 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009217 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009218 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009219 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009220 /*
9221 * And now for the children...
9222 */
9223 child = node->children;
9224 if (IS_SCHEMA(child, "annotation")) {
9225 /*
9226 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009227 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009228 */
9229 child = child->next;
9230 }
9231 if (child != NULL) {
9232 xmlSchemaPContentErr(ctxt,
9233 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9234 NULL, NULL, node, child, NULL,
9235 "(annotation?)");
9236 }
9237 /*
9238 * Apply additional constraints.
9239 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009240 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009241 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009242 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9243 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009244 * targetNamespace [attribute].
9245 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009246 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009247 xmlSchemaPCustomErr(ctxt,
9248 XML_SCHEMAP_SRC_IMPORT_1_1,
9249 NULL, NULL, node,
9250 "The value of the attribute 'namespace' must not match "
9251 "the target namespace '%s' of the importing schema",
9252 schema->targetNamespace);
9253 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9254 }
9255 } else {
9256 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009257 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009258 * <schema> must have a targetNamespace [attribute].
9259 */
9260 if (schema->targetNamespace == NULL) {
9261 xmlSchemaPCustomErr(ctxt,
9262 XML_SCHEMAP_SRC_IMPORT_1_2,
9263 NULL, NULL, node,
9264 "The attribute 'namespace' must be existent if "
9265 "the importing schema has no target namespace",
9266 NULL);
9267 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9268 }
9269 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009270 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009271 * Add the namespace to the list of locally imported namespace.
9272 */
9273 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009274 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009275 sizeof(const xmlChar*));
9276 ctxt->sizeLocalImports = 10;
9277 ctxt->nbLocalImports = 0;
9278 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9279 ctxt->sizeLocalImports *= 2;
9280 ctxt->localImports = (const xmlChar **) xmlRealloc(
9281 (xmlChar **) ctxt->localImports,
9282 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9283 }
9284 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9285 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009286 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9289 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009290 schemaLocation, &doc, &targetNamespace, 0);
9291 if (ret != 0) {
9292 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009293 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009294 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009295 } else if (doc != NULL) {
9296 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9297 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009299
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009300 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009301}
9302
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009303/**
9304 * xmlSchemaParseInclude:
9305 * @ctxt: a schema validation context
9306 * @schema: the schema being built
9307 * @node: a subtree containing XML Schema informations
9308 *
9309 * parse a XML schema Include definition
9310 *
William M. Bracke7091952004-05-11 15:09:58 +00009311 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009312 * 1 in case of success.
9313 */
9314static int
9315xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9316 xmlNodePtr node)
9317{
9318 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009319 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009320 xmlDocPtr doc = NULL;
9321 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009322 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009323 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009324 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009325 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009326
9327
9328 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9329 return (-1);
9330
9331 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009332 * Check for illegal attributes.
9333 */
9334 attr = node->properties;
9335 while (attr != NULL) {
9336 if (attr->ns == NULL) {
9337 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009339 xmlSchemaPIllegalAttrErr(ctxt,
9340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9341 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009342 }
9343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009344 xmlSchemaPIllegalAttrErr(ctxt,
9345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9346 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 }
9348 attr = attr->next;
9349 }
9350 /*
9351 * Extract and validate attributes.
9352 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009353 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009354 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009355 * Preliminary step, extract the URI-Reference for the include and
9356 * make an URI from the base.
9357 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009358 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9359 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009360 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009361 xmlChar *uri = NULL;
9362
9363 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9364 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009365 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009366 base = xmlNodeGetBase(node->doc, node);
9367 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009368 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009369 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009370 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009371 xmlFree(base);
9372 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009373 if (uri == NULL) {
9374 xmlSchemaPErr(ctxt,
9375 node,
9376 XML_SCHEMAP_INTERNAL,
9377 "Internal error: xmlSchemaParseInclude, "
9378 "could not build an URI from the schemaLocation.\n",
9379 NULL, NULL);
9380 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009381 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009382 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9383 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009384 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009385 xmlSchemaPMissingAttrErr(ctxt,
9386 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9387 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009388 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009389 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009390 /*
9391 * And now for the children...
9392 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009393 child = node->children;
9394 while (IS_SCHEMA(child, "annotation")) {
9395 /*
9396 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009397 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009398 */
9399 child = child->next;
9400 }
9401 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009402 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009403 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9404 NULL, NULL, node, child, NULL,
9405 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009406 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009407 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009408 * Report self-inclusion.
9409 */
9410 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9411 xmlSchemaPCustomErr(ctxt,
9412 XML_SCHEMAP_SRC_INCLUDE,
9413 NULL, NULL, node,
9414 "The schema document '%s' cannot include itself.",
9415 schemaLocation);
9416 return (XML_SCHEMAP_SRC_INCLUDE);
9417 }
9418 /*
9419 * Check if this one was already processed to avoid incorrect
9420 * duplicate component errors and infinite circular inclusion.
9421 */
9422 include = schema->includes;
9423 while (include != NULL) {
9424 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9425 targetNamespace = include->origTargetNamespace;
9426 if (targetNamespace == NULL) {
9427 /*
9428 * Chameleon include: skip only if it was build for
9429 * the targetNamespace of the including schema.
9430 */
9431 if (xmlStrEqual(schema->targetNamespace,
9432 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009433 goto check_targetNamespace;
9434 }
9435 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009436 goto check_targetNamespace;
9437 }
9438 }
9439 include = include->next;
9440 }
9441 /*
9442 * First step is to parse the input document into an DOM/Infoset
9443 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009444 */
9445 parserCtxt = xmlNewParserCtxt();
9446 if (parserCtxt == NULL) {
9447 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9448 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009449 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009450 }
9451
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009452 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9453 xmlDictFree(parserCtxt->dict);
9454 parserCtxt->dict = ctxt->dict;
9455 xmlDictReference(parserCtxt->dict);
9456 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009457
9458 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009459 NULL, SCHEMAS_PARSE_OPTIONS);
9460 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009461 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009462 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 * TODO: It is not an error for the ·actual value· of the
9464 * schemaLocation [attribute] to fail to resolve it all, in which
9465 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009466 * So do we need a warning report here?
9467 */
9468 xmlSchemaPCustomErr(ctxt,
9469 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009470 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009471 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009472 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009473 }
9474
9475 /*
9476 * Then extract the root of the schema
9477 */
9478 root = xmlDocGetRootElement(doc);
9479 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009480 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009481 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009482 NULL, NULL, node,
9483 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009484 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009485 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009486 }
9487
9488 /*
9489 * Remove all the blank text nodes
9490 */
9491 xmlSchemaCleanupDoc(ctxt, root);
9492
9493 /*
9494 * Check the schemas top level element
9495 */
9496 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009497 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009498 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009499 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009500 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009501 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009502 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009504
William M. Brack2f2a6632004-08-20 23:09:47 +00009505 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009506 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009507 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9508 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9510 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009511check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009512 if (targetNamespace != NULL) {
9513 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009514 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009515 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009516 NULL, NULL, node,
9517 "The target namespace of the included schema "
9518 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009519 "has no target namespace",
9520 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009521 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009522 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9523 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009524 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009525 NULL, NULL, node,
9526 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009527 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009528 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009531 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009532 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009533 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009534 } else
9535 wasConvertingNs = 1;
9536 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009537
9538 if (include != NULL)
9539 goto exit;
9540
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009541 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009542 * URGENT TODO: If the schema is a chameleon-include then copy the
9543 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009544 * of those components, do nothing otherwise.
9545 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009546 * for every destinct including targetNamespace; thus not performant at
9547 * the moment.
9548 * TODO: Check when the namespace in wildcards for chameleons needs
9549 * to be converted: before we built wildcard intersections or after.
9550 */
9551 /*
9552 * Register the include.
9553 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009554 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9555 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009556 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9557 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009558 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009559 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009560 include->next = schema->includes;
9561 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009562 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009563 * TODO: Use the resolved URI for the this location, since it might
9564 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009565 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009566 include->schemaLocation = schemaLocation;
9567 include->doc = doc;
9568 /*
9569 * In case of chameleons, the original target namespace will differ
9570 * from the resulting namespace.
9571 */
9572 include->origTargetNamespace = targetNamespace;
9573 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009574#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009575 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009576 xmlGenericError(xmlGenericErrorContext,
9577 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9578 " into TNS '%s'\n", schemaLocation,
9579 targetNamespace, schema->targetNamespace);
9580 else
9581 xmlGenericError(xmlGenericErrorContext,
9582 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9583 targetNamespace);
9584#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009585 /*
9586 * Compile the included schema.
9587 */
9588 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9589
9590exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009591 /*
9592 * Remove the converting flag.
9593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009594 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009595 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009596 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009597 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009598
9599exit_invalid:
9600 if (doc != NULL) {
9601 if (include != NULL)
9602 include->doc = NULL;
9603 xmlFreeDoc(doc);
9604 }
9605 return (ctxt->err);
9606
9607exit_failure:
9608 if (doc != NULL) {
9609 if (include != NULL)
9610 include->doc = NULL;
9611 xmlFreeDoc(doc);
9612 }
9613 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009614}
9615
9616/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009617 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009618 * @ctxt: a schema validation context
9619 * @schema: the schema being built
9620 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009621 * @type: the "compositor" type
9622 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009623 *
9624 * parse a XML schema Sequence definition
9625 * *WARNING* this interface is highly subject to change
9626 *
William M. Bracke7091952004-05-11 15:09:58 +00009627 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009628 * 1 in case of success.
9629 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009630static xmlSchemaTreeItemPtr
9631xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9632 xmlNodePtr node, xmlSchemaTypeType type,
9633 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009634{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009635 xmlSchemaModelGroupPtr item;
9636 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009637 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009638 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009639 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009640 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009641
9642 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009643 return (NULL);
9644 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009645 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009646 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009647 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9648 if (item == NULL)
9649 return (NULL);
9650
9651 if (withParticle) {
9652 if (type == XML_SCHEMA_TYPE_ALL) {
9653 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009654 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009655 } else {
9656 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009657 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9658 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9659 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009660 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009661 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9662 /*
9663 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009664 */
9665 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9666 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009667 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009668 particle->children = (xmlSchemaTreeItemPtr) item;
9669 /*
9670 * Check for illegal attributes.
9671 */
9672 attr = node->properties;
9673 while (attr != NULL) {
9674 if (attr->ns == NULL) {
9675 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9676 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9677 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 xmlSchemaPIllegalAttrErr(ctxt,
9679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9680 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009681 }
9682 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009683 xmlSchemaPIllegalAttrErr(ctxt,
9684 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9685 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009686 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009687 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009688 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009689 } else {
9690 /*
9691 * Check for illegal attributes.
9692 */
9693 attr = node->properties;
9694 while (attr != NULL) {
9695 if (attr->ns == NULL) {
9696 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009697 xmlSchemaPIllegalAttrErr(ctxt,
9698 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9699 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009700 }
9701 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009702 xmlSchemaPIllegalAttrErr(ctxt,
9703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9704 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009705 }
9706 attr = attr->next;
9707 }
9708
William M. Brack2f2a6632004-08-20 23:09:47 +00009709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009710
William M. Brack2f2a6632004-08-20 23:09:47 +00009711 /*
9712 * Extract and validate attributes.
9713 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009714 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009715 /*
9716 * And now for the children...
9717 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009718 child = node->children;
9719 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009720 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009721 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009723 oldcontainer = ctxt->container;
9724 ctxt->container = container;
9725 if (type == XML_SCHEMA_TYPE_ALL) {
9726 xmlSchemaParticlePtr part, last = NULL;
9727
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009728 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009729 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9730 schema, child, 0);
9731 if (part != NULL) {
9732 if (part->minOccurs > 1)
9733 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009734 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009735 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9736 if (part->maxOccurs > 1)
9737 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009738 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009739 "Invalid value for maxOccurs (must be 0 or 1)",
9740 NULL);
9741 if (last == NULL)
9742 item->children = (xmlSchemaTreeItemPtr) part;
9743 else
9744 last->next = (xmlSchemaTreeItemPtr) part;
9745 last = part;
9746 }
9747 child = child->next;
9748 }
9749 if (child != NULL) {
9750 xmlSchemaPContentErr(ctxt,
9751 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9752 NULL, NULL, node, child, NULL,
9753 "(annotation?, (annotation?, element*)");
9754 }
9755 } else {
9756 /* choice + sequence */
9757 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9758
9759 while ((IS_SCHEMA(child, "element")) ||
9760 (IS_SCHEMA(child, "group")) ||
9761 (IS_SCHEMA(child, "any")) ||
9762 (IS_SCHEMA(child, "choice")) ||
9763 (IS_SCHEMA(child, "sequence"))) {
9764
9765 if (IS_SCHEMA(child, "element")) {
9766 part = (xmlSchemaTreeItemPtr)
9767 xmlSchemaParseElement(ctxt, schema, child, 0);
9768 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009769 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009770 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9771 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009772 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009773 xmlSchemaParseAny(ctxt, schema, child);
9774 } else if (IS_SCHEMA(child, "choice")) {
9775 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9776 XML_SCHEMA_TYPE_CHOICE, 1);
9777 } else if (IS_SCHEMA(child, "sequence")) {
9778 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9779 XML_SCHEMA_TYPE_SEQUENCE, 1);
9780 }
9781 if (part != NULL) {
9782 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009783 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009784 else
9785 last->next = part;
9786 last = part;
9787 }
9788 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009790 if (child != NULL) {
9791 xmlSchemaPContentErr(ctxt,
9792 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9793 NULL, NULL, node, child, NULL,
9794 "(annotation?, (element | group | choice | sequence | any)*)");
9795 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009796 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009797 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009798 if (withParticle) {
9799 if ((min == 0) && (max == 0))
9800 return (NULL);
9801 else
9802 return ((xmlSchemaTreeItemPtr) particle);
9803 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009804 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009805}
9806
9807/**
9808 * xmlSchemaParseRestriction:
9809 * @ctxt: a schema validation context
9810 * @schema: the schema being built
9811 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009812 *
9813 * parse a XML schema Restriction definition
9814 * *WARNING* this interface is highly subject to change
9815 *
9816 * Returns the type definition or NULL in case of error
9817 */
9818static xmlSchemaTypePtr
9819xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009821{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009822 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009823 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009824 char buf[30];
9825 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009826 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009827
9828 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9829 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009830 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009831 type = ctxt->ctxtType;
9832 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009833
9834 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009835 * TODO: Is the container needed at all? the anonymous
9836 * items inside should generate unique names already.
9837 */
9838 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009839 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009840 /*
9841 * Check for illegal attributes.
9842 */
9843 attr = node->properties;
9844 while (attr != NULL) {
9845 if (attr->ns == NULL) {
9846 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9847 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009848 xmlSchemaPIllegalAttrErr(ctxt,
9849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9850 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 }
9852 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009853 xmlSchemaPIllegalAttrErr(ctxt,
9854 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9855 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009856 }
9857 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 /*
9860 * Extract and validate attributes.
9861 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009862 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009863 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009864 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009865 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009866 /*
9867 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9868 * among its [children]), the simple type definition which is
9869 * the {content type} of the type definition ·resolved· to by
9870 * the ·actual value· of the base [attribute]"
9871 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009872 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009873 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009874 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009875 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009876 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009877 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009878 XML_SCHEMAP_S4S_ATTR_MISSING,
9879 type, node, "base", NULL);
9880 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009881 /*
9882 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009883 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009884 child = node->children;
9885 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009886 /*
9887 * Add the annotation to the simple type ancestor.
9888 */
9889 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9890 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009891 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009892 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009893 oldcontainer = ctxt->container;
9894 ctxt->container = container;
9895 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9896 /*
9897 * Corresponds to <simpleType><restriction><simpleType>.
9898 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009899 if (IS_SCHEMA(child, "simpleType")) {
9900 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009901 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009902 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009903 * Either the base [attribute] or the simpleType [child] of the
9904 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009905 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009906 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009907 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009908 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009909 "The attribute 'base' and the <simpleType> child are "
9910 "mutually exclusive", NULL);
9911 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009912 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009913 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009914 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009915 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009917 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009918 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9919 NULL, NULL, node, child,
9920 "Either the attribute 'base' or a <simpleType> child "
9921 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009922 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9924 /*
9925 * Corresponds to <complexType><complexContent><restriction>...
9926 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009927 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009928 * Model groups <all>, <choice> and <sequence>.
9929 */
9930 if (IS_SCHEMA(child, "all")) {
9931 type->subtypes = (xmlSchemaTypePtr)
9932 xmlSchemaParseModelGroup(ctxt, schema, child,
9933 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009934 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009935 } else if (IS_SCHEMA(child, "choice")) {
9936 type->subtypes = (xmlSchemaTypePtr)
9937 xmlSchemaParseModelGroup(ctxt,
9938 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9939 child = child->next;
9940 } else if (IS_SCHEMA(child, "sequence")) {
9941 type->subtypes = (xmlSchemaTypePtr)
9942 xmlSchemaParseModelGroup(ctxt, schema, child,
9943 XML_SCHEMA_TYPE_SEQUENCE, 1);
9944 child = child->next;
9945 /*
9946 * Model group reference <group>.
9947 */
9948 } else if (IS_SCHEMA(child, "group")) {
9949 type->subtypes = (xmlSchemaTypePtr)
9950 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9951 child = child->next;
9952 }
9953 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009954 /*
9955 * Corresponds to <complexType><simpleContent><restriction>...
9956 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009957 * "1.1 the simple type definition corresponding to the <simpleType>
9958 * among the [children] of <restriction> if there is one;"
9959 */
9960 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009961 /*
9962 * We will store the to-be-restricted simple type in
9963 * type->contentTypeDef *temporarily*.
9964 */
9965 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009966 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009967 if ( type->contentTypeDef == NULL)
9968 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009969 child = child->next;
9970 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009971 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009972
9973 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009974 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009975 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009976 /*
9977 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009978 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009979 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009980
Daniel Veillard01fa6152004-06-29 17:04:39 +00009981 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009982 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009983 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009984 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009985 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9986 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009987 * *Single Facet Value*
9988 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009989 while ((IS_SCHEMA(child, "minInclusive")) ||
9990 (IS_SCHEMA(child, "minExclusive")) ||
9991 (IS_SCHEMA(child, "maxInclusive")) ||
9992 (IS_SCHEMA(child, "maxExclusive")) ||
9993 (IS_SCHEMA(child, "totalDigits")) ||
9994 (IS_SCHEMA(child, "fractionDigits")) ||
9995 (IS_SCHEMA(child, "pattern")) ||
9996 (IS_SCHEMA(child, "enumeration")) ||
9997 (IS_SCHEMA(child, "whiteSpace")) ||
9998 (IS_SCHEMA(child, "length")) ||
9999 (IS_SCHEMA(child, "maxLength")) ||
10000 (IS_SCHEMA(child, "minLength"))) {
10001 facet = xmlSchemaParseFacet(ctxt, schema, child);
10002 if (facet != NULL) {
10003 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010005 else
10006 lastfacet->next = facet;
10007 lastfacet = facet;
10008 lastfacet->next = NULL;
10009 }
10010 child = child->next;
10011 }
10012 /*
10013 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010014 */
10015 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010016 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10017
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010018 facet = type->facets;
10019 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010020 facetLink = (xmlSchemaFacetLinkPtr)
10021 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010022 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010023 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010024 xmlFree(facetLink);
10025 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010026 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010027 facetLink->facet = facet;
10028 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010029 if (lastFacetLink == NULL)
10030 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010031 else
10032 lastFacetLink->next = facetLink;
10033 lastFacetLink = facetLink;
10034 facet = facet->next;
10035 } while (facet != NULL);
10036 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010037 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010038 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10039 /*
10040 * Attribute uses/declarations.
10041 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010042 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010043 /*
10044 * Attribute wildcard.
10045 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010046 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010047 type->attributeWildcard =
10048 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010049 child = child->next;
10050 }
10051 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010052 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010053 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10054 xmlSchemaPContentErr(ctxt,
10055 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010056 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010057 "annotation?, (group | all | choice | sequence)?, "
10058 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010059 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010060 xmlSchemaPContentErr(ctxt,
10061 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010062 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010063 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10064 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10065 "length | minLength | maxLength | enumeration | whiteSpace | "
10066 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10067 } else {
10068 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 xmlSchemaPContentErr(ctxt,
10070 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010071 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010072 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10073 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10074 "length | minLength | maxLength | enumeration | whiteSpace | "
10075 "pattern)*))");
10076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010078 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010080}
10081
10082/**
10083 * xmlSchemaParseExtension:
10084 * @ctxt: a schema validation context
10085 * @schema: the schema being built
10086 * @node: a subtree containing XML Schema informations
10087 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010088 * Parses an <extension>, which is found inside a
10089 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010090 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010092 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010093 */
10094static xmlSchemaTypePtr
10095xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010096 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010097{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010098 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010099 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 char buf[30];
10101 const xmlChar *oldcontainer, *container;
10102 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010103
10104 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10105 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010106 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010107 type = ctxt->ctxtType;
10108 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010109
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010110 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10111 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10112 /*
10113 * Check for illegal attributes.
10114 */
10115 attr = node->properties;
10116 while (attr != NULL) {
10117 if (attr->ns == NULL) {
10118 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10119 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010120 xmlSchemaPIllegalAttrErr(ctxt,
10121 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10122 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010123 }
10124 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010125 xmlSchemaPIllegalAttrErr(ctxt,
10126 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10127 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010128 }
10129 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010130 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010131
10132 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010133
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010134 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010135 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010136 */
10137 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010138 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10139 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010140 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010141 XML_SCHEMAP_S4S_ATTR_MISSING,
10142 NULL, node, "base", NULL);
10143 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 /*
10145 * And now for the children...
10146 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010147 child = node->children;
10148 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010149 /*
10150 * Add the annotation to the type ancestor.
10151 */
10152 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10153 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010154 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010155 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010156 oldcontainer = ctxt->container;
10157 ctxt->container = container;
10158 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10159 /*
10160 * Corresponds to <complexType><complexContent><extension>... and:
10161 *
10162 * Model groups <all>, <choice>, <sequence> and <group>.
10163 */
10164 if (IS_SCHEMA(child, "all")) {
10165 type->subtypes = (xmlSchemaTypePtr)
10166 xmlSchemaParseModelGroup(ctxt, schema,
10167 child, XML_SCHEMA_TYPE_ALL, 1);
10168 child = child->next;
10169 } else if (IS_SCHEMA(child, "choice")) {
10170 type->subtypes = (xmlSchemaTypePtr)
10171 xmlSchemaParseModelGroup(ctxt, schema,
10172 child, XML_SCHEMA_TYPE_CHOICE, 1);
10173 child = child->next;
10174 } else if (IS_SCHEMA(child, "sequence")) {
10175 type->subtypes = (xmlSchemaTypePtr)
10176 xmlSchemaParseModelGroup(ctxt, schema,
10177 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10178 child = child->next;
10179 } else if (IS_SCHEMA(child, "group")) {
10180 type->subtypes = (xmlSchemaTypePtr)
10181 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10182 child = child->next;
10183 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185 if (child != NULL) {
10186 /*
10187 * Attribute uses/declarations.
10188 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010189 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010190 /*
10191 * Attribute wildcard.
10192 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010193 if (IS_SCHEMA(child, "anyAttribute")) {
10194 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010195 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10196 child = child->next;
10197 }
10198 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010199 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010200 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10201 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010202 xmlSchemaPContentErr(ctxt,
10203 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010204 NULL, NULL, node, child, NULL,
10205 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010206 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010207 } else {
10208 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010209 xmlSchemaPContentErr(ctxt,
10210 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010211 NULL, NULL, node, child, NULL,
10212 "(annotation?, ((attribute | attributeGroup)*, "
10213 "anyAttribute?))");
10214 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010215 }
10216 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010217 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010218}
10219
10220/**
10221 * xmlSchemaParseSimpleContent:
10222 * @ctxt: a schema validation context
10223 * @schema: the schema being built
10224 * @node: a subtree containing XML Schema informations
10225 *
10226 * parse a XML schema SimpleContent definition
10227 * *WARNING* this interface is highly subject to change
10228 *
10229 * Returns the type definition or NULL in case of error
10230 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010231static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010232xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10233 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010234{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010235 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010236 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010237 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010238
10239 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010240 return (-1);
10241 /* Not a component, don't create it. */
10242 type = ctxt->ctxtType;
10243 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10244 /*
10245 * Check for illegal attributes.
10246 */
10247 attr = node->properties;
10248 while (attr != NULL) {
10249 if (attr->ns == NULL) {
10250 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010251 xmlSchemaPIllegalAttrErr(ctxt,
10252 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10253 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 }
10255 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010256 xmlSchemaPIllegalAttrErr(ctxt,
10257 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10258 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010259 }
10260 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010261 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010262
10263 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010264
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010265 /*
10266 * And now for the children...
10267 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010268 child = node->children;
10269 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010270 /*
10271 * Add the annotation to the complex type ancestor.
10272 */
10273 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10274 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010275 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010276 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010277 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010278 xmlSchemaParseRestriction(ctxt, schema, child,
10279 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010281 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010282 xmlSchemaParseExtension(ctxt, schema, child,
10283 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010284 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010285 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010286 if (child != NULL) {
10287 xmlSchemaPContentErr(ctxt,
10288 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010289 NULL, NULL, node, child, NULL,
10290 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010291 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010292 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010293}
10294
10295/**
10296 * xmlSchemaParseComplexContent:
10297 * @ctxt: a schema validation context
10298 * @schema: the schema being built
10299 * @node: a subtree containing XML Schema informations
10300 *
10301 * parse a XML schema ComplexContent definition
10302 * *WARNING* this interface is highly subject to change
10303 *
10304 * Returns the type definition or NULL in case of error
10305 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010307xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10308 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010309{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010310 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010311 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010312 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010313
10314 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010315 return (-1);
10316 /* Not a component, don't create it. */
10317 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010318 /*
10319 * Check for illegal attributes.
10320 */
10321 attr = node->properties;
10322 while (attr != NULL) {
10323 if (attr->ns == NULL) {
10324 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010325 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010326 {
10327 xmlSchemaPIllegalAttrErr(ctxt,
10328 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10329 NULL, NULL, attr);
10330 }
10331 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10332 xmlSchemaPIllegalAttrErr(ctxt,
10333 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10334 NULL, NULL, attr);
10335 }
10336 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010337 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010338
10339 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10340
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010341 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010342 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010343 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010344 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10345 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10346 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010347 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010348 child = node->children;
10349 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010350 /*
10351 * Add the annotation to the complex type ancestor.
10352 */
10353 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10354 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010355 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010356 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010357 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010358 xmlSchemaParseRestriction(ctxt, schema, child,
10359 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010360 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010361 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010362 xmlSchemaParseExtension(ctxt, schema, child,
10363 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010364 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010365 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010366 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 xmlSchemaPContentErr(ctxt,
10368 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10369 NULL, NULL, node, child,
10370 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010371 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010372 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010373}
10374
10375/**
10376 * xmlSchemaParseComplexType:
10377 * @ctxt: a schema validation context
10378 * @schema: the schema being built
10379 * @node: a subtree containing XML Schema informations
10380 *
10381 * parse a XML schema Complex Type definition
10382 * *WARNING* this interface is highly subject to change
10383 *
10384 * Returns the type definition or NULL in case of error
10385 */
10386static xmlSchemaTypePtr
10387xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010388 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010389{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010390 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010391 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010392 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010393 xmlAttrPtr attr;
10394 const xmlChar *attrValue;
10395 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010396 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010397 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010398
Daniel Veillard4255d502002-04-16 15:50:10 +000010399
10400 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10401 return (NULL);
10402
Daniel Veillard01fa6152004-06-29 17:04:39 +000010403 ctxtType = ctxt->ctxtType;
10404
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010405 if (topLevel) {
10406 attr = xmlSchemaGetPropNode(node, "name");
10407 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010408 xmlSchemaPMissingAttrErr(ctxt,
10409 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010410 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010411 } else if (xmlSchemaPValAttrNode(ctxt,
10412 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010413 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10414 return (NULL);
10415 }
10416 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010418 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 /*
10420 * Parse as local complex type definition.
10421 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010422 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010423 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10424 if (type == NULL)
10425 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010426 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010427 type->node = node;
10428 type->type = XML_SCHEMA_TYPE_COMPLEX;
10429 /*
10430 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010431 */
10432 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010433 /*
10434 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010436 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 if (type == NULL)
10438 return (NULL);
10439 type->node = node;
10440 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010441 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010442 }
10443 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010444 /*
10445 * Handle attributes.
10446 */
10447 attr = node->properties;
10448 while (attr != NULL) {
10449 if (attr->ns == NULL) {
10450 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10451 /*
10452 * Attribute "id".
10453 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010454 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10455 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010456 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10457 /*
10458 * Attribute "mixed".
10459 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010460 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010462 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10463 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010464 /*
10465 * Attributes of global complex type definitions.
10466 */
10467 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10468 /* Pass. */
10469 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10470 /*
10471 * Attribute "abstract".
10472 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010473 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10474 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010475 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10476 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10477 /*
10478 * Attribute "final".
10479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010480 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010481 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010482 if (xmlSchemaPValAttrBlockFinal(attrValue,
10483 &(type->flags),
10484 -1,
10485 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10486 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10487 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010488 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010489 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010490 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010491 type, (xmlNodePtr) attr, NULL,
10492 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010494 } else
10495 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010496 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10497 /*
10498 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010499 */
10500 attrValue = xmlSchemaGetNodeContent(ctxt,
10501 (xmlNodePtr) attr);
10502 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010503 -1,
10504 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010505 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010506 -1, -1, -1) != 0) {
10507 xmlSchemaPSimpleTypeErr(ctxt,
10508 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010509 type, (xmlNodePtr) attr, NULL,
10510 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010511 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010512 } else
10513 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010514 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010515 xmlSchemaPIllegalAttrErr(ctxt,
10516 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010517 &des, type, attr);
10518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010519 } else {
10520 xmlSchemaPIllegalAttrErr(ctxt,
10521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010522 &des, type, attr);
10523 }
10524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010525 xmlSchemaPIllegalAttrErr(ctxt,
10526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10527 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010528 }
10529 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010531 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010532 /*
10533 * Apply default "block" values.
10534 */
10535 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10536 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10537 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10538 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010540 if (! final) {
10541 /*
10542 * Apply default "block" values.
10543 */
10544 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10545 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10546 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10547 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10548 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010549 /*
10550 * And now for the children...
10551 */
10552 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010553 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010554 child = node->children;
10555 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010556 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010558 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010559 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010560 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010561 /*
10562 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010563 * Specifying mixed='true' when the <simpleContent>
10564 * alternative is chosen has no effect
10565 */
William M. Bracke7091952004-05-11 15:09:58 +000010566 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10567 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010568 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010569 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010570 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010571 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10572 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010573 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010575 /*
10576 * SPEC
10577 * "...the third alternative (neither <simpleContent> nor
10578 * <complexContent>) is chosen. This case is understood as shorthand
10579 * for complex content restricting the ·ur-type definition·, and the
10580 * details of the mappings should be modified as necessary.
10581 */
10582 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10583 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010584 /*
10585 * Parse model groups.
10586 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010587 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010588 type->subtypes = (xmlSchemaTypePtr)
10589 xmlSchemaParseModelGroup(ctxt, schema, child,
10590 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010591 child = child->next;
10592 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010593 type->subtypes = (xmlSchemaTypePtr)
10594 xmlSchemaParseModelGroup(ctxt, schema, child,
10595 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010596 child = child->next;
10597 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010598 type->subtypes = (xmlSchemaTypePtr)
10599 xmlSchemaParseModelGroup(ctxt, schema, child,
10600 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010601 child = child->next;
10602 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010603 type->subtypes = (xmlSchemaTypePtr)
10604 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010605 child = child->next;
10606 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010607 /*
10608 * Parse attribute decls/refs.
10609 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010610 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010611 /*
10612 * Parse attribute wildcard.
10613 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010614 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010615 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10616 child = child->next;
10617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010618 }
10619 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010620 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010621 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010622 &des, type, node, child,
10623 NULL, "(annotation?, (simpleContent | complexContent | "
10624 "((group | all | choice | sequence)?, ((attribute | "
10625 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010626 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010627 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010628 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010629 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010630 return (type);
10631}
10632
Daniel Veillard4255d502002-04-16 15:50:10 +000010633/**
10634 * xmlSchemaParseSchema:
10635 * @ctxt: a schema validation context
10636 * @node: a subtree containing XML Schema informations
10637 *
10638 * parse a XML schema definition from a node set
10639 * *WARNING* this interface is highly subject to change
10640 *
10641 * Returns the internal XML Schema structure built from the resource or
10642 * NULL in case of error
10643 */
10644static xmlSchemaPtr
10645xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10646{
10647 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010648 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010649 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010650 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010651
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010652 /*
10653 * This one is called by xmlSchemaParse only and is used if
10654 * the schema to be parsed was specified via the API; i.e. not
10655 * automatically by the validated instance document.
10656 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010657 if ((ctxt == NULL) || (node == NULL))
10658 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010659 nberrors = ctxt->nberrors;
10660 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010661 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010662 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010663 xmlSchemaImportPtr import;
10664
Daniel Veillard4255d502002-04-16 15:50:10 +000010665 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010666 if (schema == NULL)
10667 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010668 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010669 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010670 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010671 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10672 /*
10673 * TODO: Should we proceed with an invalid target namespace?
10674 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010675 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010676 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10677 /*
10678 * We are parsing the schema for schema!
10679 */
10680 ctxt->isS4S = 1;
10681 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010682 } else {
10683 schema->targetNamespace = NULL;
10684 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010685 /*
10686 * Add the current ns name and location to the import table;
10687 * this is needed to have a consistent mechanism, regardless
10688 * if all schemata are constructed dynamically fired by the
10689 * instance or if the schema to be used was specified via
10690 * the API.
10691 */
10692 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10693 schema->targetNamespace);
10694 if (import == NULL) {
10695 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10696 NULL, NULL, (xmlNodePtr) ctxt->doc,
10697 "Internal error: xmlSchemaParseSchema, "
10698 "failed to add an import entry", NULL);
10699 xmlSchemaFree(schema);
10700 schema = NULL;
10701 return (NULL);
10702 }
10703 import->schemaLocation = ctxt->URL;
10704 /*
10705 * NOTE: We won't set the doc here, otherwise it will be freed
10706 * if the import struct is freed.
10707 * import->doc = ctxt->doc;
10708 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010709 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010710 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10711 } else {
10712 xmlDocPtr doc;
10713
10714 doc = node->doc;
10715
10716 if ((doc != NULL) && (doc->URL != NULL)) {
10717 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10718 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010719 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010720 } else {
10721 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10722 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010723 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010724 }
10725 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010726 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010727 if (ctxt->nberrors != 0) {
10728 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010729 xmlSchemaFree(schema);
10730 schema = NULL;
10731 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010732 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010733 if (schema != NULL)
10734 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010735 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010736#ifdef DEBUG
10737 if (schema == NULL)
10738 xmlGenericError(xmlGenericErrorContext,
10739 "xmlSchemaParse() failed\n");
10740#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010741 return (schema);
10742}
10743
10744/************************************************************************
10745 * *
10746 * Validating using Schemas *
10747 * *
10748 ************************************************************************/
10749
10750/************************************************************************
10751 * *
10752 * Reading/Writing Schemas *
10753 * *
10754 ************************************************************************/
10755
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010756#if 0 /* Will be enabled if it is clear what options are needed. */
10757/**
10758 * xmlSchemaParserCtxtSetOptions:
10759 * @ctxt: a schema parser context
10760 * @options: a combination of xmlSchemaParserOption
10761 *
10762 * Sets the options to be used during the parse.
10763 *
10764 * Returns 0 in case of success, -1 in case of an
10765 * API error.
10766 */
10767static int
10768xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10769 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010770
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010771{
10772 int i;
10773
10774 if (ctxt == NULL)
10775 return (-1);
10776 /*
10777 * WARNING: Change the start value if adding to the
10778 * xmlSchemaParseOption.
10779 */
10780 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10781 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010782 return (-1);
10783 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010784 }
10785 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010786 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010787}
10788
10789/**
10790 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010791 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010792 *
10793 * Returns the option combination of the parser context.
10794 */
10795static int
10796xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010797
10798{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010799 if (ctxt == NULL)
10800 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010801 else
10802 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010803}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010804#endif
10805
Daniel Veillard4255d502002-04-16 15:50:10 +000010806/**
10807 * xmlSchemaNewParserCtxt:
10808 * @URL: the location of the schema
10809 *
10810 * Create an XML Schemas parse context for that file/resource expected
10811 * to contain an XML Schemas file.
10812 *
10813 * Returns the parser context or NULL in case of error
10814 */
10815xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010816xmlSchemaNewParserCtxt(const char *URL)
10817{
Daniel Veillard4255d502002-04-16 15:50:10 +000010818 xmlSchemaParserCtxtPtr ret;
10819
10820 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010821 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010822
10823 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10824 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010825 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010826 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010827 return (NULL);
10828 }
10829 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010830 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010831 ret->dict = xmlDictCreate();
10832 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010833 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010834 return (ret);
10835}
10836
10837/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010838 * xmlSchemaNewMemParserCtxt:
10839 * @buffer: a pointer to a char array containing the schemas
10840 * @size: the size of the array
10841 *
10842 * Create an XML Schemas parse context for that memory buffer expected
10843 * to contain an XML Schemas file.
10844 *
10845 * Returns the parser context or NULL in case of error
10846 */
10847xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010848xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10849{
Daniel Veillard6045c902002-10-09 21:13:59 +000010850 xmlSchemaParserCtxtPtr ret;
10851
10852 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010853 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010854
10855 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10856 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010857 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010858 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010859 return (NULL);
10860 }
10861 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10862 ret->buffer = buffer;
10863 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010864 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010865 return (ret);
10866}
10867
10868/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010869 * xmlSchemaNewDocParserCtxt:
10870 * @doc: a preparsed document tree
10871 *
10872 * Create an XML Schemas parse context for that document.
10873 * NB. The document may be modified during the parsing process.
10874 *
10875 * Returns the parser context or NULL in case of error
10876 */
10877xmlSchemaParserCtxtPtr
10878xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10879{
10880 xmlSchemaParserCtxtPtr ret;
10881
10882 if (doc == NULL)
10883 return (NULL);
10884
10885 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10886 if (ret == NULL) {
10887 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10888 NULL);
10889 return (NULL);
10890 }
10891 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10892 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010893 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010894 /* The application has responsibility for the document */
10895 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010896
10897 return (ret);
10898}
10899
10900/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010901 * xmlSchemaFreeParserCtxt:
10902 * @ctxt: the schema parser context
10903 *
10904 * Free the resources associated to the schema parser context
10905 */
10906void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010907xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10908{
Daniel Veillard4255d502002-04-16 15:50:10 +000010909 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010910 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010911 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010912 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010913 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010914 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010915 xmlFree(ctxt->assemble);
10916 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010917 if (ctxt->vctxt != NULL) {
10918 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10919 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010920 if (ctxt->localImports != NULL)
10921 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010922 if (ctxt->substGroups != NULL)
10923 xmlHashFree(ctxt->substGroups,
10924 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010925 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010926 xmlFree(ctxt);
10927}
10928
10929/************************************************************************
10930 * *
10931 * Building the content models *
10932 * *
10933 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010934
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010935static void
10936xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010937 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010938{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010939 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010940 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010941 xmlSchemaSubstGroupPtr substGroup;
10942 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010943
10944 elemDecl = (xmlSchemaElementPtr) particle->children;
10945 /*
10946 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010947 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010948 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010949 if (end == NULL)
10950 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010951 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10952 if (substGroup == NULL) {
10953 xmlSchemaPErr(pctxt, GET_NODE(particle),
10954 XML_SCHEMAP_INTERNAL,
10955 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10956 "declaration is marked having a subst. group but none "
10957 "available.\n", elemDecl->name, NULL);
10958 return;
10959 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010960 if (counter >= 0) {
10961 /*
10962 * NOTE that we put the declaration in, even if it's abstract,
10963 */
10964 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10965 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10966 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10967 /*
10968 * Add subst. group members.
10969 */
10970 for (i = 0; i < substGroup->members->nbItems; i++) {
10971 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10972 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10973 member->name, member->targetNamespace, member);
10974 }
10975 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010976 /*
10977 * NOTE that we put the declaration in, even if it's abstract,
10978 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010979 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010980 xmlAutomataNewTransition2(pctxt->am,
10981 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010982 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10983 /*
10984 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010985 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010986 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010987 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010988 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10989 member->name, member->targetNamespace,
10990 1, 1, member);
10991 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010992 }
10993 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010994 xmlAutomataStatePtr hop;
10995 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10996 UNBOUNDED : particle->maxOccurs - 1;
10997 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10998
10999 counter =
11000 xmlAutomataNewCounter(pctxt->am, minOccurs,
11001 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011002 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011003
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011004 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011005 xmlAutomataNewTransition2(pctxt->am,
11006 start, NULL,
11007 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011008 hop);
11009 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000011010 * Add subst. group members.
11011 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011012 for (i = 0; i < substGroup->members->nbItems; i++) {
11013 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11014 xmlAutomataNewEpsilon(pctxt->am,
11015 xmlAutomataNewTransition2(pctxt->am,
11016 start, NULL,
11017 member->name, member->targetNamespace, member),
11018 hop);
11019 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011020 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11021 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11022 }
11023 if (particle->minOccurs == 0)
11024 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011025 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011026}
11027
11028static void
11029xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11030 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011031{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011032 if (((xmlSchemaElementPtr) particle->children)->flags &
11033 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011034 /*
11035 * Substitution groups.
11036 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011037 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011038 } else {
11039 xmlSchemaElementPtr elemDecl;
11040 xmlAutomataStatePtr start;
11041
11042 elemDecl = (xmlSchemaElementPtr) particle->children;
11043
11044 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011045 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011046 if (particle->maxOccurs == 1) {
11047 start = ctxt->state;
11048 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011049 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11050 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11051 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011052 /* Special case. */
11053 start = ctxt->state;
11054 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11055 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011056 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011057 } else {
11058 int counter;
11059 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11060 UNBOUNDED : particle->maxOccurs - 1;
11061 int minOccurs = particle->minOccurs < 1 ?
11062 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011063
11064 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011065 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11066 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11067 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11068 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11069 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11070 NULL, counter);
11071 }
11072 if (particle->minOccurs == 0)
11073 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11074 }
11075}
11076
Daniel Veillard4255d502002-04-16 15:50:10 +000011077/**
11078 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011079 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011080 * @particle: the particle component
11081 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011082 *
11083 * Generate the automata sequence needed for that type
11084 */
11085static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011086xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011087 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011088 const xmlChar * name)
11089{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011090 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011091 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011092 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011094 if (particle->children == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011095 PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011096 return;
11097 }
11098
11099 switch (particle->children->type) {
11100 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011102 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011104
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011105 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011106
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011107 start = pctxt->state;
11108 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011109
11110 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011111 if (wild->any == 1) {
11112 /*
11113 * We need to add both transitions:
11114 *
11115 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011116 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011117 pctxt->state =
11118 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011119 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011120 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 /*
11122 * 2. the {"*"} for elements in no namespace.
11123 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011124 pctxt->state =
11125 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011126 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011127 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128
11129 } else if (wild->nsSet != NULL) {
11130 ns = wild->nsSet;
11131 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011132 pctxt->state = start;
11133 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
11134 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
11135 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011136 ns = ns->next;
11137 } while (ns != NULL);
11138
11139 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011140
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011141 /*
11142 * Lead nodes with the negated namespace to the sink-state
11143 * {"*", "##other"}.
11144 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011145 pctxt->state = xmlAutomataNewTransition2(pctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011146 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011147 /*
11148 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011149 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011150 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011151 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011153 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011154 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011155 } else {
11156 int counter;
11157 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011158 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011159 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011160 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011162
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011163 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11164 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011165 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011166 pctxt->state =
11167 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011168 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011169 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
11170 pctxt->state =
11171 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011172 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011173 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011174 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011175 ns = wild->nsSet;
11176 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011177 pctxt->state =
11178 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011179 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011180 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011181 ns = ns->next;
11182 } while (ns != NULL);
11183
11184 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011185 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000011186 start, hop, BAD_CAST "*", wild->negNsSet->value,
11187 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011188 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011189 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11190 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011191 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011192 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011193 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011194 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011195 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011196 break;
11197 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011198 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011199 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011200 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011201 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011202 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011203
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011204 /*
11205 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011206 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011207 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011208 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11209 sub = particle->children->children;
11210 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011211 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212 (xmlSchemaParticlePtr) sub, name);
11213 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011214 }
11215 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011216 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011217
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 if (particle->maxOccurs >= UNBOUNDED) {
11219 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011220 xmlAutomataStatePtr tmp;
11221 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011222
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011223 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011224 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011225 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011226
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011227 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011229
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011230 sub = particle->children->children;
11231 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011232 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233 (xmlSchemaParticlePtr) sub, name);
11234 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011235 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011236 tmp = pctxt->state;
11237 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011238 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011239 pctxt->state =
11240 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011241 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011242
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011243 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011244 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000011245 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011246 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011247
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 sub = particle->children->children;
11249 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011250 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011251 (xmlSchemaParticlePtr) sub, name);
11252 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011253 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011254 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011255 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011256 /*
11257 * epsilon needed to block previous trans from
11258 * being allowed to enter back from another
11259 * construct
11260 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011261 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
11262 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011263 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011264 xmlAutomataNewEpsilon(pctxt->am,
11265 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011266 }
11267 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 } else if ((particle->maxOccurs > 1)
11269 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011270 xmlAutomataStatePtr tmp;
11271 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011272
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011273 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011274 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011275 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011276
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011277 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 particle->minOccurs - 1,
11279 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011281 sub = particle->children->children;
11282 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011283 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011284 (xmlSchemaParticlePtr) sub, name);
11285 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011287 tmp = pctxt->state;
11288 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011289 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011290 pctxt->state =
11291 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011294 xmlAutomataNewEpsilon(pctxt->am,
11295 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011297 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011298 sub = particle->children->children;
11299 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011300 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011301 (xmlSchemaParticlePtr) sub, name);
11302 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011303 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011304 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011305 xmlAutomataNewEpsilon(pctxt->am, oldstate,
11306 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011307 }
11308 }
11309 }
11310 break;
11311 }
11312 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011313 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011314 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011315
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011316 start = pctxt->state;
11317 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011318
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011319 /*
11320 * iterate over the subtypes and remerge the end with an
11321 * epsilon transition
11322 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011323 if (particle->maxOccurs == 1) {
11324 sub = particle->children->children;
11325 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011326 pctxt->state = start;
11327 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011328 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011329 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011330 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011331 }
11332 } else {
11333 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011334 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11336 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011337 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011338 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011339
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 /*
11341 * use a counter to keep track of the number of transtions
11342 * which went through the choice.
11343 */
11344 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011345 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11346 hop = xmlAutomataNewState(pctxt->am);
11347 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011348
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011349 sub = particle->children->children;
11350 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011351 pctxt->state = base;
11352 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011353 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011354 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011355 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011356 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011357 xmlAutomataNewEpsilon(pctxt->am, start, base);
11358 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
11359 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011361 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011362 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011363 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011364 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011365 break;
11366 }
11367 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011368 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011369 xmlSchemaParticlePtr sub;
11370 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011371 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011372
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011373 sub = (xmlSchemaParticlePtr) particle->children->children;
11374 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011375 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011376 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011377 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011378 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011379
11380 elemDecl = (xmlSchemaElementPtr) sub->children;
11381 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011382 PERROR_INT("xmlSchemaBuildAContentModel",
11383 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011384 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011385 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011386 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011387 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011388 * {particles} of the group must be 0 or 1; this is
11389 * already ensured during the parse of the content of
11390 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011391 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011392 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11393 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011394
Daniel Veillarda980bef2005-07-18 21:34:03 +000011395 /*
11396 * This is an abstract group, we need to share
11397 * the same counter for all the element transitions
11398 * derived from the group
11399 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011400 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011401 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011402 xmlSchemaBuildContentModelForSubstGroup(pctxt,
11403 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000011404 } else {
11405 if ((sub->minOccurs == 1) &&
11406 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011407 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
11408 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011409 elemDecl->name,
11410 elemDecl->targetNamespace,
11411 1, 1, elemDecl);
11412 } else if ((sub->minOccurs == 0) &&
11413 (sub->maxOccurs == 1)) {
11414
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011415 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
11416 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011417 elemDecl->name,
11418 elemDecl->targetNamespace,
11419 0,
11420 1,
11421 elemDecl);
11422 }
11423 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011424 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011425 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011426 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011427 pctxt->state =
11428 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011429 break;
11430 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011431 case XML_SCHEMA_TYPE_GROUP:
11432 /*
11433 * If we hit a model group definition, then this means that
11434 * it was empty, thus was not substituted for the containing
11435 * model group. Just do nothing in this case.
11436 */
11437 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011438 default:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011439 xmlSchemaPInternalErr(pctxt, "xmlSchemaBuildAContentModel",
11440 "found unexpected term of type '%s' in content model of complex "
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011441 "type '%s'",
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011442 xmlSchemaCompTypeToString(particle->children->type), name);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011443 xmlGenericError(xmlGenericErrorContext,
11444 "Unexpected type: %d\n", particle->children->type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011445 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011446 }
11447}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011448
Daniel Veillard4255d502002-04-16 15:50:10 +000011449/**
11450 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011451 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011453 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011454 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011455 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011456 */
11457static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011458xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011459 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011460 const xmlChar * name)
11461{
Daniel Veillard4255d502002-04-16 15:50:10 +000011462 xmlAutomataStatePtr start;
11463
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011464 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11465 (type->contModel != NULL) ||
11466 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11467 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011468 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011469
11470#ifdef DEBUG_CONTENT
11471 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011472 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011473#endif
11474
Daniel Veillard4255d502002-04-16 15:50:10 +000011475 ctxt->am = xmlNewAutomata();
11476 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011477 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011478 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011479 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011480 }
11481 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011482 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011483 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011484 type->contModel = xmlAutomataCompile(ctxt->am);
11485 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011486 xmlSchemaPCustomErr(ctxt,
11487 XML_SCHEMAP_INTERNAL,
11488 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011489 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011490 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011491 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011492 XML_SCHEMAP_NOT_DETERMINISTIC,
11493 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011494 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011495 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011496 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011497#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011498 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011499 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011500 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011501#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011502 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011503 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011504 xmlFreeAutomata(ctxt->am);
11505 ctxt->am = NULL;
11506}
11507
11508/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011509 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011510 * @elem: the schema element context
11511 * @ctxt: the schema parser context
11512 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011513 * Resolves the references of an element declaration
11514 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011515 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011516 */
11517static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011518xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011519 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011520 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011521 const xmlChar * context ATTRIBUTE_UNUSED,
11522 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011523{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 if ((ctxt == NULL) || (elemDecl == NULL) ||
11525 ((elemDecl != NULL) &&
11526 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011527 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011528 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011529
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011530 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011531 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011532
11533 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011534 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011535 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011536 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 elemDecl->namedTypeNs);
11538 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011539 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011540 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011541 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011542 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011543 XML_SCHEMA_TYPE_BASIC, "type definition");
11544 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011545 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011546 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011547 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011548 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011549
Daniel Veillardc0826a72004-08-10 14:17:33 +000011550 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011551 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011552 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011553 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011554 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11555 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011556 if (substHead == NULL) {
11557 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011558 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011559 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011560 "substitutionGroup", elemDecl->substGroup,
11561 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011562 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011563 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011564 /*
11565 * Set the "substitution group affiliation".
11566 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011567 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011568 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011569 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011570 * (type definition)...otherwise the {type definition} of the
11571 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011572 * the substitutionGroup [attribute], if present
11573 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011574 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011575 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011576 }
11577 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011578 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11579 (elemDecl->substGroup == NULL))
11580 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011581}
11582
11583/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011584 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011585 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011586 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011587 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011588 * Checks and builds the "member type definitions" property of the union
11589 * simple type. This handles part (1), part (2) is done in
11590 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11591 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011592 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011593 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011594static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011595xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11596 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011597{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011598
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011599 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011600 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011601
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011602 /*
11603 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11604 * define the explicit members as the type definitions ·resolved·
11605 * to by the items in the ·actual value· of the memberTypes [attribute],
11606 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011607 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011608 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011609 /*
11610 * Resolve references.
11611 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011612 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011613 lastLink = NULL;
11614 while (link != NULL) {
11615 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011616
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011617 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11618 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11619
11620 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11621 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11622 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011623 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011624 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11625 /*
11626 * Remove the member type link.
11627 */
11628 if (lastLink == NULL)
11629 type->memberTypes = link->next;
11630 else
11631 lastLink->next = link->next;
11632 newLink = link;
11633 link = link->next;
11634 xmlFree(newLink);
11635 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011636 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011637 lastLink = link;
11638 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011639 }
11640 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011641 /*
11642 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011643 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011644 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011645 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011646 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11647 if (link == NULL) {
11648 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11649 return (-1);
11650 }
11651 link->type = memberType;
11652 link->next = NULL;
11653 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011654 type->memberTypes = link;
11655 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011656 lastLink->next = link;
11657 lastLink = link;
11658 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011659 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011660 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011661}
11662
Daniel Veillard4255d502002-04-16 15:50:10 +000011663/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011664 * xmlSchemaIsDerivedFromBuiltInType:
11665 * @ctxt: the schema parser context
11666 * @type: the type definition
11667 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011668 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011669 *
11670 * Returns 1 if the type has the given value type, or
11671 * is derived from such a type.
11672 */
William M. Brack803812b2004-06-03 02:11:24 +000011673static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011674xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011675{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011676 if (type == NULL)
11677 return (0);
11678 if (IS_COMPLEX_TYPE(type))
11679 return (0);
11680 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11681 if (type->builtInType == valType)
11682 return(1);
11683 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11684 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11685 return (0);
11686 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11687 } else
11688 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011689
11690 return (0);
11691}
11692
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011693#if 0
11694/**
11695 * xmlSchemaIsDerivedFromBuiltInType:
11696 * @ctxt: the schema parser context
11697 * @type: the type definition
11698 * @valType: the value type
11699 *
11700 *
11701 * Returns 1 if the type has the given value type, or
11702 * is derived from such a type.
11703 */
11704static int
11705xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11706{
11707 if (type == NULL)
11708 return (0);
11709 if (IS_COMPLEX_TYPE(type))
11710 return (0);
11711 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11712 if (type->builtInType == valType)
11713 return(1);
11714 return (0);
11715 } else
11716 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11717
11718 return (0);
11719}
11720#endif
11721
11722static xmlSchemaTypePtr
11723xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11724{
11725 if (type == NULL)
11726 return (NULL);
11727 if (IS_COMPLEX_TYPE(type))
11728 return (NULL);
11729 if (type->type == XML_SCHEMA_TYPE_BASIC)
11730 return(type);
11731 else
11732 return(xmlSchemaQueryBuiltInType(type->subtypes));
11733
11734 return (NULL);
11735}
11736
Daniel Veillard3646d642004-06-02 19:19:14 +000011737/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011738 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011739 * @type: the simpleType definition
11740 *
11741 * Returns the primitive type of the given type or
11742 * NULL in case of error.
11743 */
11744static xmlSchemaTypePtr
11745xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11746{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011747
Daniel Veillard01fa6152004-06-29 17:04:39 +000011748 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011749 /*
11750 * Note that anySimpleType is actually not a primitive type
11751 * but we need that here.
11752 */
11753 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11754 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011755 return (type);
11756 type = type->baseType;
11757 }
11758
11759 return (NULL);
11760}
11761
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011762#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011763/**
11764 * xmlSchemaGetBuiltInTypeAncestor:
11765 * @type: the simpleType definition
11766 *
11767 * Returns the primitive type of the given type or
11768 * NULL in case of error.
11769 */
11770static xmlSchemaTypePtr
11771xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11772{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011773 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011774 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011775 while (type != NULL) {
11776 if (type->type == XML_SCHEMA_TYPE_BASIC)
11777 return (type);
11778 type = type->baseType;
11779 }
11780
11781 return (NULL);
11782}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011783#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011784
Daniel Veillard01fa6152004-06-29 17:04:39 +000011785/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011786 * xmlSchemaBuildAttributeUsesOwned:
11787 * @ctxt: the schema parser context
11788 * @type: the complex type definition
11789 * @cur: the attribute declaration list
11790 * @lastUse: the top of the attribute use list
11791 *
11792 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011793 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011794 * xmlSchemaBuildAttributeValidation only.
11795 */
11796static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011797xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011798 xmlSchemaAttributePtr cur,
11799 xmlSchemaAttributeLinkPtr *uses,
11800 xmlSchemaAttributeLinkPtr *lastUse)
11801{
11802 xmlSchemaAttributeLinkPtr tmp;
11803 while (cur != NULL) {
11804 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011805 /*
11806 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11807 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011808 * <attributeGroup> [children], if any."
11809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011810 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11811 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011812 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011813 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011814 }
11815 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011816 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011817 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011818 */
11819 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011820 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11821 if (tmp == NULL) {
11822 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11823 return (-1);
11824 }
11825 tmp->attr = cur;
11826 tmp->next = NULL;
11827 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011828 *uses = tmp;
11829 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011830 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011831 *lastUse = tmp;
11832 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011833 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011834 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011835 return (0);
11836}
11837
Daniel Veillard50355f02004-06-08 17:52:16 +000011838/**
11839 * xmlSchemaCloneWildcardNsConstraints:
11840 * @ctxt: the schema parser context
11841 * @dest: the destination wildcard
11842 * @source: the source wildcard
11843 *
11844 * Clones the namespace constraints of source
11845 * and assignes them to dest.
11846 * Returns -1 on internal error, 0 otherwise.
11847 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011848static int
11849xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11850 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011851 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011852{
11853 xmlSchemaWildcardNsPtr cur, tmp, last;
11854
11855 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011856 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011857 (*dest)->any = source->any;
11858 cur = source->nsSet;
11859 last = NULL;
11860 while (cur != NULL) {
11861 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11862 if (tmp == NULL)
11863 return(-1);
11864 tmp->value = cur->value;
11865 if (last == NULL)
11866 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011867 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011868 last->next = tmp;
11869 last = tmp;
11870 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011871 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011872 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011873 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011874 if (source->negNsSet != NULL) {
11875 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11876 if ((*dest)->negNsSet == NULL)
11877 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011878 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011879 } else
11880 (*dest)->negNsSet = NULL;
11881 return(0);
11882}
11883
Daniel Veillard50355f02004-06-08 17:52:16 +000011884/**
11885 * xmlSchemaUnionWildcards:
11886 * @ctxt: the schema parser context
11887 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011888 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011889 *
11890 * Unions the namespace constraints of the given wildcards.
11891 * @completeWild will hold the resulting union.
11892 * Returns a positive error code on failure, -1 in case of an
11893 * internal error, 0 otherwise.
11894 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011895static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011896xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011897 xmlSchemaWildcardPtr completeWild,
11898 xmlSchemaWildcardPtr curWild)
11899{
11900 xmlSchemaWildcardNsPtr cur, curB, tmp;
11901
11902 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011903 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011904 * value.
11905 */
11906 if ((completeWild->any == curWild->any) &&
11907 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11908 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011909
Daniel Veillard3646d642004-06-02 19:19:14 +000011910 if ((completeWild->negNsSet == NULL) ||
11911 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011912
Daniel Veillard3646d642004-06-02 19:19:14 +000011913 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011914 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915
11916 /*
11917 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011918 */
11919 cur = completeWild->nsSet;
11920 while (cur != NULL) {
11921 found = 0;
11922 curB = curWild->nsSet;
11923 while (curB != NULL) {
11924 if (cur->value == curB->value) {
11925 found = 1;
11926 break;
11927 }
11928 curB = curB->next;
11929 }
11930 if (!found)
11931 break;
11932 cur = cur->next;
11933 }
11934 if (found)
11935 return(0);
11936 } else
11937 return(0);
11938 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011939 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011940 /*
11941 * 2 If either O1 or O2 is any, then any must be the value
11942 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011943 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011944 if (completeWild->any == 0) {
11945 completeWild->any = 1;
11946 if (completeWild->nsSet != NULL) {
11947 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11948 completeWild->nsSet = NULL;
11949 }
11950 if (completeWild->negNsSet != NULL) {
11951 xmlFree(completeWild->negNsSet);
11952 completeWild->negNsSet = NULL;
11953 }
11954 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011955 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011956 }
11957 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011958 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011959 * then the union of those sets must be the value.
11960 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011961 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011962 int found;
11963 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011964
Daniel Veillard3646d642004-06-02 19:19:14 +000011965 cur = curWild->nsSet;
11966 start = completeWild->nsSet;
11967 while (cur != NULL) {
11968 found = 0;
11969 curB = start;
11970 while (curB != NULL) {
11971 if (cur->value == curB->value) {
11972 found = 1;
11973 break;
11974 }
11975 curB = curB->next;
11976 }
11977 if (!found) {
11978 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011979 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011980 return (-1);
11981 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011982 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011983 completeWild->nsSet = tmp;
11984 }
11985 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011986 }
11987
Daniel Veillard3646d642004-06-02 19:19:14 +000011988 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011989 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011990 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011991 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011992 * or ·absent·), then a pair of not and ·absent· must be the value.
11993 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011994 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011995 (curWild->negNsSet != NULL) &&
11996 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11997 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011998
11999 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012000 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012001 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012002 * 5.
12003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012004 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012005 (completeWild->negNsSet->value != NULL) &&
12006 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012007 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012008 (curWild->negNsSet->value != NULL) &&
12009 (completeWild->nsSet != NULL))) {
12010
12011 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012012
Daniel Veillard3646d642004-06-02 19:19:14 +000012013 if (completeWild->nsSet != NULL) {
12014 cur = completeWild->nsSet;
12015 curB = curWild->negNsSet;
12016 } else {
12017 cur = curWild->nsSet;
12018 curB = completeWild->negNsSet;
12019 }
12020 nsFound = 0;
12021 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012022 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012023 absentFound = 1;
12024 else if (cur->value == curB->value)
12025 nsFound = 1;
12026 if (nsFound && absentFound)
12027 break;
12028 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012029 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012030
12031 if (nsFound && absentFound) {
12032 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012033 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012034 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012035 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012036 completeWild->any = 1;
12037 if (completeWild->nsSet != NULL) {
12038 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12039 completeWild->nsSet = NULL;
12040 }
12041 if (completeWild->negNsSet != NULL) {
12042 xmlFree(completeWild->negNsSet);
12043 completeWild->negNsSet = NULL;
12044 }
12045 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012046 /*
12047 * 5.2 If the set S includes the negated namespace name
12048 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012049 * be the value.
12050 */
12051 if (completeWild->nsSet != NULL) {
12052 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12053 completeWild->nsSet = NULL;
12054 }
12055 if (completeWild->negNsSet == NULL) {
12056 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12057 if (completeWild->negNsSet == NULL)
12058 return (-1);
12059 }
12060 completeWild->negNsSet->value = NULL;
12061 } else if ((!nsFound) && absentFound) {
12062 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012063 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012064 * namespace name, then the union is not expressible.
12065 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012066 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012067 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012068 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012069 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012070 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012071 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012072 /*
12073 * 5.4 If the set S does not include either the negated namespace
12074 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012075 * and a namespace name must be the value.
12076 */
12077 if (completeWild->negNsSet == NULL) {
12078 if (completeWild->nsSet != NULL) {
12079 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12080 completeWild->nsSet = NULL;
12081 }
12082 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12083 if (completeWild->negNsSet == NULL)
12084 return (-1);
12085 completeWild->negNsSet->value = curWild->negNsSet->value;
12086 }
12087 }
12088 return (0);
12089 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012090 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012091 * 6.
12092 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012093 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012094 (completeWild->negNsSet->value == NULL) &&
12095 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012096 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012097 (curWild->negNsSet->value == NULL) &&
12098 (completeWild->nsSet != NULL))) {
12099
12100 if (completeWild->nsSet != NULL) {
12101 cur = completeWild->nsSet;
12102 } else {
12103 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012104 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012105 while (cur != NULL) {
12106 if (cur->value == NULL) {
12107 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012108 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012109 * value.
12110 */
12111 completeWild->any = 1;
12112 if (completeWild->nsSet != NULL) {
12113 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12114 completeWild->nsSet = NULL;
12115 }
12116 if (completeWild->negNsSet != NULL) {
12117 xmlFree(completeWild->negNsSet);
12118 completeWild->negNsSet = NULL;
12119 }
12120 return (0);
12121 }
12122 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012123 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012124 if (completeWild->negNsSet == NULL) {
12125 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012126 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012127 * and ·absent· must be the value.
12128 */
12129 if (completeWild->nsSet != NULL) {
12130 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12131 completeWild->nsSet = NULL;
12132 }
12133 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12134 if (completeWild->negNsSet == NULL)
12135 return (-1);
12136 completeWild->negNsSet->value = NULL;
12137 }
12138 return (0);
12139 }
12140 return (0);
12141
12142}
12143
Daniel Veillard50355f02004-06-08 17:52:16 +000012144/**
12145 * xmlSchemaIntersectWildcards:
12146 * @ctxt: the schema parser context
12147 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012148 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012149 *
12150 * Intersects the namespace constraints of the given wildcards.
12151 * @completeWild will hold the resulting intersection.
12152 * Returns a positive error code on failure, -1 in case of an
12153 * internal error, 0 otherwise.
12154 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012155static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012156xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012157 xmlSchemaWildcardPtr completeWild,
12158 xmlSchemaWildcardPtr curWild)
12159{
William M. Brack803812b2004-06-03 02:11:24 +000012160 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012161
12162 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012163 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012164 * value.
12165 */
12166 if ((completeWild->any == curWild->any) &&
12167 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12168 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169
Daniel Veillard3646d642004-06-02 19:19:14 +000012170 if ((completeWild->negNsSet == NULL) ||
12171 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012172
Daniel Veillard3646d642004-06-02 19:19:14 +000012173 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012174 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012175
12176 /*
12177 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012178 */
12179 cur = completeWild->nsSet;
12180 while (cur != NULL) {
12181 found = 0;
12182 curB = curWild->nsSet;
12183 while (curB != NULL) {
12184 if (cur->value == curB->value) {
12185 found = 1;
12186 break;
12187 }
12188 curB = curB->next;
12189 }
12190 if (!found)
12191 break;
12192 cur = cur->next;
12193 }
12194 if (found)
12195 return(0);
12196 } else
12197 return(0);
12198 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012199 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012200 /*
12201 * 2 If either O1 or O2 is any, then the other must be the value.
12202 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012203 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012204 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012205 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012206 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012207 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012208 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012209 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12210 * name or ·absent·) and the other is a set of (namespace names or
12211 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012212 * the set, minus ·absent· if it was in the set, must be the value.
12213 */
12214 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12215 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12216 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217
Daniel Veillard3646d642004-06-02 19:19:14 +000012218 if (completeWild->nsSet == NULL) {
12219 neg = completeWild->negNsSet->value;
12220 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12221 return(-1);
12222 } else
12223 neg = curWild->negNsSet->value;
12224 /*
12225 * Remove absent and negated.
12226 */
12227 prev = NULL;
12228 cur = completeWild->nsSet;
12229 while (cur != NULL) {
12230 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012231 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012232 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012233 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012234 prev->next = cur->next;
12235 xmlFree(cur);
12236 break;
12237 }
12238 prev = cur;
12239 cur = cur->next;
12240 }
12241 if (neg != NULL) {
12242 prev = NULL;
12243 cur = completeWild->nsSet;
12244 while (cur != NULL) {
12245 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012246 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012247 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012248 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012249 prev->next = cur->next;
12250 xmlFree(cur);
12251 break;
12252 }
12253 prev = cur;
12254 cur = cur->next;
12255 }
12256 }
12257
12258 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012259 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012260 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012261 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012262 * then the intersection of those sets must be the value.
12263 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012264 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012265 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012266
Daniel Veillard3646d642004-06-02 19:19:14 +000012267 cur = completeWild->nsSet;
12268 prev = NULL;
12269 while (cur != NULL) {
12270 found = 0;
12271 curB = curWild->nsSet;
12272 while (curB != NULL) {
12273 if (cur->value == curB->value) {
12274 found = 1;
12275 break;
12276 }
12277 curB = curB->next;
12278 }
12279 if (!found) {
12280 if (prev == NULL)
12281 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012282 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012283 prev->next = cur->next;
12284 tmp = cur->next;
12285 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012286 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012287 continue;
12288 }
12289 prev = cur;
12290 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012291 }
12292
Daniel Veillard3646d642004-06-02 19:19:14 +000012293 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012294 }
12295 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012296 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012297 */
12298 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012299 (curWild->negNsSet != NULL) &&
12300 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012301 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012302 (curWild->negNsSet->value != NULL)) {
12303
12304 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012305 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012306 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012307 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012308 }
12309 /*
12310 * 6 If the one is a negation of a namespace name and the other
12311 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012312 * of a namespace name must be the value.
12313 */
12314 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12315 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012316 (completeWild->negNsSet->value == NULL)) {
12317 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012318 }
12319 return(0);
12320}
12321
Daniel Veillard50355f02004-06-08 17:52:16 +000012322/**
12323 * xmlSchemaIsWildcardNsConstraintSubset:
12324 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012325 * @sub: the first wildcard
12326 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012327 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012328 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12329 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012330 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012331 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012332 */
12333static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012334xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12335 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012336{
Daniel Veillard50355f02004-06-08 17:52:16 +000012337 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012338 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012339 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012340 if (super->any)
12341 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012342 /*
12343 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12344 * 2.2 super must be a pair of not and the same value.
12345 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012346 if ((sub->negNsSet != NULL) &&
12347 (super->negNsSet != NULL) &&
12348 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012349 return (0);
12350 /*
12351 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012352 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012353 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012354 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012355 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012356 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012357 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012358 xmlSchemaWildcardNsPtr cur, curB;
12359 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012360
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012361 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012362 while (cur != NULL) {
12363 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012364 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012365 while (curB != NULL) {
12366 if (cur->value == curB->value) {
12367 found = 1;
12368 break;
12369 }
12370 curB = curB->next;
12371 }
12372 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012373 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012374 cur = cur->next;
12375 }
12376 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012377 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012378 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012379 xmlSchemaWildcardNsPtr cur;
12380 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012381 * 3.2.2 super must be a pair of not and a namespace name or
12382 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012383 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012384 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012385 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012386 if (cur->value == super->negNsSet->value)
12387 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012388 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012389 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012390 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012391 }
12392 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012393 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012394}
12395
12396/**
12397 * xmlSchemaBuildCompleteAttributeWildcard:
12398 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012399 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012400 * @completeWild: the resulting complete wildcard
12401 *
12402 * Returns -1 in case of an internal error, 0 otherwise.
12403 */
12404static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012405xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012406 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012407 xmlSchemaWildcardPtr *completeWild)
12408{
Daniel Veillard3646d642004-06-02 19:19:14 +000012409 while (attrs != NULL) {
12410 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12411 xmlSchemaAttributeGroupPtr group;
12412
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012413 group = (xmlSchemaAttributeGroupPtr) attrs;
12414 /*
12415 * Handle attribute group references.
12416 */
12417 if (group->ref != NULL) {
12418 if (group->refItem == NULL) {
12419 /*
12420 * TODO: Should we raise a warning here?
12421 */
12422 /*
12423 * The referenced attribute group definition could not
12424 * be resolved beforehand, so skip.
12425 */
12426 attrs = attrs->next;
12427 continue;
12428 } else
12429 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012430 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012431 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012432 * For every attribute group definition, an intersected wildcard
12433 * will be created (assumed that a wildcard exists on the
12434 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012435 * at all).
12436 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12437 * that the intersection will be performed only once.
12438 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012439 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12440 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012441 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012442 group->attributes, &group->attributeWildcard) == -1)
12443 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012444 }
12445 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012446 }
12447 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012448 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012449 /*
12450 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012451 *
12452 * Although the complete wildcard might not correspond to any
12453 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012454 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012455 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12456 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12457 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012458 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012459 completeWild, group->attributeWildcard) == -1)
12460 return (-1);
12461 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012462 (*completeWild)->node = group->attributeWildcard->node;
12463 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012464 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012465 }
12466 }
12467 attrs = attrs->next;
12468 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012469
12470 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012471}
12472
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012473static int
12474xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12475 int *fixed,
12476 const xmlChar **value,
12477 xmlSchemaValPtr *val)
12478{
12479 *fixed = 0;
12480 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012481 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012482 *val = NULL;
12483
12484 if (item->defValue == NULL)
12485 item = item->refDecl;
12486
12487 if (item == NULL)
12488 return (0);
12489
12490 if (item->defValue != NULL) {
12491 *value = item->defValue;
12492 if (val != 0)
12493 *val = item->defVal;
12494 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12495 *fixed = 1;
12496 return (1);
12497 }
12498 return (0);
12499}
Daniel Veillard3646d642004-06-02 19:19:14 +000012500/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012501 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012502 * @wild: the wildcard
12503 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012504 *
12505 * Validation Rule: Wildcard allows Namespace Name
12506 * (cvc-wildcard-namespace)
12507 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012508 *
12509 * Returns 1 if the given namespace matches the wildcard,
12510 * 0 otherwise.
12511 */
12512static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12514 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012515{
12516 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012517 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012518
12519 if (wild->any)
12520 return(1);
12521 else if (wild->nsSet != NULL) {
12522 xmlSchemaWildcardNsPtr cur;
12523
12524 cur = wild->nsSet;
12525 while (cur != NULL) {
12526 if (xmlStrEqual(cur->value, ns))
12527 return(1);
12528 cur = cur->next;
12529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012531 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012532 return(1);
12533
Daniel Veillard3646d642004-06-02 19:19:14 +000012534 return(0);
12535}
12536
12537/**
12538 * xmlSchemaBuildAttributeValidation:
12539 * @ctxt: the schema parser context
12540 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012541 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012542 *
12543 * Builds the wildcard and the attribute uses on the given complex type.
12544 * Returns -1 if an internal error occurs, 0 otherwise.
12545 */
12546static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012547xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12548 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012549{
12550 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12552 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012553 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012554 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012555 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012556 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012557
Daniel Veillard01fa6152004-06-29 17:04:39 +000012558 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012559 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012560 * Complex Type Definition with complex content Schema Component.
12561 *
12562 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012563 * TODO: Add checks for absent referenced attribute declarations and
12564 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012565 */
12566 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 PERROR_INT("xmlSchemaBuildAttributeValidation",
12568 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012569 return (-1);
12570 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012571 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012572 PERROR_INT("xmlSchemaBuildAttributeValidation",
12573 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012574 return (-1);
12575 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012576 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012577 /*
12578 * Inherit the attribute uses of the base type.
12579 */
12580 /*
12581 * NOTE: It is allowed to "extend" the anyType complex type.
12582 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012584 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012585 for (cur = baseType->attributeUses; cur != NULL;
12586 cur = cur->next) {
12587 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012588 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12589 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012590 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012591 "building attribute uses of complexType", NULL);
12592 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012593 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012594 tmp->attr = cur->attr;
12595 tmp->next = NULL;
12596 if (type->attributeUses == NULL) {
12597 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012598 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012599 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012600 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012601 }
12602 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012603 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012604 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012605 /*
12606 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012607 */
12608 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12609 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012610 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012611 * NOTE: During the parse time, the wildcard is created on the complexType
12612 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012613 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012614 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012615 PERROR_INT("xmlSchemaBuildAttributeValidation",
12616 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012617 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012618 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012619
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012620 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12621 ((IS_ANYTYPE(baseType)) ||
12622 ((baseType != NULL) &&
12623 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12624 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012625 if (type->attributeWildcard != NULL) {
12626 /*
12627 * Union the complete wildcard with the base wildcard.
12628 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012629 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012630 baseType->attributeWildcard) == -1)
12631 return (-1);
12632 } else {
12633 /*
12634 * Just inherit the wildcard.
12635 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012636 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012638 * wildcard is shared.
12639 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012640 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012641 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012643
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012644 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12645 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012646 /*
12647 * Derivation Valid (Restriction, Complex)
12648 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012649 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012650 if (baseType->attributeWildcard == NULL) {
12651 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012652 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012653 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012654 "The type has an attribute wildcard, "
12655 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012657 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012658 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012659 } else if (xmlSchemaCheckCOSNSSubset(
12660 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012661 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012662 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012663 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012664 NULL, type, NULL,
12665 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012666 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012667 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12668 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012669 return (1);
12670 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012671 /* 4.3 Unless the {base type definition} is the ·ur-type
12672 * definition·, the complex type definition's {attribute
12673 * wildcard}'s {process contents} must be identical to or
12674 * stronger than the {base type definition}'s {attribute
12675 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012676 * than lax is stronger than skip.
12677 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012678 if ((! IS_ANYTYPE(baseType)) &&
12679 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012680 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012681 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012682 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012683 NULL, type, NULL,
12684 "The 'process contents' of the attribute wildcard is "
12685 "weaker than the one in the base type %s",
12686 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012687 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012688 return (1);
12689 }
12690 }
12691 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12692 /*
12693 * Derivation Valid (Extension)
12694 * At this point the type and the base have both, either
12695 * no wildcard or a wildcard.
12696 */
12697 if ((baseType->attributeWildcard != NULL) &&
12698 (baseType->attributeWildcard != type->attributeWildcard)) {
12699 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012700 if (xmlSchemaCheckCOSNSSubset(
12701 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012703 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012704 NULL, type, NULL,
12705 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012706 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012707 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12708 FREE_AND_NULL(str)
12709 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012710 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012711 }
12712 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012713
Daniel Veillard3646d642004-06-02 19:19:14 +000012714 /*
12715 * Gather attribute uses defined by this type.
12716 */
12717 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012719 &uses, &lastUse) == -1) {
12720 return (-1);
12721 }
12722 }
12723 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012724 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012725 * not have identical {name}s and {target namespace}s."
12726 *
12727 * For "extension" this is done further down.
12728 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012729 if ((uses != NULL) && ((type->flags &
12730 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012731 cur = uses;
12732 while (cur != NULL) {
12733 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012734 while (tmp != NULL) {
12735 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012736 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012738 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12739
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012740 xmlSchemaPAttrUseErr(pctxt,
12741 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12742 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012743 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012744 xmlSchemaFormatQName(&str,
12745 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12746 xmlSchemaGetAttrName(tmp->attr)));
12747 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012748 break;
12749 }
12750 tmp = tmp->next;
12751 }
12752 cur = cur->next;
12753 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012754 }
12755 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012756 /*
12757 * Derive by restriction.
12758 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012759 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012760 type->attributeUses = uses;
12761 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012762 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012763 const xmlChar *bEffValue;
12764 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012765
12766 cur = uses;
12767 while (cur != NULL) {
12768 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012769 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012770 base = type->attributeUses;
12771 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012772 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012773 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012774 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012775 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776
12777 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012778
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012779 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012780 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12781 (base->attr->occurs ==
12782 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12783 /*
12784 * NOOP.
12785 */
12786 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012787 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12788 (base->attr->occurs ==
12789 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012790 /*
12791 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012792 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012793 xmlSchemaPAttrUseErr(pctxt,
12794 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12795 type, cur->attr,
12796 "The 'optional' use is inconsistent with a "
12797 "matching 'required' use of the base type",
12798 NULL);
12799 } else if ((cur->attr->occurs ==
12800 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12801 (base->attr->occurs ==
12802 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12803 /*
12804 * derivation-ok-restriction 3
12805 */
12806 xmlSchemaPCustomErr(pctxt,
12807 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12808 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012809 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012810 "attribute use '%s' of the base type is "
12811 "missing",
12812 xmlSchemaFormatQName(&str,
12813 xmlSchemaGetAttrTargetNsURI(base->attr),
12814 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012815 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012816 } else if (xmlSchemaCheckCOSSTDerivedOK(
12817 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12818
12819 /*
12820 * SPEC (2.1.2) "R's {attribute declaration}'s
12821 * {type definition} must be validly derived from
12822 * B's {type definition} given the empty set as
12823 * defined in Type Derivation OK (Simple) (§3.14.6)."
12824 */
12825 xmlSchemaPAttrUseErr(pctxt,
12826 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12827 type, cur->attr,
12828 "The attribute declaration's type "
12829 "definition is not validly derived from "
12830 "the corresponding definition in the "
12831 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012832 } else {
12833 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012834 * 2.1.3 [Definition:] Let the effective value
12835 * constraint of an attribute use be its {value
12836 * constraint}, if present, otherwise its {attribute
12837 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012838 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012839 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000012840 &effFixed, &bEffValue, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012841 /*
12842 * 2.1.3 ... one of the following must be true
12843 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012844 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012845 * ·absent· or default.
12846 */
12847 if ((bEffValue != NULL) &&
12848 (effFixed == 1)) {
12849 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012850
12851 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000012852 &effFixed, &rEffValue, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012853 /*
12854 * 2.1.3.2 R's ·effective value constraint· is
12855 * fixed with the same string as B's.
12856 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012857 */
12858 if ((effFixed == 0) ||
12859 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012860 xmlSchemaPAttrUseErr(pctxt,
12861 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12862 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012863 "The effective value constraint of the "
12864 "attribute use is inconsistent with "
12865 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012866 NULL);
12867 } else {
12868 /*
12869 * Override the attribute use.
12870 */
12871 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012872 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012873 } else
12874 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012875 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012876
Daniel Veillard3646d642004-06-02 19:19:14 +000012877 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012878 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012879 base = base->next;
12880 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012881
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012882 if ((!found) && (cur->attr->occurs !=
12883 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12884 /*
12885 * derivation-ok-restriction 2.2
12886 */
12887 if ((baseType->attributeWildcard == NULL) ||
12888 (xmlSchemaCheckCVCWildcardNamespace(
12889 baseType->attributeWildcard,
12890 cur->attr->targetNamespace) != 1)) {
12891 xmlSchemaPAttrUseErr(pctxt,
12892 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12893 type, cur->attr,
12894 "Neither a matching attribute use, "
12895 "nor a matching wildcard in the base type does exist",
12896 NULL);
12897 } else {
12898 /*
12899 * Add the attribute use.
12900 *
12901 * Note that this may lead to funny derivation error reports, if
12902 * multiple equal attribute uses exist; but this is not
12903 * allowed anyway, and it will be reported beforehand.
12904 */
12905 tmp = cur;
12906 if (prev != NULL)
12907 prev->next = cur->next;
12908 else
12909 uses = cur->next;
12910 cur = cur->next;
12911 tmp->next = NULL;
12912 if (type->attributeUses == NULL) {
12913 type->attributeUses = tmp;
12914 } else
12915 lastBaseUse->next = tmp;
12916 lastBaseUse = tmp;
12917
12918 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012919 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920 }
12921 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012922 cur = cur->next;
12923 }
12924 if (uses != NULL)
12925 xmlSchemaFreeAttributeUseList(uses);
12926 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012927 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012928 /*
12929 * The spec allows only appending, and not other kinds of extensions.
12930 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012931 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012932 */
12933 if (uses != NULL) {
12934 if (type->attributeUses == NULL) {
12935 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012936 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012937 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012938 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012939 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012940 PERROR_INT("xmlSchemaBuildAttributeValidation",
12941 "no derivation method");
12942 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012943 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012944 /*
12945 * 3.4.6 -> Complex Type Definition Properties Correct
12946 */
12947 if (type->attributeUses != NULL) {
12948 cur = type->attributeUses;
12949 prev = NULL;
12950 while (cur != NULL) {
12951 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012952 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012953 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012954 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012955 * Note that this was already done for "restriction" and types derived from
12956 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012957 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012958 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12959 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012960 while (tmp != NULL) {
12961 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012962 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012963 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012964 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012965
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 xmlSchemaPAttrUseErr(pctxt,
12967 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12968 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012969 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012970 break;
12971 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012972 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012973 }
12974 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012975 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012976 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012977 * not have {type definition}s which are or are derived from ID.
12978 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012979 if ((cur->attr->subtypes != NULL) &&
12980 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12981 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012982 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012983 xmlSchemaPAttrUseErr(pctxt,
12984 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12985 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012986 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012987 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012988 NULL);
12989 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012990 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012991 id = cur;
12992 }
12993 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012994 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012995 * stage is to be able to catch dublicate attribute uses. So we had to keep
12996 * prohibited uses in the list as well.
12997 */
12998 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12999 tmp = cur;
13000 if (prev == NULL)
13001 type->attributeUses = cur->next;
13002 else
13003 prev->next = cur->next;
13004 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013005 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013006 } else {
13007 prev = cur;
13008 cur = cur->next;
13009 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013010 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013011 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013012 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013013 * TODO: This check should be removed if we are 100% sure of
13014 * the base type attribute uses already being built.
13015 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013016 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013017 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013018 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013019 PERROR_INT("xmlSchemaBuildAttributeValidation",
13020 "attribute uses not builded on base type");
13021 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013022 return (0);
13023}
13024
13025/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013026 * xmlSchemaTypeFinalContains:
13027 * @schema: the schema
13028 * @type: the type definition
13029 * @final: the final
13030 *
13031 * Evaluates if a type definition contains the given "final".
13032 * This does take "finalDefault" into account as well.
13033 *
13034 * Returns 1 if the type does containt the given "final",
13035 * 0 otherwise.
13036 */
13037static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013038xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013039{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013040 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013041 return (0);
13042 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013043 return (1);
13044 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013045 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013046}
13047
13048/**
13049 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13050 * @type: the Union Simple Type
13051 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013052 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013053 * returns NULL otherwise.
13054 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013055static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013056xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13057{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013058 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013059 if (type->memberTypes != NULL)
13060 return (type->memberTypes);
13061 else
13062 type = type->baseType;
13063 }
13064 return (NULL);
13065}
13066
13067/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013068 * xmlSchemaGetParticleTotalRangeMin:
13069 * @particle: the particle
13070 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013071 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013072 * (all and sequence) + (choice)
13073 *
13074 * Returns the minimun Effective Total Range.
13075 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013076static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013077xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013078{
13079 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013080 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013081 return (0);
13082 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013083 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013084 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013085 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013086
13087 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013088 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013089 while (part != NULL) {
13090 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13091 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013092 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013093 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013094 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013095 if (cur == 0)
13096 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013097 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013098 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013099 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013100 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013101 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013102 } else {
13103 /* <all> and <sequence> */
13104 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013105 xmlSchemaParticlePtr part =
13106 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013107
13108 if (part == NULL)
13109 return (0);
13110 do {
13111 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13112 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013113 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013114 else
13115 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013116 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013117 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013118 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013119 }
13120}
13121
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013122/**
13123 * xmlSchemaGetParticleTotalRangeMax:
13124 * @particle: the particle
13125 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013126 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013127 * (all and sequence) + (choice)
13128 *
13129 * Returns the maximum Effective Total Range.
13130 */
13131static int
13132xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13133{
13134 if ((particle->children == NULL) ||
13135 (particle->children->children == NULL))
13136 return (0);
13137 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13138 int max = -1, cur;
13139 xmlSchemaParticlePtr part =
13140 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013141
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013142 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13143 if (part->children == NULL)
13144 continue;
13145 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13146 (part->children->type == XML_SCHEMA_TYPE_ANY))
13147 cur = part->maxOccurs;
13148 else
13149 cur = xmlSchemaGetParticleTotalRangeMax(part);
13150 if (cur == UNBOUNDED)
13151 return (UNBOUNDED);
13152 if ((max < cur) || (max == -1))
13153 max = cur;
13154 }
13155 /* TODO: Handle overflows? */
13156 return (particle->maxOccurs * max);
13157 } else {
13158 /* <all> and <sequence> */
13159 int sum = 0, cur;
13160 xmlSchemaParticlePtr part =
13161 (xmlSchemaParticlePtr) particle->children->children;
13162
13163 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13164 if (part->children == NULL)
13165 continue;
13166 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13167 (part->children->type == XML_SCHEMA_TYPE_ANY))
13168 cur = part->maxOccurs;
13169 else
13170 cur = xmlSchemaGetParticleTotalRangeMax(part);
13171 if (cur == UNBOUNDED)
13172 return (UNBOUNDED);
13173 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13174 return (UNBOUNDED);
13175 sum += cur;
13176 }
13177 /* TODO: Handle overflows? */
13178 return (particle->maxOccurs * sum);
13179 }
13180}
13181
13182/**
13183 * xmlSchemaIsParticleEmptiable:
13184 * @particle: the particle
13185 *
13186 * Schema Component Constraint: Particle Emptiable
13187 * Checks whether the given particle is emptiable.
13188 *
13189 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013190 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013191static int
13192xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13193{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013194 /*
13195 * SPEC (1) "Its {min occurs} is 0."
13196 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013197 if ((particle == NULL) || (particle->minOccurs == 0) ||
13198 (particle->children == NULL))
13199 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013200 /*
13201 * SPEC (2) "Its {term} is a group and the minimum part of the
13202 * effective total range of that group, [...] is 0."
13203 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013204 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013205 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013206 return (1);
13207 }
13208 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013209}
13210
13211/**
13212 * xmlSchemaCheckCOSSTDerivedOK:
13213 * @type: the derived simple type definition
13214 * @baseType: the base type definition
13215 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013216 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013217 * Type Derivation OK (Simple) (cos-st-derived-OK)
13218 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013219 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013220 * derived from @baseType.
13221 *
13222 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013223 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013224static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013225xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13226 xmlSchemaTypePtr baseType,
13227 int subset)
13228{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013229 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013230 * 1 They are the same type definition.
13231 * TODO: The identy check might have to be more complex than this.
13232 */
13233 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013234 return (0);
13235 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013236 * 2.1 restriction is not in the subset, or in the {final}
13237 * of its own {base type definition};
13238 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013239 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013240 (xmlSchemaTypeFinalContains(type->baseType,
13241 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13242 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013243 }
13244 /* 2.2 */
13245 if (type->baseType == baseType) {
13246 /*
13247 * 2.2.1 D's ·base type definition· is B.
13248 */
13249 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013250 }
13251 /*
13252 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13253 * and is validly derived from B given the subset, as defined by this
13254 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013255 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013256 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013257 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013258 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013259 return (0);
13260 }
13261 /*
13262 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013263 * definition·.
13264 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013265 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013266 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013267 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013268 }
13269 /*
13270 * 2.2.4 B's {variety} is union and D is validly derived from a type
13271 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013272 * defined by this constraint.
13273 *
13274 * NOTE: This seems not to involve built-in types, since there is no
13275 * built-in Union Simple Type.
13276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013277 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013278 xmlSchemaTypeLinkPtr cur;
13279
13280 cur = baseType->memberTypes;
13281 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013282 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013283 return (0);
13284 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013286 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013287
Daniel Veillard01fa6152004-06-29 17:04:39 +000013288 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13289}
13290
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013291/**
13292 * xmlSchemaCheckTypeDefCircularInternal:
13293 * @pctxt: the schema parser context
13294 * @ctxtType: the type definition
13295 * @ancestor: an ancestor of @ctxtType
13296 *
13297 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013298 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013299 *
13300 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13301 * circular, 0 otherwise.
13302 */
13303static int
13304xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13305 xmlSchemaTypePtr ctxtType,
13306 xmlSchemaTypePtr ancestor)
13307{
13308 int ret;
13309
13310 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13311 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013312
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013313 if (ctxtType == ancestor) {
13314 xmlSchemaPCustomErr(pctxt,
13315 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13316 NULL, ctxtType, GET_NODE(ctxtType),
13317 "The definition is circular", NULL);
13318 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13319 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013320 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13321 /*
13322 * Avoid inifinite recursion on circular types not yet checked.
13323 */
13324 return (0);
13325 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013326 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13327 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13328 ancestor->baseType);
13329 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13330 return (ret);
13331}
13332
13333/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013334 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013335 * @item: the complex/simple type definition
13336 * @ctxt: the parser context
13337 * @name: the name
13338 *
13339 * Checks for circular type definitions.
13340 */
13341static void
13342xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013343 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013344 const xmlChar * name ATTRIBUTE_UNUSED)
13345{
13346 if ((item == NULL) ||
13347 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13348 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13349 return;
13350 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13351
13352}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013353
13354/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013355 * xmlSchemaResolveTypeDefs:
13356 * @item: the complex/simple type definition
13357 * @ctxt: the parser context
13358 * @name: the name
13359 *
13360 * Checks for circular type definitions.
13361 */
13362static void
13363xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013364 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013365 const xmlChar * name ATTRIBUTE_UNUSED)
13366{
13367 if (typeDef == NULL)
13368 return;
13369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013370 /*
13371 * Resolve the base type.
13372 */
13373 if (typeDef->baseType == NULL) {
13374 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13375 typeDef->base, typeDef->baseNs);
13376 if (typeDef->baseType == NULL) {
13377 xmlSchemaPResCompAttrErr(ctxt,
13378 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013379 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013380 "base", typeDef->base, typeDef->baseNs,
13381 XML_SCHEMA_TYPE_SIMPLE, NULL);
13382 return;
13383 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384 }
13385 if (IS_SIMPLE_TYPE(typeDef)) {
13386 if (VARIETY_UNION(typeDef)) {
13387 /*
13388 * Resolve the memberTypes.
13389 */
13390 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13391 return;
13392 } else if (VARIETY_LIST(typeDef)) {
13393 /*
13394 * Resolve the itemType.
13395 */
13396 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13397 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13398 typeDef->ref, typeDef->refNs);
13399 if ((typeDef->subtypes == NULL) ||
13400 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13401 typeDef->subtypes = NULL;
13402 xmlSchemaPResCompAttrErr(ctxt,
13403 XML_SCHEMAP_SRC_RESOLVE,
13404 typeDef, typeDef->node,
13405 "itemType", typeDef->ref, typeDef->refNs,
13406 XML_SCHEMA_TYPE_SIMPLE, NULL);
13407 }
13408 }
13409 return;
13410 }
13411 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013412}
13413
13414
13415
13416/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 * xmlSchemaCheckSTPropsCorrect:
13418 * @ctxt: the schema parser context
13419 * @type: the simple type definition
13420 *
13421 * Checks st-props-correct.
13422 *
13423 * Returns 0 if the properties are correct,
13424 * if not, a positive error code and -1 on internal
13425 * errors.
13426 */
13427static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013429 xmlSchemaTypePtr type)
13430{
13431 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13432 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013433 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013434
Daniel Veillardc0826a72004-08-10 14:17:33 +000013435 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013436 /*
13437 * Schema Component Constraint: Simple Type Definition Properties Correct
13438 *
13439 * NOTE: This is somehow redundant, since we actually built a simple type
13440 * to have all the needed information; this acts as an self test.
13441 */
13442 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13443 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 /* Base type: If the datatype has been ·derived· by ·restriction·
13445 * then the Simple Type Definition component from which it is ·derived·,
13446 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013447 */
13448 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013449 /*
13450 * TODO: Think about: "modulo the impact of Missing
13451 * Sub-components (§5.3)."
13452 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013453 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013454 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013455 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013456 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013457 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013458
Daniel Veillard01fa6152004-06-29 17:04:39 +000013459 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013460 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013461 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 NULL, type, NULL,
13464 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013465 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013466 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013467 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13468 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013469 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13470 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13471 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013472 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013474 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013476 "the simple ur-type definition as base type, not '%s'",
13477 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013478 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13480 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481 /*
13482 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13485 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013486 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013487 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013489 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13491 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013494 /*
13495 * 3 The {final} of the {base type definition} must not contain restriction.
13496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013497 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013498 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13499 xmlSchemaPCustomErr(ctxt,
13500 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013501 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013502 "The 'final' of its base type '%s' must not contain "
13503 "'restriction'",
13504 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013506 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013507 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013508
13509 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013510 * 2 All simple type definitions must be derived ultimately from the ·simple
13511 * ur-type definition (so· circular definitions are disallowed). That is, it
13512 * must be possible to reach a built-in primitive datatype or the ·simple
13513 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013514 *
13515 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013516 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 return (0);
13518}
13519
13520/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013521 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 * @ctxt: the schema parser context
13523 * @type: the simple type definition
13524 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013525 * Schema Component Constraint:
13526 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13527
13528 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013529 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013530 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013531 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 * a positive error code otherwise.
13533 */
13534static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013535xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013536 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013537{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013538 xmlChar *str = NULL;
13539
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013541 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13542 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 return (-1);
13544 }
13545
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013547 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013548 /*
13549 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013550 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 */
13552 if (! VARIETY_ATOMIC(type->baseType)) {
13553 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013554 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013555 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013556 "The base type '%s' is not an atomic simple type",
13557 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013558 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013559 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13560 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 * restriction.
13563 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013564 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013565 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013566 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013569 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013570 "The final of its base type '%s' must not contain 'restriction'",
13571 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013572 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013573 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13574 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013575
13576 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013579 * Primitive datatypes.
13580 */
13581 if (type->facets != NULL) {
13582 xmlSchemaFacetPtr facet;
13583 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013584
Daniel Veillard01fa6152004-06-29 17:04:39 +000013585 primitive = xmlSchemaGetPrimitiveType(type);
13586 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13588 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013589 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 facet = type->facets;
13592 do {
13593 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013594 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013595 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013596 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013597 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013598 }
13599 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013600 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013602 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013603 }
13604 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013605 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13606 * of the {base type definition} (call this BF),then the DF's {value}
13607 * must be a valid restriction of BF's {value} as defined in
13608 * [XML Schemas: Datatypes]."
13609 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013610 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013611 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013612 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013614 xmlSchemaTypePtr itemType = NULL;
13615
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013616 itemType = type->subtypes;
13617 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013618 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13619 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013620 return (-1);
13621 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013622 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013623 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013624 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 * 2.1 The {item type definition} must have a {variety} of atomic or
13626 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013627 * must be atomic).
13628 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 if ((! VARIETY_ATOMIC(itemType)) &&
13630 (! VARIETY_UNION(itemType))) {
13631 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013632 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013633 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013634 "The item type '%s' does not have a variety of atomic or union",
13635 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013636 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013637 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013639 xmlSchemaTypeLinkPtr member;
13640
13641 member = itemType->memberTypes;
13642 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643 if (! VARIETY_ATOMIC(member->type)) {
13644 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013645 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013647 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013648 "member type '%s' of this item type is not atomic",
13649 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013650 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013651 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13652 }
13653 member = member->next;
13654 }
13655 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013656
13657 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013658 xmlSchemaFacetPtr facet;
13659 /*
13660 * This is the case if we have: <simpleType><list ..
13661 */
13662 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663 * 2.3.1
13664 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 * contain list.
13666 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013667 if (xmlSchemaTypeFinalContains(itemType,
13668 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13669 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013670 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013671 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013672 "The final of its item type '%s' must not contain 'list'",
13673 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013675 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13676 }
13677 /*
13678 * 2.3.1.2 The {facets} must only contain the whiteSpace
13679 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013680 * OPTIMIZE TODO: the S4S already disallows any facet
13681 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013682 */
13683 if (type->facets != NULL) {
13684 facet = type->facets;
13685 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013686 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013687 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013688 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013689 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13691 }
13692 facet = facet->next;
13693 } while (facet != NULL);
13694 }
13695 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013696 * MAYBE TODO: (Hmm, not really) Datatypes states:
13697 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13698 * whose ·lexical space· allows space (such as string or anyURI)or
13699 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013700 * ·lexical space· allows space.
13701 */
13702 } else {
13703 /*
13704 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013705 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013706 */
13707 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13710 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711 if (! VARIETY_LIST(type->baseType)) {
13712 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013713 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013715 "The base type '%s' must be a list type",
13716 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013717 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13719 }
13720 /*
13721 * 2.3.2.2 The {final} of the {base type definition} must not
13722 * contain restriction.
13723 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013726 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013728 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013729 "The 'final' of the base type '%s' must not contain 'restriction'",
13730 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013731 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13733 }
13734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013736 * from the {base type definition}'s {item type definition} given
13737 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13738 */
13739 {
13740 xmlSchemaTypePtr baseItemType;
13741
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013742 baseItemType = type->baseType->subtypes;
13743 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013744 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13745 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013746 return (-1);
13747 }
13748 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013749 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13750 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013751 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013753 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 NULL, type, NULL,
13755 "The item type '%s' is not validly derived from "
13756 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013757 xmlSchemaGetComponentQName(&str, itemType),
13758 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13759 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013760
13761 FREE_AND_NULL(str)
13762 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13765 }
13766 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013767
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 if (type->facets != NULL) {
13769 xmlSchemaFacetPtr facet;
13770 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013771 /*
13772 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 * and enumeration facet components are allowed among the {facets}.
13774 */
13775 facet = type->facets;
13776 do {
13777 switch (facet->type) {
13778 case XML_SCHEMA_FACET_LENGTH:
13779 case XML_SCHEMA_FACET_MINLENGTH:
13780 case XML_SCHEMA_FACET_MAXLENGTH:
13781 case XML_SCHEMA_FACET_WHITESPACE:
13782 /*
13783 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013784 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 */
13786 case XML_SCHEMA_FACET_PATTERN:
13787 case XML_SCHEMA_FACET_ENUMERATION:
13788 break;
13789 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013791 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013792 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013793 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013794 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 * invalid facets.
13796 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 facet = facet->next;
13801 } while (facet != NULL);
13802 if (ok == 0)
13803 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13804 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013805 * SPEC (2.3.2.5) (same as 1.3.2)
13806 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013808 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013812 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013813 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013814 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013815 * atomic or list.
13816 */
13817 xmlSchemaTypeLinkPtr member;
13818
13819 member = type->memberTypes;
13820 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013821 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013822 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013823
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013824 if ((! VARIETY_ATOMIC(member->type)) &&
13825 (! VARIETY_LIST(member->type))) {
13826 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013828 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013829 "The member type '%s' is neither an atomic, nor a list type",
13830 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013831 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13833 }
13834 member = member->next;
13835 }
13836 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 * 3.3.1 If the {base type definition} is the ·simple ur-type
13838 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013839 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013840 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013841 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013842 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013843 * {final} which does not contain union.
13844 */
13845 member = type->memberTypes;
13846 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013847 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013848 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013849 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013850 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013851 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013852 "The 'final' of member type '%s' contains 'union'",
13853 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13856 }
13857 member = member->next;
13858 }
13859 /*
13860 * 3.3.1.2 The {facets} must be empty.
13861 */
13862 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013865 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013866 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013867 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13868 }
13869 } else {
13870 /*
13871 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013872 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013873 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013874 if (! VARIETY_UNION(type->baseType)) {
13875 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013877 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013878 "The base type '%s' is not a union type",
13879 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013880 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013881 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13882 }
13883 /*
13884 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13885 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013887 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013888 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013889 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013890 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013891 "The 'final' of its base type '%s' must not contain 'restriction'",
13892 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013893 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013894 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13895 }
13896 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013897 * 3.3.2.3 The {member type definitions}, in order, must be validly
13898 * derived from the corresponding type definitions in the {base
13899 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013900 * as defined in Type Derivation OK (Simple) (§3.14.6).
13901 */
13902 {
13903 xmlSchemaTypeLinkPtr baseMember;
13904
13905 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013906 * OPTIMIZE: if the type is restricting, it has no local defined
13907 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013908 * thus a check for equality can be skipped.
13909 */
13910 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013911 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013912 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013913 * types of it's base type. This check seems not necessary with
13914 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013915 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 */
13917 if (type->memberTypes != NULL) {
13918 member = type->memberTypes;
13919 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920 if ((member == NULL) && (baseMember != NULL)) {
13921 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13922 "different number of member types in base");
13923 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013924 while (member != NULL) {
13925 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013926 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13927 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013928 }
13929 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930 (xmlSchemaCheckCOSSTDerivedOK(
13931 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013932 xmlChar *strBMT = NULL, *strBT = NULL;
13933
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013934 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013935 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13936 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013937 "The member type %s is not validly "
13938 "derived from its corresponding member "
13939 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013940 xmlSchemaGetComponentQName(&str, member->type),
13941 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13942 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013943 FREE_AND_NULL(str)
13944 FREE_AND_NULL(strBMT)
13945 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013946 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013947 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013948 member = member->next;
13949 baseMember = baseMember->next;
13950 }
13951 }
13952 }
13953 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013954 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013955 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013956 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013957 if (type->facets != NULL) {
13958 xmlSchemaFacetPtr facet;
13959 int ok = 1;
13960
13961 facet = type->facets;
13962 do {
13963 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13964 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013965 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013966 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013967 NULL, type, facet);
13968 ok = 0;
13969 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013970 facet = facet->next;
13971 } while (facet != NULL);
13972 if (ok == 0)
13973 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013974
Daniel Veillard01fa6152004-06-29 17:04:39 +000013975 }
13976 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013977 * SPEC (3.3.2.5) (same as 1.3.2)
13978 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013979 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013980 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013981 */
13982 }
13983 }
13984
13985 return (0);
13986}
13987
13988/**
13989 * xmlSchemaCheckSRCSimpleType:
13990 * @ctxt: the schema parser context
13991 * @type: the simple type definition
13992 *
13993 * Checks crc-simple-type constraints.
13994 *
13995 * Returns 0 if the constraints are satisfied,
13996 * if not a positive error code and -1 on internal
13997 * errors.
13998 */
13999static int
14000xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14001 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014002{
14003 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014004 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014005 * must satisfy the conditions set out in Constraints on Simple Type
14006 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 */
14008 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
14009 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14010 /*
14011 * TODO: Removed this, since it got annoying to get an
14012 * extra error report, if anything failed until now.
14013 * Enable this if needed.
14014 */
14015 /*
14016 xmlSchemaPErr(ctxt, type->node,
14017 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014018 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014019 "on simple type definitions.\n",
14020 type->name, NULL);
14021 */
14022 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14023 }
14024
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014025 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014026 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014027 * src-simple-type.2 If the <restriction> alternative is chosen,
14028 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014031 /*
14032 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014033 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014034 */
14035 } else if (VARIETY_LIST(type)) {
14036 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14037 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000014038 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014039 *
14040 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041 */
14042 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014043 xmlSchemaTypeLinkPtr member;
14044 xmlSchemaTypePtr ancestor, anySimpleType;
14045
14046 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14047
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014048 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14049 * the <union> alternative is chosen, there must not be any entries
14050 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014051 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014052 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014053 member = type->memberTypes;
14054 while (member != NULL) {
14055 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014056 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014057 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014058 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014059 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014060 NULL, type, NULL,
14061 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014062 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014063 }
14064 if (IS_NOT_TYPEFIXED(ancestor))
14065 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014066 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014067 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014068 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014069 * type as item type, which in turn has a list ST as member
14070 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014071 * was not yet performed.
14072 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014073 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014074
Daniel Veillard01fa6152004-06-29 17:04:39 +000014075 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014077 member = member->next;
14078 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014079 }
14080
14081 return (0);
14082}
14083
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014084static int
14085xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14086{
14087 if (ctxt->vctxt == NULL) {
14088 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14089 if (ctxt->vctxt == NULL) {
14090 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014091 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014092 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014093 "failed to create a temp. validation context.\n",
14094 NULL, NULL);
14095 return (-1);
14096 }
14097 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014098 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014099 }
14100 return (0);
14101}
14102
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014103static int
14104xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14105 xmlNodePtr node,
14106 xmlSchemaTypePtr type,
14107 const xmlChar *value,
14108 xmlSchemaValPtr *retVal,
14109 int fireErrors,
14110 int normalize,
14111 int isNormalized);
14112
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014113/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014114 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014115 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014116 * @type: the simple type definition
14117 * @value: the default value
14118 * @node: an optional node (the holder of the value)
14119 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014120 * Schema Component Constraint: Element Default Valid (Immediate)
14121 * (cos-valid-default)
14122 * This will be used by the parser only. For the validator there's
14123 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014124 *
14125 * Returns 0 if the constraints are satisfied,
14126 * if not, a positive error code and -1 on internal
14127 * errors.
14128 */
14129static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014130xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14131 xmlNodePtr node,
14132 xmlSchemaTypePtr type,
14133 const xmlChar *value,
14134 xmlSchemaValPtr *val)
14135{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014136 int ret = 0;
14137
14138 /*
14139 * cos-valid-default:
14140 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014141 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014142 * definition the appropriate case among the following must be true:
14143 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014144 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014145 /*
14146 * Complex type.
14147 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014148 * SPEC (2.1) "its {content type} must be a simple type definition
14149 * or mixed."
14150 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014151 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014152 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014153 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014154 if ((! HAS_SIMPLE_CONTENT(type)) &&
14155 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14156 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014157 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014158 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014159 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014160 "For a string to be a valid default, the type definition "
14161 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014162 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014163 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14164 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014165 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014166 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014167 * 1 If the type definition is a simple type definition, then the string
14168 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014169 * Valid (§3.14.4).
14170 *
14171 * AND
14172 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014173 * 2.2.1 If the {content type} is a simple type definition, then the
14174 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014175 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014176 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014177 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014178 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14179 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014180 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014181 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14182 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014183 else
14184 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014185
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014186 if (ret < 0) {
14187 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14188 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014189 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014190
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014191 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014192}
14193
14194/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014195 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014196 * @ctxt: the schema parser context
14197 * @type: the complex type definition
14198 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014199 *.(4.6) Constraints on Complex Type Definition Schema Components
14200 * Schema Component Constraint:
14201 * Complex Type Definition Properties Correct (ct-props-correct)
14202 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014203 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014204 * Returns 0 if the constraints are satisfied, a positive
14205 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014206 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014207static int
14208xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14209 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014210{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014211 /*
14212 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14213 *
14214 * SPEC (1) "The values of the properties of a complex type definition must
14215 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014216 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014217 * Sub-components (§5.3)."
14218 */
14219 if ((type->baseType != NULL) &&
14220 (IS_SIMPLE_TYPE(type->baseType)) &&
14221 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14222 /*
14223 * SPEC (2) "If the {base type definition} is a simple type definition,
14224 * the {derivation method} must be extension."
14225 */
14226 xmlSchemaPCustomErr(pctxt,
14227 XML_SCHEMAP_SRC_CT_1,
14228 NULL, type, NULL,
14229 "If the base type is a simple type, the derivation method must be "
14230 "'extension'", NULL);
14231 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014232 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014233 /*
14234 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14235 * definition·. That is, it must be possible to reach the ·ur-type
14236 * definition by repeatedly following the {base type definition}."
14237 *
14238 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14239 *
14240 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014241 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014242 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14243 * must not have {type definition}s which are or are derived from ID."
14244 *
14245 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14246 */
14247 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014248}
14249
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014250static int
14251xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14252 xmlSchemaTypePtr typeB)
14253{
14254 /*
14255 * TODO: This should implement component-identity
14256 * in the future.
14257 */
14258 if ((typeA == NULL) || (typeB == NULL))
14259 return (0);
14260 return (typeA == typeB);
14261}
14262
14263/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014264 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014265 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014266 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014267 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014268 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014269 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014270 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014271 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14272 *
14273 * STATUS: completed
14274 *
14275 * Returns 0 if the constraints are satisfied, or 1
14276 * if not.
14277 */
14278static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014279xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014280 xmlSchemaTypePtr baseType,
14281 int set)
14282{
14283 int equal = xmlSchemaAreEqualTypes(type, baseType);
14284 /* TODO: Error codes. */
14285 /*
14286 * SPEC "For a complex type definition (call it D, for derived)
14287 * to be validly derived from a type definition (call this
14288 * B, for base) given a subset of {extension, restriction}
14289 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014290 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014291 if (! equal) {
14292 /*
14293 * SPEC (1) "If B and D are not the same type definition, then the
14294 * {derivation method} of D must not be in the subset."
14295 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014296 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014297 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014298 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014299 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014300 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014301 } else {
14302 /*
14303 * SPEC (2.1) "B and D must be the same type definition."
14304 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014305 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014306 }
14307 /*
14308 * SPEC (2.2) "B must be D's {base type definition}."
14309 */
14310 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014311 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014312 /*
14313 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14314 * definition·."
14315 */
14316 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014317 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014318
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014319 if (IS_COMPLEX_TYPE(type->baseType)) {
14320 /*
14321 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14322 * must be validly derived from B given the subset as defined by this
14323 * constraint."
14324 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014325 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014326 baseType, set));
14327 } else {
14328 /*
14329 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14330 * must be validly derived from B given the subset as defined in Type
14331 * Derivation OK (Simple) (§3.14.6).
14332 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014333 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14334 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014335}
14336
14337/**
14338 * xmlSchemaCheckCOSDerivedOK:
14339 * @type: the derived simple type definition
14340 * @baseType: the base type definition
14341 *
14342 * Calls:
14343 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014344 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014345 * Checks wheter @type can be validly derived from @baseType.
14346 *
14347 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014348 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014349static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014350xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014351 xmlSchemaTypePtr baseType,
14352 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014353{
14354 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014355 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014356 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014357 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014358}
14359
William M. Brack2f2a6632004-08-20 23:09:47 +000014360/**
14361 * xmlSchemaCheckCOSCTExtends:
14362 * @ctxt: the schema parser context
14363 * @type: the complex type definition
14364 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014365 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014366 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014367 * Derivation Valid (Extension) (cos-ct-extends)
14368 *
14369 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014370 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014371 * (1.5)
14372 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014373 *
14374 * Returns 0 if the constraints are satisfied, a positive
14375 * error code if not and -1 if an internal error occured.
14376 */
14377static int
14378xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14379 xmlSchemaTypePtr type)
14380{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014381 xmlSchemaTypePtr base = type->baseType;
14382 /*
14383 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14384 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014385 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014386 /*
14387 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014388 * then all of the following must be true:"
14389 */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000014390 if (IS_COMPLEX_TYPE(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014391 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014392 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014393 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014394 */
14395 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14396 xmlSchemaPCustomErr(ctxt,
14397 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14398 NULL, type, NULL,
14399 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014400 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014401 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14402 }
14403 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014404 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014405 * uses}
14406 * of the complex type definition itself, that is, for every attribute
14407 * use in the {attribute uses} of the {base type definition}, there
14408 * must be an attribute use in the {attribute uses} of the complex
14409 * type definition itself whose {attribute declaration} has the same
14410 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014411 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014412 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014413 * NOTE (1.2): This will be already satisfied by the way the attribute
14414 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14415 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014416 */
14417
14418 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014419 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14420 * definition must also have one, and the base type definition's
14421 * {attribute wildcard}'s {namespace constraint} must be a subset
14422 * of the complex type definition's {attribute wildcard}'s {namespace
14423 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014424 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014425 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014426 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014427 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014428 * SPEC (1.4) "One 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 != NULL) &&
14431 (type->contentTypeDef == base->contentTypeDef)) {
14432 /*
14433 * SPEC (1.4.1) "The {content type} of the {base type definition}
14434 * and the {content type} of the complex type definition itself
14435 * must be the same simple type definition"
14436 * PASS
14437 */
14438 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14439 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14440 /*
14441 * SPEC (1.4.2) "The {content type} of both the {base type
14442 * definition} and the complex type definition itself must
14443 * be empty."
14444 * PASS
14445 */
14446 } else {
14447 /*
14448 * SPEC (1.4.3) "All of the following must be true:"
14449 */
14450 if (type->subtypes == NULL) {
14451 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014452 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014453 * definition itself must specify a particle.
14454 */
14455 xmlSchemaPCustomErr(ctxt,
14456 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14457 NULL, type, NULL,
14458 "The content type must specify a particle", NULL);
14459 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14460 }
14461 /*
14462 * SPEC (1.4.3.2) "One of the following must be true:"
14463 */
14464 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14465 /*
14466 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14467 * definition} must be empty.
14468 * PASS
14469 */
14470 } else {
14471 /*
14472 * SPEC (1.4.3.2.2) "All of the following must be true:"
14473 */
14474 if ((type->contentType != base->contentType) ||
14475 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14476 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14477 /*
14478 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14479 * or both must be element-only."
14480 */
14481 xmlSchemaPCustomErr(ctxt,
14482 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14483 NULL, type, NULL,
14484 "The content type of both, the type and its base "
14485 "type, must either 'mixed' or 'element-only'", NULL);
14486 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014487 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014488 /*
14489 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14490 * complex type definition must be a ·valid extension·
14491 * of the {base type definition}'s particle, as defined
14492 * in Particle Valid (Extension) (§3.9.6)."
14493 *
14494 * NOTE that we won't check "Particle Valid (Extension)",
14495 * since it is ensured by the derivation process in
14496 * xmlSchemaTypeFixup(). We need to implement this when heading
14497 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014498 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014499 }
14500 /*
14501 * TODO (1.5)
14502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014503 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014504 } else {
14505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014507 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014508 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014509 if (type->contentTypeDef != base) {
14510 /*
14511 * SPEC (2.1) "The {content type} must be the same simple type
14512 * definition."
14513 */
14514 xmlSchemaPCustomErr(ctxt,
14515 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14516 NULL, type, NULL,
14517 "The content type must be the simple base type", NULL);
14518 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14519 }
14520 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14521 /*
14522 * SPEC (2.2) "The {final} of the {base type definition} must not
14523 * contain extension"
14524 * NOTE that this is the same as (1.1).
14525 */
14526 xmlSchemaPCustomErr(ctxt,
14527 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14528 NULL, type, NULL,
14529 "The 'final' of the base type definition "
14530 "contains 'extension'", NULL);
14531 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014532 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014533 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014534 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014535}
14536
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014537/**
14538 * xmlSchemaCheckDerivationOKRestriction:
14539 * @ctxt: the schema parser context
14540 * @type: the complex type definition
14541 *
14542 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014543 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014544 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14545 *
14546 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014547 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014548 * (5.4.2), (5.2.2.1)
14549 *
14550 * Returns 0 if the constraints are satisfied, a positive
14551 * error code if not and -1 if an internal error occured.
14552 */
14553static int
14554xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14555 xmlSchemaTypePtr type)
14556{
14557 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014558
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014559 /*
14560 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14561 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014562 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014563 base = type->baseType;
14564 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14565 /*
14566 * SPEC (1) "The {base type definition} must be a complex type
14567 * definition whose {final} does not contain restriction."
14568 */
14569 xmlSchemaPCustomErr(ctxt,
14570 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14571 NULL, type, NULL,
14572 "The 'final' of the base type definition "
14573 "contains 'restriction'", NULL);
14574 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14575 }
14576 /*
14577 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14578 *
14579 * SPEC (5) "One of the following must be true:"
14580 */
14581 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14582 /*
14583 * SPEC (5.1) "The {base type definition} must be the
14584 * ·ur-type definition·."
14585 * PASS
14586 */
14587 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14588 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14589 /*
14590 * SPEC (5.2.1) "The {content type} of the complex type definition
14591 * must be a simple type definition"
14592 *
14593 * SPEC (5.2.2) "One of the following must be true:"
14594 */
14595 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14596 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14597 /*
14598 * SPEC (5.2.2.1) "The {content type} of the {base type
14599 * definition} must be a simple type definition from which
14600 * the {content type} is validly derived given the empty
14601 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14602 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014603 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014604 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14605 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014606 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014607 /*
14608 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14609 * and have a particle which is ·emptiable· as defined in
14610 * Particle Emptiable (§3.9.6)."
14611 * PASS
14612 */
14613 } else {
14614 xmlSchemaPCustomErr(ctxt,
14615 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14616 NULL, type, NULL,
14617 "The content type of the base type must be either "
14618 "a simple type or 'mixed' and an emptiable particle", NULL);
14619 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14620 }
14621 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14622 /*
14623 * SPEC (5.3.1) "The {content type} of the complex type itself must
14624 * be empty"
14625 */
14626 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14627 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014628 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014629 * definition} must also be empty."
14630 * PASS
14631 */
14632 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14633 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14634 xmlSchemaIsParticleEmptiable(
14635 (xmlSchemaParticlePtr) base->subtypes)) {
14636 /*
14637 * SPEC (5.3.2.2) "The {content type} of the {base type
14638 * definition} must be elementOnly or mixed and have a particle
14639 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14640 * PASS
14641 */
14642 } else {
14643 xmlSchemaPCustomErr(ctxt,
14644 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14645 NULL, type, NULL,
14646 "The content type of the base type must be either "
14647 "empty or 'mixed' (or 'elements-only') and an emptiable "
14648 "particle", NULL);
14649 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14650 }
14651 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014652 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014653 /*
14654 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14655 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014656 */
14657 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14658 /*
14659 * SPEC (5.4.1.2) "The {content type} of the complex type
14660 * definition itself and of the {base type definition} must be
14661 * mixed"
14662 */
14663 xmlSchemaPCustomErr(ctxt,
14664 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14665 NULL, type, NULL,
14666 "If the content type is 'mixed', then the content type of the "
14667 "base type must also be 'mixed'", NULL);
14668 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14669 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014670 /*
14671 * SPEC (5.4.2) "The particle of the complex type definition itself
14672 * must be a ·valid restriction· of the particle of the {content
14673 * type} of the {base type definition} as defined in Particle Valid
14674 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014675 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014676 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014677 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014678 } else {
14679 xmlSchemaPCustomErr(ctxt,
14680 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14681 NULL, type, NULL,
14682 "The type is not a valid restriction of its base type", NULL);
14683 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14684 }
14685 return (0);
14686}
14687
14688/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014689 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014690 * @ctxt: the schema parser context
14691 * @type: the complex type definition
14692 *
14693 * (3.4.6) Constraints on Complex Type Definition Schema Components
14694 *
14695 * Returns 0 if the constraints are satisfied, a positive
14696 * error code if not and -1 if an internal error occured.
14697 */
14698static int
14699xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14700 xmlSchemaTypePtr type)
14701{
14702 int ret;
14703 /*
14704 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014705 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014706 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14707 if (ret != 0)
14708 return (ret);
14709 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14710 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14711 else
14712 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14713 return (ret);
14714}
14715
14716/**
14717 * xmlSchemaCheckSRCCT:
14718 * @ctxt: the schema parser context
14719 * @type: the complex type definition
14720 *
14721 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014722 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014723 * Complex Type Definition Representation OK (src-ct)
14724 *
14725 * Returns 0 if the constraints are satisfied, a positive
14726 * error code if not and -1 if an internal error occured.
14727 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014728static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014729xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014730 xmlSchemaTypePtr type)
14731{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014732 xmlSchemaTypePtr base;
14733 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014734
14735 /*
14736 * TODO: Adjust the error codes here, as I used
14737 * XML_SCHEMAP_SRC_CT_1 only yet.
14738 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014739 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014740 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014741 /*
14742 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014743 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014744 * must be a complex type definition;
14745 */
14746 if (! IS_COMPLEX_TYPE(base)) {
14747 xmlChar *str = NULL;
14748 xmlSchemaPCustomErr(ctxt,
14749 XML_SCHEMAP_SRC_CT_1,
14750 NULL, type, type->node,
14751 "If using <complexContent>, the base type is expected to be "
14752 "a complex type. The base type '%s' is a simple type",
14753 xmlSchemaFormatQName(&str, base->targetNamespace,
14754 base->name));
14755 FREE_AND_NULL(str)
14756 return (XML_SCHEMAP_SRC_CT_1);
14757 }
14758 } else {
14759 /*
14760 * SPEC
14761 * 2 If the <simpleContent> alternative is chosen, all of the
14762 * following must be true:
14763 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14764 * base [attribute] must be one of the following:
14765 */
14766 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014767 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014768 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14769 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770 /*
14771 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014772 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014773 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014774 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014775 xmlSchemaPCustomErr(ctxt,
14776 XML_SCHEMAP_SRC_CT_1,
14777 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014778 "If using <simpleContent> and <restriction>, the base "
14779 "type must be a complex type. The base type '%s' is "
14780 "a simple type",
14781 xmlSchemaFormatQName(&str, base->targetNamespace,
14782 base->name));
14783 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014784 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014785 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014786 } else {
14787 /* Base type is a complex type. */
14788 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14789 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14790 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014791 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014792 * simple type definition;
14793 * PASS
14794 */
14795 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014796 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014797 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014798 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014799 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014800 type->name);
14801 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014802 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014803 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14804 (type->flags &
14805 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014806
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014807 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014808 * 2.1.2 only if the <restriction> alternative is also
14809 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014810 * is mixed and a particle emptiable.
14811 */
14812 if (! xmlSchemaIsParticleEmptiable(
14813 (xmlSchemaParticlePtr) base->subtypes)) {
14814 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014815 } else
14816 /*
14817 * Attention: at this point the <simpleType> child is in
14818 * ->contentTypeDef (put there during parsing).
14819 */
14820 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014821 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014823 * 2.2 If clause 2.1.2 above is satisfied, then there
14824 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014825 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014826 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014827 /* TODO: Change error code to ..._SRC_CT_2_2. */
14828 xmlSchemaPCustomErr(ctxt,
14829 XML_SCHEMAP_SRC_CT_1,
14830 NULL, type, NULL,
14831 "A <simpleType> is expected among the children "
14832 "of <restriction>, if <simpleContent> is used and "
14833 "the base type '%s' is a complex type",
14834 xmlSchemaFormatQName(&str, base->targetNamespace,
14835 base->name));
14836 FREE_AND_NULL(str)
14837 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014838 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014839 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014840 ret = XML_SCHEMAP_SRC_CT_1;
14841 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014842 }
14843 if (ret > 0) {
14844 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014845 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014846 xmlSchemaPCustomErr(ctxt,
14847 XML_SCHEMAP_SRC_CT_1,
14848 NULL, type, NULL,
14849 "If <simpleContent> and <restriction> is used, the "
14850 "base type must be a simple type or a complex type with "
14851 "mixed content and particle emptiable. The base type "
14852 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014853 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014854 base->name));
14855 } else {
14856 xmlSchemaPCustomErr(ctxt,
14857 XML_SCHEMAP_SRC_CT_1,
14858 NULL, type, NULL,
14859 "If <simpleContent> and <extension> is used, the "
14860 "base type must be a simple type. The base type '%s' "
14861 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014862 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014863 base->name));
14864 }
14865 FREE_AND_NULL(str)
14866 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014867 }
14868 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014869 * SPEC (3) "The corresponding complex type definition component must
14870 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014871 * Definition Schema Components (§3.4.6);"
14872 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014873 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014874 /*
14875 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014876 * above for {attribute wildcard} is satisfied, the intensional
14877 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014878 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014879 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014880 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014881 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014882}
William M. Brack2f2a6632004-08-20 23:09:47 +000014883
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014884#ifdef ENABLE_PARTICLE_RESTRICTION
14885/**
14886 * xmlSchemaCheckParticleRangeOK:
14887 * @ctxt: the schema parser context
14888 * @type: the complex type definition
14889 *
14890 * (3.9.6) Constraints on Particle Schema Components
14891 * Schema Component Constraint:
14892 * Occurrence Range OK (range-ok)
14893 *
14894 * STATUS: complete
14895 *
14896 * Returns 0 if the constraints are satisfied, a positive
14897 * error code if not and -1 if an internal error occured.
14898 */
14899static int
14900xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14901 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014902{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014903 if (rmin < bmin)
14904 return (1);
14905 if ((bmax != UNBOUNDED) &&
14906 (rmax > bmax))
14907 return (1);
14908 return (0);
14909}
14910
14911/**
14912 * xmlSchemaCheckRCaseNameAndTypeOK:
14913 * @ctxt: the schema parser context
14914 * @r: the restricting element declaration particle
14915 * @b: the base element declaration particle
14916 *
14917 * (3.9.6) Constraints on Particle Schema Components
14918 * Schema Component Constraint:
14919 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14920 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014921 *
14922 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014923 * MISSING (3.2.3)
14924 * CLARIFY: (3.2.2)
14925 *
14926 * Returns 0 if the constraints are satisfied, a positive
14927 * error code if not and -1 if an internal error occured.
14928 */
14929static int
14930xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14931 xmlSchemaParticlePtr r,
14932 xmlSchemaParticlePtr b)
14933{
14934 xmlSchemaElementPtr elemR, elemB;
14935
14936 /* TODO: Error codes (rcase-NameAndTypeOK). */
14937 elemR = (xmlSchemaElementPtr) r->children;
14938 elemB = (xmlSchemaElementPtr) b->children;
14939 /*
14940 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14941 * the same."
14942 */
14943 if ((elemR != elemB) &&
14944 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14945 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14946 return (1);
14947 /*
14948 * SPEC (2) "R's occurrence range is a valid restriction of B's
14949 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14950 */
14951 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14952 b->minOccurs, b->maxOccurs) != 0)
14953 return (1);
14954 /*
14955 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14956 * {scope} are global."
14957 */
14958 if (elemR == elemB)
14959 return (0);
14960 /*
14961 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14962 */
14963 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14964 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14965 return (1);
14966 /*
14967 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14968 * or is not fixed, or R's declaration's {value constraint} is fixed
14969 * with the same value."
14970 */
14971 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14972 ((elemR->value == NULL) ||
14973 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14974 /* TODO: Equality of the initial value or normalized or canonical? */
14975 (! xmlStrEqual(elemR->value, elemB->value))))
14976 return (1);
14977 /*
14978 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14979 * definitions} is a subset of B's declaration's {identity-constraint
14980 * definitions}, if any."
14981 */
14982 if (elemB->idcs != NULL) {
14983 /* TODO */
14984 }
14985 /*
14986 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14987 * superset of B's declaration's {disallowed substitutions}."
14988 */
14989 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14990 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14991 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14992 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14993 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14994 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14995 return (1);
14996 /*
14997 * SPEC (3.2.5) "R's {type definition} is validly derived given
14998 * {extension, list, union} from B's {type definition}"
14999 *
15000 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15001 * set, if the corresponding constraints handle "restriction" and
15002 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015003 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015004 */
15005 {
15006 int set = 0;
15007
15008 set |= SUBSET_EXTENSION;
15009 set |= SUBSET_LIST;
15010 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015011 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015012 elemB->subtypes, set) != 0)
15013 return (1);
15014 }
15015 return (0);
15016}
15017
15018/**
15019 * xmlSchemaCheckRCaseNSCompat:
15020 * @ctxt: the schema parser context
15021 * @r: the restricting element declaration particle
15022 * @b: the base wildcard particle
15023 *
15024 * (3.9.6) Constraints on Particle Schema Components
15025 * Schema Component Constraint:
15026 * Particle Derivation OK (Elt:Any -- NSCompat)
15027 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015028 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015029 * STATUS: complete
15030 *
15031 * Returns 0 if the constraints are satisfied, a positive
15032 * error code if not and -1 if an internal error occured.
15033 */
15034static int
15035xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15036 xmlSchemaParticlePtr r,
15037 xmlSchemaParticlePtr b)
15038{
15039 /* TODO:Error codes (rcase-NSCompat). */
15040 /*
15041 * SPEC "For an element declaration particle to be a ·valid restriction·
15042 * of a wildcard particle all of the following must be true:"
15043 *
15044 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15045 * with respect to the wildcard's {namespace constraint} as defined by
15046 * Wildcard allows Namespace Name (§3.10.4)."
15047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015048 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015049 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15050 return (1);
15051 /*
15052 * SPEC (2) "R's occurrence range is a valid restriction of B's
15053 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15054 */
15055 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15056 b->minOccurs, b->maxOccurs) != 0)
15057 return (1);
15058
15059 return (0);
15060}
15061
15062/**
15063 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15064 * @ctxt: the schema parser context
15065 * @r: the restricting element declaration particle
15066 * @b: the base model group particle
15067 *
15068 * (3.9.6) Constraints on Particle Schema Components
15069 * Schema Component Constraint:
15070 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15071 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015072 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015073 * STATUS: TODO
15074 *
15075 * Returns 0 if the constraints are satisfied, a positive
15076 * error code if not and -1 if an internal error occured.
15077 */
15078static int
15079xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15080 xmlSchemaParticlePtr r,
15081 xmlSchemaParticlePtr b)
15082{
15083 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15084 TODO
15085 return (0);
15086}
15087
15088/**
15089 * xmlSchemaCheckRCaseNSSubset:
15090 * @ctxt: the schema parser context
15091 * @r: the restricting wildcard particle
15092 * @b: the base wildcard particle
15093 *
15094 * (3.9.6) Constraints on Particle Schema Components
15095 * Schema Component Constraint:
15096 * Particle Derivation OK (Any:Any -- NSSubset)
15097 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015098 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015099 * STATUS: complete
15100 *
15101 * Returns 0 if the constraints are satisfied, a positive
15102 * error code if not and -1 if an internal error occured.
15103 */
15104static int
15105xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15106 xmlSchemaParticlePtr r,
15107 xmlSchemaParticlePtr b,
15108 int isAnyTypeBase)
15109{
15110 /* TODO: Error codes (rcase-NSSubset). */
15111 /*
15112 * SPEC (1) "R's occurrence range is a valid restriction of B's
15113 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15114 */
15115 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15116 b->minOccurs, b->maxOccurs))
15117 return (1);
15118 /*
15119 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15120 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15121 */
15122 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15123 (xmlSchemaWildcardPtr) b->children))
15124 return (1);
15125 /*
15126 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15127 * definition·, R's {process contents} must be identical to or stronger
15128 * than B's {process contents}, where strict is stronger than lax is
15129 * stronger than skip."
15130 */
15131 if (! isAnyTypeBase) {
15132 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15133 ((xmlSchemaWildcardPtr) b->children)->processContents)
15134 return (1);
15135 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015136
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015137 return (0);
15138}
15139
15140/**
15141 * xmlSchemaCheckCOSParticleRestrict:
15142 * @ctxt: the schema parser context
15143 * @type: the complex type definition
15144 *
15145 * (3.9.6) Constraints on Particle Schema Components
15146 * Schema Component Constraint:
15147 * Particle Valid (Restriction) (cos-particle-restrict)
15148 *
15149 * STATUS: TODO
15150 *
15151 * Returns 0 if the constraints are satisfied, a positive
15152 * error code if not and -1 if an internal error occured.
15153 */
15154static int
15155xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15156 xmlSchemaParticlePtr r,
15157 xmlSchemaParticlePtr b)
15158{
15159 int ret = 0;
15160
15161 /*part = GET_PARTICLE(type);
15162 basePart = GET_PARTICLE(base);
15163 */
15164
15165 TODO
15166
15167 /*
15168 * SPEC (1) "They are the same particle."
15169 */
15170 if (r == b)
15171 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015172
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015173
15174 return (0);
15175}
15176
15177/**
15178 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15179 * @ctxt: the schema parser context
15180 * @r: the model group particle
15181 * @b: the base wildcard particle
15182 *
15183 * (3.9.6) Constraints on Particle Schema Components
15184 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015185 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015186 * NSRecurseCheckCardinality)
15187 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015188 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015189 * STATUS: TODO: subst-groups
15190 *
15191 * Returns 0 if the constraints are satisfied, a positive
15192 * error code if not and -1 if an internal error occured.
15193 */
15194static int
15195xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15196 xmlSchemaParticlePtr r,
15197 xmlSchemaParticlePtr b)
15198{
15199 xmlSchemaParticlePtr part;
15200 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15201 if ((r->children == NULL) || (r->children->children == NULL))
15202 return (-1);
15203 /*
15204 * SPEC "For a group particle to be a ·valid restriction· of a
15205 * wildcard particle..."
15206 *
15207 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015208 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015209 * Particle Valid (Restriction) (§3.9.6)."
15210 */
15211 part = (xmlSchemaParticlePtr) r->children->children;
15212 do {
15213 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15214 return (1);
15215 part = (xmlSchemaParticlePtr) part->next;
15216 } while (part != NULL);
15217 /*
15218 * SPEC (2) "The effective total range of the group [...] is a
15219 * valid restriction of B's occurrence range as defined by
15220 * Occurrence Range OK (§3.9.6)."
15221 */
15222 if (xmlSchemaCheckParticleRangeOK(
15223 xmlSchemaGetParticleTotalRangeMin(r),
15224 xmlSchemaGetParticleTotalRangeMax(r),
15225 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015226 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015227 return (0);
15228}
15229
15230/**
15231 * xmlSchemaCheckRCaseRecurse:
15232 * @ctxt: the schema parser context
15233 * @r: the <all> or <sequence> model group particle
15234 * @b: the base <all> or <sequence> model group particle
15235 *
15236 * (3.9.6) Constraints on Particle Schema Components
15237 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015238 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015239 Recurse)
15240 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015241 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015242 * STATUS: ?
15243 * TODO: subst-groups
15244 *
15245 * Returns 0 if the constraints are satisfied, a positive
15246 * error code if not and -1 if an internal error occured.
15247 */
15248static int
15249xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15250 xmlSchemaParticlePtr r,
15251 xmlSchemaParticlePtr b)
15252{
15253 /* xmlSchemaParticlePtr part; */
15254 /* TODO: Error codes (rcase-Recurse). */
15255 if ((r->children == NULL) || (b->children == NULL) ||
15256 (r->children->type != b->children->type))
15257 return (-1);
15258 /*
15259 * SPEC "For an all or sequence group particle to be a ·valid
15260 * restriction· of another group particle with the same {compositor}..."
15261 *
15262 * SPEC (1) "R's occurrence range is a valid restriction of B's
15263 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15264 */
15265 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15266 b->minOccurs, b->maxOccurs))
15267 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015268
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015269
15270 return (0);
15271}
15272
15273#endif
15274
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015275#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15276 xmlSchemaPCustomErrExt(pctxt, \
15277 XML_SCHEMAP_INVALID_FACET_VALUE, \
15278 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15279 "It is an error for both '%s' and '%s' to be specified on the "\
15280 "same type definition", \
15281 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15282 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15283
15284#define FACET_RESTR_ERR(fac1, msg) \
15285 xmlSchemaPCustomErr(pctxt, \
15286 XML_SCHEMAP_INVALID_FACET_VALUE, \
15287 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015288 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015289
15290#define FACET_RESTR_FIXED_ERR(fac) \
15291 xmlSchemaPCustomErr(pctxt, \
15292 XML_SCHEMAP_INVALID_FACET_VALUE, \
15293 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15294 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015295 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015296
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015297static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015298xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15299 xmlSchemaFacetPtr facet1,
15300 xmlSchemaFacetPtr facet2,
15301 int lessGreater,
15302 int orEqual,
15303 int ofBase)
15304{
15305 xmlChar *msg = NULL;
15306
15307 msg = xmlStrdup(BAD_CAST "'");
15308 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15309 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15310 if (lessGreater == 0)
15311 msg = xmlStrcat(msg, BAD_CAST " equal to");
15312 if (lessGreater == 1)
15313 msg = xmlStrcat(msg, BAD_CAST " greater than");
15314 else
15315 msg = xmlStrcat(msg, BAD_CAST " less than");
15316
15317 if (orEqual)
15318 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15319 msg = xmlStrcat(msg, BAD_CAST " '");
15320 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15321 if (ofBase)
15322 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15323 else
15324 msg = xmlStrcat(msg, BAD_CAST "'");
15325
15326 xmlSchemaPCustomErr(pctxt,
15327 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015328 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015329 (const char *) msg, NULL);
15330
15331 if (msg != NULL)
15332 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015333}
15334
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015335static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015336xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15337 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015338{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015339 xmlSchemaTypePtr base = type->baseType;
15340 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015341 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015342 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15343 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15344 fmininc = NULL, fmaxinc = NULL,
15345 fminexc = NULL, fmaxexc = NULL,
15346 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15347 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15348 bfmininc = NULL, bfmaxinc = NULL,
15349 bfminexc = NULL, bfmaxexc = NULL;
15350 int res, err = 0, fixedErr;
15351 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015352 * 3 The {facets} of R are the union of S and the {facets}
15353 * of B, eliminating duplicates. To eliminate duplicates,
15354 * when a facet of the same kind occurs in both S and the
15355 * {facets} of B, the one in the {facets} of B is not
15356 * included, with the exception of enumeration and pattern
15357 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015358 * are allowed.
15359 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015360
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015361 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15362 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015363
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015364 last = type->facetSet;
15365 if (last != NULL)
15366 while (last->next != NULL)
15367 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015368
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015369 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15370 facet = cur->facet;
15371 switch (facet->type) {
15372 case XML_SCHEMA_FACET_LENGTH:
15373 flength = facet; break;
15374 case XML_SCHEMA_FACET_MINLENGTH:
15375 fminlen = facet; break;
15376 case XML_SCHEMA_FACET_MININCLUSIVE:
15377 fmininc = facet; break;
15378 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15379 fminexc = facet; break;
15380 case XML_SCHEMA_FACET_MAXLENGTH:
15381 fmaxlen = facet; break;
15382 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15383 fmaxinc = facet; break;
15384 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15385 fmaxexc = facet; break;
15386 case XML_SCHEMA_FACET_TOTALDIGITS:
15387 ftotdig = facet; break;
15388 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15389 ffracdig = facet; break;
15390 default:
15391 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015392 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015393 }
15394 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15395 facet = cur->facet;
15396 switch (facet->type) {
15397 case XML_SCHEMA_FACET_LENGTH:
15398 bflength = facet; break;
15399 case XML_SCHEMA_FACET_MINLENGTH:
15400 bfminlen = facet; break;
15401 case XML_SCHEMA_FACET_MININCLUSIVE:
15402 bfmininc = facet; break;
15403 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15404 bfminexc = facet; break;
15405 case XML_SCHEMA_FACET_MAXLENGTH:
15406 bfmaxlen = facet; break;
15407 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15408 bfmaxinc = facet; break;
15409 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15410 bfmaxexc = facet; break;
15411 case XML_SCHEMA_FACET_TOTALDIGITS:
15412 bftotdig = facet; break;
15413 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15414 bffracdig = facet; break;
15415 default:
15416 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015417 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015418 }
15419 err = 0;
15420 /*
15421 * length and minLength or maxLength (2.2) + (3.2)
15422 */
15423 if (flength && (fminlen || fmaxlen)) {
15424 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15425 "either of 'minLength' or 'maxLength' to be specified on "
15426 "the same type definition")
15427 }
15428 /*
15429 * Mutual exclusions in the same derivation step.
15430 */
15431 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015432 /*
15433 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015434 */
15435 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15436 }
15437 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015438 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015439 * SCC "minInclusive and minExclusive"
15440 */
15441 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015442 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015443
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015444 if (flength && bflength) {
15445 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015446 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015447 * The values have to be equal.
15448 */
15449 res = xmlSchemaCompareValues(flength->val, bflength->val);
15450 if (res == -2)
15451 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015452 if (res != 0)
15453 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15454 if ((res != 0) && (bflength->fixed)) {
15455 FACET_RESTR_FIXED_ERR(flength)
15456 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015457
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015458 }
15459 if (fminlen && bfminlen) {
15460 /*
15461 * SCC "minLength valid restriction"
15462 * minLength >= BASE minLength
15463 */
15464 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15465 if (res == -2)
15466 goto internal_error;
15467 if (res == -1)
15468 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15469 if ((res != 0) && (bfminlen->fixed)) {
15470 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015471 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015472 }
15473 if (fmaxlen && bfmaxlen) {
15474 /*
15475 * SCC "maxLength valid restriction"
15476 * maxLength <= BASE minLength
15477 */
15478 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15479 if (res == -2)
15480 goto internal_error;
15481 if (res == 1)
15482 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15483 if ((res != 0) && (bfmaxlen->fixed)) {
15484 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015485 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015486 }
15487 /*
15488 * SCC "length and minLength or maxLength"
15489 */
15490 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015491 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015492 if (flength) {
15493 if (! fminlen)
15494 flength = bflength;
15495 if (fminlen) {
15496 /* (1.1) length >= minLength */
15497 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15498 if (res == -2)
15499 goto internal_error;
15500 if (res == -1)
15501 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15502 }
15503 if (! fmaxlen)
15504 fmaxlen = bfmaxlen;
15505 if (fmaxlen) {
15506 /* (2.1) length <= maxLength */
15507 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15508 if (res == -2)
15509 goto internal_error;
15510 if (res == 1)
15511 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15512 }
15513 }
15514 if (fmaxinc) {
15515 /*
15516 * "maxInclusive"
15517 */
15518 if (fmininc) {
15519 /* SCC "maxInclusive >= minInclusive" */
15520 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15521 if (res == -2)
15522 goto internal_error;
15523 if (res == -1) {
15524 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15525 }
15526 }
15527 /*
15528 * SCC "maxInclusive valid restriction"
15529 */
15530 if (bfmaxinc) {
15531 /* maxInclusive <= BASE maxInclusive */
15532 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15533 if (res == -2)
15534 goto internal_error;
15535 if (res == 1)
15536 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15537 if ((res != 0) && (bfmaxinc->fixed)) {
15538 FACET_RESTR_FIXED_ERR(fmaxinc)
15539 }
15540 }
15541 if (bfmaxexc) {
15542 /* maxInclusive < BASE maxExclusive */
15543 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15544 if (res == -2)
15545 goto internal_error;
15546 if (res != -1) {
15547 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15548 }
15549 }
15550 if (bfmininc) {
15551 /* maxInclusive >= BASE minInclusive */
15552 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15553 if (res == -2)
15554 goto internal_error;
15555 if (res == -1) {
15556 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15557 }
15558 }
15559 if (bfminexc) {
15560 /* maxInclusive > BASE minExclusive */
15561 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15562 if (res == -2)
15563 goto internal_error;
15564 if (res != 1) {
15565 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15566 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015567 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015568 }
15569 if (fmaxexc) {
15570 /*
15571 * "maxExclusive >= minExclusive"
15572 */
15573 if (fminexc) {
15574 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15575 if (res == -2)
15576 goto internal_error;
15577 if (res == -1) {
15578 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15579 }
15580 }
15581 /*
15582 * "maxExclusive valid restriction"
15583 */
15584 if (bfmaxexc) {
15585 /* maxExclusive <= BASE maxExclusive */
15586 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15587 if (res == -2)
15588 goto internal_error;
15589 if (res == 1) {
15590 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15591 }
15592 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015593 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015594 }
15595 }
15596 if (bfmaxinc) {
15597 /* maxExclusive <= BASE maxInclusive */
15598 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15599 if (res == -2)
15600 goto internal_error;
15601 if (res == 1) {
15602 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15603 }
15604 }
15605 if (bfmininc) {
15606 /* maxExclusive > BASE minInclusive */
15607 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15608 if (res == -2)
15609 goto internal_error;
15610 if (res != 1) {
15611 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15612 }
15613 }
15614 if (bfminexc) {
15615 /* maxExclusive > BASE minExclusive */
15616 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15617 if (res == -2)
15618 goto internal_error;
15619 if (res != 1) {
15620 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15621 }
15622 }
15623 }
15624 if (fminexc) {
15625 /*
15626 * "minExclusive < maxInclusive"
15627 */
15628 if (fmaxinc) {
15629 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15630 if (res == -2)
15631 goto internal_error;
15632 if (res != -1) {
15633 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15634 }
15635 }
15636 /*
15637 * "minExclusive valid restriction"
15638 */
15639 if (bfminexc) {
15640 /* minExclusive >= BASE minExclusive */
15641 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15642 if (res == -2)
15643 goto internal_error;
15644 if (res == -1) {
15645 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15646 }
15647 if ((res != 0) && (bfminexc->fixed)) {
15648 FACET_RESTR_FIXED_ERR(fminexc)
15649 }
15650 }
15651 if (bfmaxinc) {
15652 /* minExclusive <= BASE maxInclusive */
15653 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15654 if (res == -2)
15655 goto internal_error;
15656 if (res == 1) {
15657 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15658 }
15659 }
15660 if (bfmininc) {
15661 /* minExclusive >= BASE minInclusive */
15662 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15663 if (res == -2)
15664 goto internal_error;
15665 if (res == -1) {
15666 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15667 }
15668 }
15669 if (bfmaxexc) {
15670 /* minExclusive < BASE maxExclusive */
15671 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15672 if (res == -2)
15673 goto internal_error;
15674 if (res != -1) {
15675 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15676 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015677 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015678 }
15679 if (fmininc) {
15680 /*
15681 * "minInclusive < maxExclusive"
15682 */
15683 if (fmaxexc) {
15684 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15685 if (res == -2)
15686 goto internal_error;
15687 if (res != -1) {
15688 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15689 }
15690 }
15691 /*
15692 * "minExclusive valid restriction"
15693 */
15694 if (bfmininc) {
15695 /* minInclusive >= BASE minInclusive */
15696 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15697 if (res == -2)
15698 goto internal_error;
15699 if (res == -1) {
15700 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15701 }
15702 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015703 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015704 }
15705 }
15706 if (bfmaxinc) {
15707 /* minInclusive <= BASE maxInclusive */
15708 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15709 if (res == -2)
15710 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000015711 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015712 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15713 }
15714 }
15715 if (bfminexc) {
15716 /* minInclusive > BASE minExclusive */
15717 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15718 if (res == -2)
15719 goto internal_error;
15720 if (res != 1)
15721 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15722 }
15723 if (bfmaxexc) {
15724 /* minInclusive < BASE maxExclusive */
15725 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15726 if (res == -2)
15727 goto internal_error;
15728 if (res != -1)
15729 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15730 }
15731 }
15732 if (ftotdig && bftotdig) {
15733 /*
15734 * SCC " totalDigits valid restriction"
15735 * totalDigits <= BASE totalDigits
15736 */
15737 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15738 if (res == -2)
15739 goto internal_error;
15740 if (res == 1)
15741 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15742 -1, 1, 1);
15743 if ((res != 0) && (bftotdig->fixed)) {
15744 FACET_RESTR_FIXED_ERR(ftotdig)
15745 }
15746 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015747 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015748 /*
15749 * SCC "fractionDigits valid restriction"
15750 * fractionDigits <= BASE fractionDigits
15751 */
15752 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15753 if (res == -2)
15754 goto internal_error;
15755 if (res == 1)
15756 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15757 -1, 1, 1);
15758 if ((res != 0) && (bffracdig->fixed)) {
15759 FACET_RESTR_FIXED_ERR(ffracdig)
15760 }
15761 }
15762 /*
15763 * SCC "fractionDigits less than or equal to totalDigits"
15764 */
15765 if (! ftotdig)
15766 ftotdig = bftotdig;
15767 if (! ffracdig)
15768 ffracdig = bffracdig;
15769 if (ftotdig && ffracdig) {
15770 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15771 if (res == -2)
15772 goto internal_error;
15773 if (res == 1)
15774 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15775 -1, 1, 0);
15776 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015777 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015778 * *Enumerations* won' be added here, since only the first set
15779 * of enumerations in the ancestor-or-self axis is used
15780 * for validation, plus we need to use the base type of those
15781 * enumerations for whitespace.
15782 *
15783 * *Patterns*: won't be add here, since they are ORed at
15784 * type level and ANDed at ancestor level. This will
15785 * happed during validation by walking the base axis
15786 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015787 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015788 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15789 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015790 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015791 * Special handling of enumerations and patterns.
15792 * TODO: hmm, they should not appear in the set, so remove this.
15793 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015794 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015795 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015796 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015797 /*
15798 * Search for a duplicate facet in the current type.
15799 */
15800 link = type->facetSet;
15801 err = 0;
15802 fixedErr = 0;
15803 while (link != NULL) {
15804 facet = link->facet;
15805 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015806 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015807 case XML_SCHEMA_FACET_WHITESPACE:
15808 /*
15809 * The whitespace must be stronger.
15810 */
15811 if (facet->whitespace < bfacet->whitespace) {
15812 FACET_RESTR_ERR(flength,
15813 "The 'whitespace' value has to be equal to "
15814 "or stronger than the 'whitespace' value of "
15815 "the base type")
15816 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015817 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015818 (facet->whitespace != bfacet->whitespace)) {
15819 FACET_RESTR_FIXED_ERR(facet)
15820 }
15821 break;
15822 default:
15823 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015824 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015825 /* Duplicate found. */
15826 break;
15827 }
15828 link = link->next;
15829 }
15830 /*
15831 * If no duplicate was found: add the base types's facet
15832 * to the set.
15833 */
15834 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015835 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015836 xmlMalloc(sizeof(xmlSchemaFacetLink));
15837 if (link == NULL) {
15838 xmlSchemaPErrMemory(pctxt,
15839 "deriving facets, creating a facet link", NULL);
15840 return (-1);
15841 }
15842 link->facet = cur->facet;
15843 link->next = NULL;
15844 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015845 type->facetSet = link;
15846 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015847 last->next = link;
15848 last = link;
15849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015850
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015851 }
15852
15853 return (0);
15854internal_error:
15855 xmlSchemaPCustomErr(pctxt,
15856 XML_SCHEMAP_INVALID_FACET_VALUE,
15857 NULL, type, NULL,
15858 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15859 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015860}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015861
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015862static int
15863xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15864 xmlSchemaTypePtr type)
15865{
15866 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15867 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015868 * The actual value is then formed by replacing any union type
15869 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015870 * {member type definitions}, in order.
15871 */
15872 link = type->memberTypes;
15873 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015874
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015875 if (IS_NOT_TYPEFIXED(link->type))
15876 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15877
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015878 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015879 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015880 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015881 link->type = subLink->type;
15882 if (subLink->next != NULL) {
15883 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015884 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015885 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015886 while (subLink != NULL) {
15887 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015888 xmlMalloc(sizeof(xmlSchemaTypeLink));
15889 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015890 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015891 NULL);
15892 return (-1);
15893 }
15894 newLink->type = subLink->type;
15895 prevLink->next = newLink;
15896 prevLink = newLink;
15897 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015898
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015899 subLink = subLink->next;
15900 }
15901 }
15902 }
15903 }
15904 link = link->next;
15905 }
15906 return (0);
15907}
15908
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015909static void
15910xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15911{
15912 int has = 0, needVal = 0, normVal = 0;
15913
15914 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15915 if (has) {
15916 needVal = (type->baseType->flags &
15917 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15918 normVal = (type->baseType->flags &
15919 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15920 }
15921 if (type->facets != NULL) {
15922 xmlSchemaFacetPtr fac;
15923
15924 for (fac = type->facets; fac != NULL; fac = fac->next) {
15925 switch (fac->type) {
15926 case XML_SCHEMA_FACET_WHITESPACE:
15927 break;
15928 case XML_SCHEMA_FACET_PATTERN:
15929 normVal = 1;
15930 has = 1;
15931 break;
15932 case XML_SCHEMA_FACET_ENUMERATION:
15933 needVal = 1;
15934 normVal = 1;
15935 has = 1;
15936 break;
15937 default:
15938 has = 1;
15939 break;
15940 }
15941 }
15942 }
15943 if (normVal)
15944 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15945 if (needVal)
15946 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15947 if (has)
15948 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15949
15950 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15951 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15952 /*
15953 * OPTIMIZE VAL TODO: Some facets need a computed value.
15954 */
15955 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15956 (prim->builtInType != XML_SCHEMAS_STRING)) {
15957 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15958 }
15959 }
15960}
15961
15962static int
15963xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15964{
15965
15966
15967 /*
15968 * Evaluate the whitespace-facet value.
15969 */
15970 if (VARIETY_LIST(type)) {
15971 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15972 return (0);
15973 } else if (VARIETY_UNION(type))
15974 return (0);
15975
15976 if (type->facetSet != NULL) {
15977 xmlSchemaFacetLinkPtr lin;
15978
15979 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15980 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15981 switch (lin->facet->whitespace) {
15982 case XML_SCHEMAS_FACET_PRESERVE:
15983 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15984 break;
15985 case XML_SCHEMAS_FACET_REPLACE:
15986 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15987 break;
15988 case XML_SCHEMAS_FACET_COLLAPSE:
15989 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15990 break;
15991 default:
15992 return (-1);
15993 }
15994 return (0);
15995 }
15996 }
15997 }
15998 /*
15999 * For all ·atomic· datatypes other than string (and types ·derived·
16000 * by ·restriction· from it) the value of whiteSpace is fixed to
16001 * collapse
16002 */
16003 {
16004 xmlSchemaTypePtr anc;
16005
16006 for (anc = type->baseType; anc != NULL &&
16007 anc->builtInType != XML_SCHEMAS_ANYTYPE;
16008 anc = anc->baseType) {
16009
16010 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
16011 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
16012 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16013
16014 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16015 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
16016 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16017
16018 } else
16019 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16020 break;
16021 }
16022 }
16023 return (0);
16024 }
16025 return (0);
16026}
16027
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016028/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016029 * xmlSchemaTypeFixup:
16030 * @typeDecl: the schema type definition
16031 * @ctxt: the schema parser context
16032 *
16033 * Fixes the content model of the type.
16034 */
16035static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016036xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016037 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016038{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016039 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016040 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016041 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16042 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016043 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016044 if (! IS_NOT_TYPEFIXED(type))
16045 return;
16046 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016047 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016048 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016049
16050 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016051 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016052 XML_SCHEMAP_INTERNAL,
16053 NULL, type, NULL,
16054 "Internal error: xmlSchemaTypeFixup, "
16055 "baseType is missing on '%s'", type->name);
16056 return;
16057 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016058
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016059 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016060 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016061
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016062 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016063 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016064 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016065 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016066 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016067 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16068 /*
16069 * Skip fixup if the base type is invalid.
16070 * TODO: Generate a warning!
16071 */
16072 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016073 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016074 /*
16075 * This basically checks if the base type can be derived.
16076 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016077 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016078 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16079 return;
16080 }
16081 /*
16082 * Fixup the content type.
16083 */
16084 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16085 /*
16086 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016087 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016088 if ((IS_COMPLEX_TYPE(baseType)) &&
16089 (baseType->contentTypeDef != NULL) &&
16090 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016091 xmlSchemaTypePtr contentBase, content;
16092 char buf[30];
16093 const xmlChar *tmpname;
16094 /*
16095 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016096 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016097 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016098 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016099 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016100 * SPEC (1.1) "the simple type definition corresponding to the
16101 * <simpleType> among the [children] of <restriction> if there
16102 * is one;"
16103 * Note that this "<simpleType> among the [children]" was put
16104 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016106 contentBase = type->contentTypeDef;
16107 type->contentTypeDef = NULL;
16108 } else {
16109 /*
16110 * (1.2) "...otherwise (<restriction> has no <simpleType>
16111 * among its [children]), the simple type definition which
16112 * is the {content type} of the ... base type."
16113 */
16114 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016115 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016116 /*
16117 * SPEC
16118 * "... a simple type definition which restricts the simple
16119 * type definition identified in clause 1.1 or clause 1.2
16120 * with a set of facet components"
16121 *
16122 * Create the anonymous simple type, which will be the content
16123 * type of the complex type.
16124 */
16125 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16126 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16127 content = xmlSchemaAddType(pctxt,
16128 pctxt->schema, tmpname, tmpname, type->node);
16129 if (content == NULL)
16130 return;
16131 /*
16132 * We will use the same node as for the <complexType>
16133 * to have it somehow anchored in the schema doc.
16134 */
16135 content->node = type->node;
16136 content->type = XML_SCHEMA_TYPE_SIMPLE;
16137 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16138 content->baseType = contentBase;
16139 /*
16140 * Move the facets, previously anchored on the complexType.
16141 */
16142 content->facets = type->facets;
16143 type->facets = NULL;
16144 content->facetSet = type->facetSet;
16145 type->facetSet = NULL;
16146
16147 type->contentTypeDef = content;
16148 if (IS_NOT_TYPEFIXED(contentBase))
16149 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16150 xmlSchemaTypeFixup(content, pctxt, NULL);
16151
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016152 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16153 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16154 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16155 /*
16156 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16157 * an emptiable particle, then a simple type definition which
16158 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016159 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016160 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 (type->contentTypeDef->baseType == NULL)) {
16162 /*
16163 * TODO: Check if this ever happens.
16164 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016165 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016166 XML_SCHEMAP_INTERNAL,
16167 NULL, type, NULL,
16168 "Internal error: xmlSchemaTypeFixup, "
16169 "complex type '%s': the <simpleContent><restriction> "
16170 "is missing a <simpleType> child, but was not catched "
16171 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016172 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016173 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16174 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16175 /*
16176 * SPEC (3) If <extension> + base is <complexType> with
16177 * <simpleType> content, "...then the {content type} of that
16178 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016179 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016180 if (baseType->contentTypeDef == NULL) {
16181 /*
16182 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16183 * should have catched this already.
16184 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016185 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016186 XML_SCHEMAP_INTERNAL,
16187 NULL, type, NULL,
16188 "Internal error: xmlSchemaTypeFixup, "
16189 "complex type '%s': the <extension>ed base type is "
16190 "a complex type with no simple content type",
16191 type->name);
16192 }
16193 type->contentTypeDef = baseType->contentTypeDef;
16194 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16195 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16196 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016197 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016198 * "... then that simple type definition"
16199 */
16200 type->contentTypeDef = baseType;
16201 } else {
16202 /*
16203 * TODO: Check if this ever happens.
16204 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016205 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016206 XML_SCHEMAP_INTERNAL,
16207 NULL, type, NULL,
16208 "Internal error: xmlSchemaTypeFixup, "
16209 "complex type '%s' with <simpleContent>: unhandled "
16210 "derivation case", type->name);
16211 }
16212 } else {
16213 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016214 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016215 (xmlSchemaParticlePtr) type->subtypes;
16216 /*
16217 * Corresponds to <complexType><complexContent>...
16218 *
16219 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016220 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016221 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016222 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016223 * Compute the "effective content":
16224 * (2.1.1) + (2.1.2) + (2.1.3)
16225 */
16226 if ((particle == NULL) ||
16227 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16228 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16229 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16230 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16231 (particle->minOccurs == 0))) &&
16232 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016233 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016234 /*
16235 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16236 * a particle whose properties are as follows:..."
16237 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016238 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016239 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16240 * NOTE that we sill assign it the <complexType> node to
16241 * somehow anchor it in the doc.
16242 */
16243 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016244 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016245 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016246 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016247 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016248 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016249 type->node, 1, 1);
16250 if (particle == NULL)
16251 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016252 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016253 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016254 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016255 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016256 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016257 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16258 if (particle->children == NULL)
16259 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016260
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016261 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016262 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016263 dummySequence = 1;
16264 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16265 } else {
16266 /*
16267 * SPEC (2.1.5) "otherwise empty"
16268 */
16269 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016270 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016271 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016272 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016273 * SPEC (2.2) "otherwise the particle corresponding to the
16274 * <all>, <choice>, <group> or <sequence> among the
16275 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016276 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016277 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16278 }
16279 /*
16280 * Compute the "content type".
16281 */
16282 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016283 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016284 * SPEC (3.1) "If <restriction>..."
16285 * (3.1.1) + (3.1.2) */
16286 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16287 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16288 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16289 }
16290 } else {
16291 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016292 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016293 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016294 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16295 /*
16296 * SPEC (3.2.1)
16297 */
16298 type->contentType = baseType->contentType;
16299 type->subtypes = baseType->subtypes;
16300 /*
16301 * NOTE that the effective mixed is ignored here.
16302 */
16303 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16304 /*
16305 * SPEC (3.2.2)
16306 */
16307 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16308 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16309 } else {
16310 /*
16311 * SPEC (3.2.3)
16312 */
16313 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16314 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16315 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016316 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016317 * {particles} are..."
16318 */
16319 if (! dummySequence) {
16320 xmlSchemaTreeItemPtr effectiveContent =
16321 (xmlSchemaTreeItemPtr) type->subtypes;
16322 /*
16323 * Create the particle.
16324 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016325 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016326 type->node, 1, 1);
16327 if (particle == NULL)
16328 return;
16329 /*
16330 * Create the "sequence" model group.
16331 */
16332 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016333 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016334 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16335 if (particle->children == NULL)
16336 return;
16337 type->subtypes = (xmlSchemaTypePtr) particle;
16338 /*
16339 * SPEC "the particle of the {content type} of
16340 * the ... base ..."
16341 * Create a duplicate of the base type's particle
16342 * and assign its "term" to it.
16343 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016344 particle->children->children =
16345 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16346 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016347 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 if (particle->children->children == NULL)
16350 return;
16351 particle = (xmlSchemaParticlePtr)
16352 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016353 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016354 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16355 /*
16356 * SPEC "followed by the ·effective content·."
16357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016358 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016359 } else {
16360 /*
16361 * This is the case when there is already an empty
16362 * <sequence> with minOccurs==maxOccurs==1.
16363 * Just add the base types's content type.
16364 * NOTE that, although we miss to add an intermediate
16365 * <sequence>, this should produce no difference to
16366 * neither the regex compilation of the content model,
16367 * nor to the complex type contraints.
16368 */
16369 particle->children->children =
16370 (xmlSchemaTreeItemPtr) baseType->subtypes;
16371 }
16372 }
16373 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016374 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016375 /*
16376 * Apply the complex type component constraints; this will not
16377 * check attributes, since this is done in
16378 * xmlSchemaBuildAttributeValidation().
16379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016380 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16381 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 /*
16383 * Inherit & check constraints for attributes.
16384 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016385 xmlSchemaBuildAttributeValidation(pctxt, type);
16386 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016387 /*
16388 * Simple Type Definition Schema Component
16389 */
16390 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016391 if (VARIETY_LIST(type)) {
16392 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016393 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016395 if (type->subtypes == NULL) {
16396 /*
16397 * This one is really needed, so get out.
16398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016399 PERROR_INT("xmlSchemaTypeFixup",
16400 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 return;
16402 }
16403 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016404 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16405 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016406 /*
16407 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 if (type->memberTypes == NULL) {
16410 /*
16411 * This one is really needed, so get out.
16412 */
16413 return;
16414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016415 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016416 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016417 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016418 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016419 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016420 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016421 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016422 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016423 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16424 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016425 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016427 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016428 */
16429 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016430 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016431 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016432 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16433 /*
16434 * Inherit the itemType.
16435 */
16436 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016437 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016438 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16439 /*
16440 * NOTE that we won't assign the memberTypes of the base,
16441 * since this will make trouble when freeing them; we will
16442 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016443 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016444 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016445 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016446 /*
16447 * Check constraints.
16448 *
16449 * TODO: Split this somehow, we need to know first if we can derive
16450 * from the base type at all!
16451 */
16452 if (type->baseType != NULL) {
16453 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016454 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016455 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016456 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016457 * applied beforehand.
16458 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016459 xmlSchemaCheckSRCSimpleType(pctxt, type);
16460 xmlSchemaCheckFacetValues(type, pctxt);
16461 if ((type->facetSet != NULL) ||
16462 (type->baseType->facetSet != NULL))
16463 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16464 /*
16465 * Whitespace value.
16466 */
16467 xmlSchemaTypeFixupWhitespace(type);
16468 xmlSchemaTypeFixupOptimFacets(type);
16469 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016470 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016471
Daniel Veillard8651f532002-04-17 09:06:27 +000016472#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016473 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016474 xmlGenericError(xmlGenericErrorContext,
16475 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016476 type->node->doc->URL,
16477 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016478 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016479 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016480 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016481 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16482 switch (type->contentType) {
16483 case XML_SCHEMA_CONTENT_SIMPLE:
16484 xmlGenericError(xmlGenericErrorContext, "simple\n");
16485 break;
16486 case XML_SCHEMA_CONTENT_ELEMENTS:
16487 xmlGenericError(xmlGenericErrorContext, "elements\n");
16488 break;
16489 case XML_SCHEMA_CONTENT_UNKNOWN:
16490 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16491 break;
16492 case XML_SCHEMA_CONTENT_EMPTY:
16493 xmlGenericError(xmlGenericErrorContext, "empty\n");
16494 break;
16495 case XML_SCHEMA_CONTENT_MIXED:
16496 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016497 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016498 xmlGenericError(xmlGenericErrorContext,
16499 "mixed as emptiable particle\n");
16500 else
16501 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16502 break;
16503 /* Removed, since not used. */
16504 /*
16505 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16506 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16507 break;
16508 */
16509 case XML_SCHEMA_CONTENT_BASIC:
16510 xmlGenericError(xmlGenericErrorContext, "basic\n");
16511 break;
16512 default:
16513 xmlGenericError(xmlGenericErrorContext,
16514 "not registered !!!\n");
16515 break;
16516 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016517 }
16518#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016519}
16520
16521/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016522 * xmlSchemaCheckFacet:
16523 * @facet: the facet
16524 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016525 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016527 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016528 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016529 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016530 * Returns 0 if valid, a positive error code if not valid and
16531 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016532 */
16533int
16534xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016535 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016536 xmlSchemaParserCtxtPtr pctxt,
16537 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016538{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016539 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016540
Daniel Veillardce682bc2004-11-05 17:22:25 +000016541 if ((facet == NULL) || (typeDecl == NULL))
16542 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016543 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016544 * TODO: will the parser context be given if used from
16545 * the relaxNG module?
16546 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016547 if (pctxt == NULL)
16548 ctxtGiven = 0;
16549 else
16550 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016551
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016552 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016553 case XML_SCHEMA_FACET_MININCLUSIVE:
16554 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16555 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016556 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16557 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016558 /*
16559 * Okay we need to validate the value
16560 * at that point.
16561 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016562 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016563
16564 /* 4.3.5.5 Constraints on enumeration Schema Components
16565 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016566 * It is an ·error· if any member of {value} is not in the
16567 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016568 *
16569 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016570 * The value ·must· be in the
16571 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016572 */
16573 /*
16574 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016575 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016576 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016577 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016578 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016579 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016580 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016581 */
16582 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16583 base = typeDecl->baseType;
16584 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016585 PERROR_INT("xmlSchemaCheckFacet",
16586 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016587 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016588 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016589 } else
16590 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591
16592 if (! ctxtGiven) {
16593 /*
16594 * A context is needed if called from RelaxNG.
16595 */
16596 pctxt = xmlSchemaNewParserCtxt("*");
16597 if (pctxt == NULL)
16598 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016599 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016600 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016601 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016602 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016603 * facet->node is just the node holding the facet
16604 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016605 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016606 */
16607 ret = xmlSchemaVCheckCVCSimpleType(
16608 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16609 facet->value, &(facet->val), 1, 1, 0);
16610 if (ret != 0) {
16611 if (ret < 0) {
16612 /* No error message for RelaxNG. */
16613 if (ctxtGiven) {
16614 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16615 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16616 "Internal error: xmlSchemaCheckFacet, "
16617 "failed to validate the value '%s' of the "
16618 "facet '%s' against the base type",
16619 facet->value, xmlSchemaFacetTypeToString(facet->type));
16620 }
16621 goto internal_error;
16622 }
16623 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16624 /* No error message for RelaxNG. */
16625 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016626 xmlChar *str = NULL;
16627
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016628 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16629 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016630 "The value '%s' of the facet does not validate "
16631 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016632 facet->value,
16633 xmlSchemaFormatQName(&str,
16634 base->targetNamespace, base->name));
16635 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016636 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016637 goto exit;
16638 } else if (facet->val == NULL) {
16639 if (ctxtGiven) {
16640 PERROR_INT("xmlSchemaCheckFacet",
16641 "value was not computed");
16642 }
16643 TODO
16644 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016645 break;
16646 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016647 case XML_SCHEMA_FACET_PATTERN:
16648 facet->regexp = xmlRegexpCompile(facet->value);
16649 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016650 ret = XML_SCHEMAP_REGEXP_INVALID;
16651 /* No error message for RelaxNG. */
16652 if (ctxtGiven) {
16653 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16654 ret, facet->node, typeDecl,
16655 "The value '%s' of the facet 'pattern' is not a "
16656 "valid regular expression",
16657 facet->value, NULL);
16658 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016659 }
16660 break;
16661 case XML_SCHEMA_FACET_TOTALDIGITS:
16662 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16663 case XML_SCHEMA_FACET_LENGTH:
16664 case XML_SCHEMA_FACET_MAXLENGTH:
16665 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016666 ret = xmlSchemaValidatePredefinedType(
16667 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16668 facet->value, &(facet->val));
16669 if (ret != 0) {
16670 if (ret < 0) {
16671 /* No error message for RelaxNG. */
16672 if (ctxtGiven) {
16673 PERROR_INT("xmlSchemaCheckFacet",
16674 "validating facet value");
16675 }
16676 goto internal_error;
16677 }
16678 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16679 /* No error message for RelaxNG. */
16680 if (ctxtGiven) {
16681 /* error code */
16682 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16683 ret, facet->node, typeDecl,
16684 "The value '%s' of the facet '%s' is not a valid "
16685 "'nonNegativeInteger'",
16686 facet->value,
16687 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016688 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016689 }
16690 break;
16691 }
16692 case XML_SCHEMA_FACET_WHITESPACE:{
16693 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16694 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16695 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16696 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16697 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16698 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16699 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016700 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16701 /* No error message for RelaxNG. */
16702 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016703 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016704 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16705 ret, facet->node, typeDecl,
16706 "The value '%s' of the facet 'whitespace' is not "
16707 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016708 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016709 }
16710 }
16711 default:
16712 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016713 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016714exit:
16715 if ((! ctxtGiven) && (pctxt != NULL))
16716 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016717 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016718internal_error:
16719 if ((! ctxtGiven) && (pctxt != NULL))
16720 xmlSchemaFreeParserCtxt(pctxt);
16721 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016722}
16723
16724/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016725 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016726 * @typeDecl: the schema type definition
16727 * @ctxt: the schema parser context
16728 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016729 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016730 */
16731static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016732xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16733 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016734{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016735 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016736 /*
16737 * NOTE: It is intended to use the facets list, instead
16738 * of facetSet.
16739 */
16740 if (typeDecl->facets != NULL) {
16741 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016742
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016743 /*
16744 * Temporarily assign the "schema" to the validation context
16745 * of the parser context. This is needed for NOTATION validation.
16746 */
16747 if (ctxt->vctxt == NULL) {
16748 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16749 return;
16750 }
16751 ctxt->vctxt->schema = ctxt->schema;
16752
Daniel Veillard01fa6152004-06-29 17:04:39 +000016753 while (facet != NULL) {
16754 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16755 facet = facet->next;
16756 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016757
16758 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016759 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016760}
16761
16762/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016763 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016764 * @ctxtMGroup: the searched model group
16765 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016766 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016767 *
16768 * This one is intended to be used by
16769 * xmlSchemaCheckGroupDefCircular only.
16770 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016771 * Returns the particle with the circular model group definition reference,
16772 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016773 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016774static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016775xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016776 xmlSchemaTreeItemPtr particle)
16777{
16778 xmlSchemaTreeItemPtr circ = NULL;
16779 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016780 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016781
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016782 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016783 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016784 if (term == NULL)
16785 continue;
16786 switch (term->type) {
16787 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016788 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016789 if (gdef == groupDef)
16790 return (particle);
16791 /*
16792 * Mark this model group definition to avoid infinite
16793 * recursion on circular references not yet examined.
16794 */
16795 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16796 continue;
16797 if (gdef->children != NULL) {
16798 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16799 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16800 gdef->children->children);
16801 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16802 if (circ != NULL)
16803 return (circ);
16804 }
16805 break;
16806 case XML_SCHEMA_TYPE_SEQUENCE:
16807 case XML_SCHEMA_TYPE_CHOICE:
16808 case XML_SCHEMA_TYPE_ALL:
16809 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16810 if (circ != NULL)
16811 return (circ);
16812 break;
16813 default:
16814 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016815 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016816 }
16817 return (NULL);
16818}
16819
16820/**
16821 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016822 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016823 * @ctxt: the parser context
16824 * @name: the name
16825 *
16826 * Checks for circular references to model group definitions.
16827 */
16828static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016829xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016830 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016831 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016832{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016833 /*
16834 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016835 * 2 Circular groups are disallowed. That is, within the {particles}
16836 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016837 * is the group itself.
16838 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016839 if ((item == NULL) ||
16840 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16841 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016842 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016843 {
16844 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016845
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016846 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016847 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016848 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016849 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016850 * TODO: The error report is not adequate: this constraint
16851 * is defined for model groups but not definitions, but since
16852 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016853 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016854 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016855 */
16856 xmlSchemaPCustomErr(ctxt,
16857 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016858 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016859 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016860 "defined", xmlSchemaFormatQName(&str,
16861 item->targetNamespace, item->name));
16862 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016863 /*
16864 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016865 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016866 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016867 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016868 }
16869 }
16870}
16871
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016872/**
16873 * xmlSchemaGroupDefTermFixup:
16874 * @item: the particle with a model group definition as term
16875 * @ctxt: the parser context
16876 * @name: the name
16877 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016878 * Checks cos-all-limited.
16879 *
16880 * Assigns the model group of model group definitions to the "term"
16881 * of the referencing particle.
16882 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16883 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016884 */
16885static void
16886xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016887 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016888 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016889{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016890 if ((item == NULL) ||
16891 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16892 (item->children == NULL) ||
16893 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16894 (item->children->children == NULL))
16895 return;
16896 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016897 /*
16898 * TODO: Not nice, but we will anchor cos-all-limited here.
16899 */
16900 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16901 (item->maxOccurs != 1)) {
16902 /*
16903 * SPEC (1.2) "the {term} property of a particle with
16904 * {max occurs}=1which is part of a pair which constitutes the
16905 * {content type} of a complex type definition."
16906 */
16907 xmlSchemaPCustomErr(ctxt,
16908 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16909 NULL, (xmlSchemaTypePtr) item, item->node,
16910 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16911 "group is its term", NULL);
16912 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016913}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016914
16915/**
16916 * xmlSchemaGetCircAttrGrRef:
16917 * @ctxtGr: the searched attribute group
16918 * @attr: the current attribute list to be processed
16919 *
16920 * This one is intended to be used by
16921 * xmlSchemaCheckSRCAttributeGroupCircular only.
16922 *
16923 * Returns the circular attribute grou reference, otherwise NULL.
16924 */
16925static xmlSchemaAttributeGroupPtr
16926xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16927 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016928{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016929 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16930 int marked;
16931 /*
16932 * We will search for an attribute group reference which
16933 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016934 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016935 while (attr != NULL) {
16936 marked = 0;
16937 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16938 gr = (xmlSchemaAttributeGroupPtr) attr;
16939 if (gr->refItem != NULL) {
16940 if (gr->refItem == ctxtGr)
16941 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016942 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016943 XML_SCHEMAS_ATTRGROUP_MARKED) {
16944 attr = attr->next;
16945 continue;
16946 } else {
16947 /*
16948 * Mark as visited to avoid infinite recursion on
16949 * circular references not yet examined.
16950 */
16951 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16952 marked = 1;
16953 }
16954 }
16955 if (gr->attributes != NULL)
16956 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16957 /*
16958 * Unmark the visited group's attributes.
16959 */
16960 if (marked)
16961 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16962 if (circ != NULL)
16963 return (circ);
16964 }
16965 attr = attr->next;
16966 }
16967 return (NULL);
16968}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016969
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016970/**
16971 * xmlSchemaCheckSRCAttributeGroupCircular:
16972 * attrGr: the attribute group definition
16973 * @ctxt: the parser context
16974 * @name: the name
16975 *
16976 * Checks for circular references of attribute groups.
16977 */
16978static void
16979xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016980 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016981 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016982{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016983 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016984 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016985 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016986 * 3 Circular group reference is disallowed outside <redefine>.
16987 * That is, unless this element information item's parent is
16988 * <redefine>, then among the [children], if any, there must
16989 * not be an <attributeGroup> with ref [attribute] which resolves
16990 * to the component corresponding to this <attributeGroup>. Indirect
16991 * circularity is also ruled out. That is, when QName resolution
16992 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16993 * any <attributeGroup>s with a ref [attribute] among the [children],
16994 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016995 * which resolves to the component corresponding to this <attributeGroup>.
16996 */
16997 /*
16998 * Only global components can be referenced.
16999 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017000 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017001 (attrGr->attributes == NULL))
17002 return;
17003 else {
17004 xmlSchemaAttributeGroupPtr circ;
17005
17006 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
17007 if (circ != NULL) {
17008 /*
17009 * TODO: Report the referenced attr group as QName.
17010 */
17011 xmlSchemaPCustomErr(ctxt,
17012 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17013 NULL, NULL, circ->node,
17014 "Circular reference to the attribute group '%s' "
17015 "defined", attrGr->name);
17016 /*
17017 * NOTE: We will cut the reference to avoid further
17018 * confusion of the processor.
17019 * BADSPEC: The spec should define how to process in this case.
17020 */
17021 circ->attributes = NULL;
17022 circ->refItem = NULL;
17023 }
17024 }
17025}
17026
17027/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017028 * xmlSchemaAttrGrpFixup:
17029 * @attrgrpDecl: the schema attribute definition
17030 * @ctxt: the schema parser context
17031 * @name: the attribute name
17032 *
17033 * Fixes finish doing the computations on the attributes definitions
17034 */
17035static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017036xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017037 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017038{
17039 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017040 name = attrgrp->name;
17041 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017042 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017043 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017044 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017045
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017046 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017047 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017048 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017049 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017050 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017051 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17052 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017053 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017054 return;
17055 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017056 attrgrp->refItem = ref;
17057 /*
17058 * Check for self reference!
17059 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017060 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017061 attrgrp->attributes = ref->attributes;
17062 attrgrp->attributeWildcard = ref->attributeWildcard;
17063 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017064}
17065
17066/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017067 * xmlSchemaAttrCheckValConstr:
17068 * @item: an schema attribute declaration/use
17069 * @ctxt: a schema parser context
17070 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017071 *
17072 *
17073 * Schema Component Constraint: Attribute Declaration Properties Correct
17074 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017075 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017076 *
17077 * Fixes finish doing the computations on the attributes definitions
17078 */
17079static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017080xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017081 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017082 const xmlChar * name ATTRIBUTE_UNUSED)
17083{
17084
17085 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017086 * 2 if there is a {value constraint}, the canonical lexical
17087 * representation of its value must be ·valid· with respect
17088 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017089 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017090 if (item->defValue != NULL) {
17091 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017092
17093 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017094 PERROR_INT("xmlSchemaCheckAttrValConstr",
17095 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017096 return;
17097 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017098 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17099 item->node, item->subtypes, item->defValue, &(item->defVal),
17100 1, 1, 0);
17101 if (ret != 0) {
17102 if (ret < 0) {
17103 PERROR_INT("xmlSchemaAttrCheckValConstr",
17104 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017105 return;
17106 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017107 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17108 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17109 ret, item->node, (xmlSchemaTypePtr) item,
17110 "The value of the value constraint is not valid", NULL, NULL);
17111 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017112 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017113 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017114}
17115
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017116static xmlSchemaElementPtr
17117xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17118 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017119{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017120 xmlSchemaElementPtr ret;
17121
17122 if (SUBST_GROUP_AFF(ancestor) == NULL)
17123 return (NULL);
17124 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17125 return (ancestor);
17126
17127 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17128 return (NULL);
17129 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17130 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17131 SUBST_GROUP_AFF(ancestor));
17132 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17133
17134 return (ret);
17135}
17136
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017137/**
17138 * xmlSchemaCheckElemPropsCorrect:
17139 * @ctxt: a schema parser context
17140 * @decl: the element declaration
17141 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017142 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017143 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017144 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017145 *
17146 * STATUS:
17147 * missing: (6)
17148 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017149static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017150xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17151 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017152{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017153 int ret = 0;
17154 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017155 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 * SPEC (1) "The values of the properties of an element declaration
17157 * must be as described in the property tableau in The Element
17158 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17159 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017160 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017161 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017162 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163
17164 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017165 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017166 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017167 * affiliation}, then {scope} must be global."
17168 */
17169 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17170 xmlSchemaPCustomErr(pctxt,
17171 XML_SCHEMAP_E_PROPS_CORRECT_3,
17172 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17173 "Only global element declarations can have a "
17174 "substitution group affiliation", NULL);
17175 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017176 }
17177 /*
17178 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17179 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017180 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017181 * property."
17182 */
17183 if (head == elemDecl)
17184 circ = head;
17185 else if (SUBST_GROUP_AFF(head) != NULL)
17186 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17187 else
17188 circ = NULL;
17189 if (circ != NULL) {
17190 xmlChar *strA = NULL, *strB = NULL;
17191
17192 xmlSchemaPCustomErrExt(pctxt,
17193 XML_SCHEMAP_E_PROPS_CORRECT_6,
17194 NULL, (xmlSchemaTypePtr) circ, circ->node,
17195 "The element declaration '%s' defines a circular "
17196 "substitution group to element declaration '%s'",
17197 xmlSchemaGetComponentQName(&strA, circ),
17198 xmlSchemaGetComponentQName(&strB, head),
17199 NULL);
17200 FREE_AND_NULL(strA)
17201 FREE_AND_NULL(strB)
17202 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17203 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017204 /*
17205 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017206 * the {type definition}
17207 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017208 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017209 * of the {substitution group exclusions} of the {substitution group
17210 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17211 * (if the {type definition} is complex) or as defined in
17212 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017213 * simple)."
17214 *
17215 * NOTE: {substitution group exclusions} means the values of the
17216 * attribute "final".
17217 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017218
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017219 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017220 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017222 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17223 set |= SUBSET_EXTENSION;
17224 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17225 set |= SUBSET_RESTRICTION;
17226
17227 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17228 ELEM_TYPE(head), set) != 0) {
17229 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17230
17231 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017232 xmlSchemaPCustomErrExt(pctxt,
17233 XML_SCHEMAP_E_PROPS_CORRECT_4,
17234 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017235 "The type definition '%s' was "
17236 "either rejected by the substitution group "
17237 "affiliation '%s', or not validly derived from its type "
17238 "definition '%s'",
17239 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017240 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017241 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017242 FREE_AND_NULL(strA)
17243 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017244 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017245 }
17246 }
17247 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017248 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017249 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017250 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017251 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017252 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017253 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017254 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017255 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017256 ((IS_SIMPLE_TYPE(typeDef) &&
17257 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017258 (IS_COMPLEX_TYPE(typeDef) &&
17259 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017260 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17261 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017262
17263 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17264 xmlSchemaPCustomErr(pctxt,
17265 XML_SCHEMAP_E_PROPS_CORRECT_5,
17266 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17267 "The type definition (or type definition's content type) is or "
17268 "is derived from ID; value constraints are not allowed in "
17269 "conjunction with such a type definition", NULL);
17270 } else if (elemDecl->value != NULL) {
17271 int vcret;
17272 xmlNodePtr node = NULL;
17273
17274 /*
17275 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17276 * representation of its value must be ·valid· with respect to the
17277 * {type definition} as defined in Element Default Valid (Immediate)
17278 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017279 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017280 if (typeDef == NULL) {
17281 xmlSchemaPErr(pctxt, elemDecl->node,
17282 XML_SCHEMAP_INTERNAL,
17283 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17284 "type is missing... skipping validation of "
17285 "the value constraint", NULL, NULL);
17286 return (-1);
17287 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017288 if (elemDecl->node != NULL) {
17289 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17290 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17291 BAD_CAST "fixed");
17292 else
17293 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17294 BAD_CAST "default");
17295 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017296 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17297 typeDef, elemDecl->value, &(elemDecl->defVal));
17298 if (vcret != 0) {
17299 if (vcret < 0) {
17300 PERROR_INT("xmlSchemaElemCheckValConstr",
17301 "failed to validate the value constraint of an "
17302 "element declaration");
17303 return (-1);
17304 }
17305 return (vcret);
17306 }
17307 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017308
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017309 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017310}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017311
17312/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017313 * xmlSchemaCheckElemSubstGroup:
17314 * @ctxt: a schema parser context
17315 * @decl: the element declaration
17316 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017317 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017318 * Schema Component Constraint:
17319 * Substitution Group (cos-equiv-class)
17320 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017321 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017322 * a list will be built for each subst. group head, holding all direct
17323 * referents to this head.
17324 * NOTE that this function needs:
17325 * 1. circular subst. groups to be checked beforehand
17326 * 2. the declaration's type to be derived from the head's type
17327 *
17328 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017329 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017330 */
17331static void
17332xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17333 xmlSchemaElementPtr elemDecl)
17334{
17335 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17336 /* SPEC (1) "Its {abstract} is false." */
17337 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17338 return;
17339 {
17340 xmlSchemaElementPtr head;
17341 xmlSchemaTypePtr headType, type;
17342 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017343 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017344 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17345 * {disallowed substitutions} as the blocking constraint, as defined in
17346 * Substitution Group OK (Transitive) (§3.3.6)."
17347 */
17348 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17349 head = SUBST_GROUP_AFF(head)) {
17350 set = 0;
17351 methSet = 0;
17352 /*
17353 * The blocking constraints.
17354 */
17355 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17356 continue;
17357 headType = head->subtypes;
17358 type = elemDecl->subtypes;
17359 if (headType == type)
17360 goto add_member;
17361 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17362 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17363 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17364 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17365 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017366 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017367 * "The set of all {derivation method}s involved in the
17368 * derivation of D's {type definition} from C's {type definition}
17369 * does not intersect with the union of the blocking constraint,
17370 * C's {prohibited substitutions} (if C is complex, otherwise the
17371 * empty set) and the {prohibited substitutions} (respectively the
17372 * empty set) of any intermediate {type definition}s in the
17373 * derivation of D's {type definition} from C's {type definition}."
17374 */
17375 /*
17376 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17377 * subst.head axis, the methSet does not need to be computed for
17378 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017379 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017380 /*
17381 * The set of all {derivation method}s involved in the derivation
17382 */
17383 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017384 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017385 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17386 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17387 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017388
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017389 if ((type->flags &
17390 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17391 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17392 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17393
17394 type = type->baseType;
17395 }
17396 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017397 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017398 * the head's type.
17399 */
17400 type = elemDecl->subtypes->baseType;
17401 while (type != NULL) {
17402 if (IS_COMPLEX_TYPE(type)) {
17403 if ((type->flags &
17404 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17405 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17406 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17407 if ((type->flags &
17408 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17409 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17410 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17411 } else
17412 break;
17413 if (type == headType)
17414 break;
17415 type = type->baseType;
17416 }
17417 if ((set != 0) &&
17418 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17419 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17420 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17421 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17422 continue;
17423 }
17424add_member:
17425 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17426 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17427 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17428 }
17429 }
17430}
17431
17432/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017433 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017434 * @item: an schema element declaration/particle
17435 * @ctxt: a schema parser context
17436 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017437 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017438 * Validates the value constraints of an element declaration.
17439 *
17440 * Fixes finish doing the computations on the element declarations.
17441 */
17442static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017443xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017444 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017445 const xmlChar * name ATTRIBUTE_UNUSED)
17446{
17447 if (elemDecl == NULL)
17448 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017449 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17450 return;
17451 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017452 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17453 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017454}
17455
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017456/**
17457 * xmlSchemaMiscRefFixup:
17458 * @item: an schema component
17459 * @ctxt: a schema parser context
17460 * @name: the internal name of the component
17461 *
17462 * Resolves references of misc. schema components.
17463 */
17464static void
17465xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017466 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017467 const xmlChar * name ATTRIBUTE_UNUSED)
17468{
17469 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017470 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017471 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17472 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17473 xmlSchemaTreeItemPtr refItem;
17474 /*
17475 * Resolve the reference.
17476 */
17477 item->children = NULL;
17478 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17479 ref->itemType, ref->name, ref->targetNamespace);
17480 if (refItem == NULL) {
17481 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017482 NULL, GET_NODE(item), "ref", ref->name,
17483 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017484 } else {
17485 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17486 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017487 * NOTE that we will assign the model group definition
17488 * itself to the "term" of the particle. This will ease
17489 * the check for circular model group definitions. After
17490 * that the "term" will be assigned the model group of the
17491 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017492 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017493 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017494 } else
17495 item->children = refItem;
17496 }
17497 }
17498 }
17499}
17500
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017501static int
17502xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17503 xmlSchemaValPtr y)
17504{
17505 xmlSchemaTypePtr tx, ty, ptx, pty;
17506 int ret;
17507
17508 while (x != NULL) {
17509 /* Same types. */
17510 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17511 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17512 ptx = xmlSchemaGetPrimitiveType(tx);
17513 pty = xmlSchemaGetPrimitiveType(ty);
17514 /*
17515 * (1) if a datatype T' is ·derived· by ·restriction· from an
17516 * atomic datatype T then the ·value space· of T' is a subset of
17517 * the ·value space· of T. */
17518 /*
17519 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17520 * from a common atomic ancestor T then the ·value space·s of T'
17521 * and T'' may overlap.
17522 */
17523 if (ptx != pty)
17524 return(0);
17525 /*
17526 * We assume computed values to be normalized, so do a fast
17527 * string comparison for string based types.
17528 */
17529 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17530 IS_ANY_SIMPLE_TYPE(ptx)) {
17531 if (! xmlStrEqual(
17532 xmlSchemaValueGetAsString(x),
17533 xmlSchemaValueGetAsString(y)))
17534 return (0);
17535 } else {
17536 ret = xmlSchemaCompareValuesWhtsp(
17537 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17538 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17539 if (ret == -2)
17540 return(-1);
17541 if (ret != 0)
17542 return(0);
17543 }
17544 /*
17545 * Lists.
17546 */
17547 x = xmlSchemaValueGetNext(x);
17548 if (x != NULL) {
17549 y = xmlSchemaValueGetNext(y);
17550 if (y == NULL)
17551 return (0);
17552 } else if (xmlSchemaValueGetNext(y) != NULL)
17553 return (0);
17554 else
17555 return (1);
17556 }
17557 return (0);
17558}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017559
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017560/**
17561 * xmlSchemaAttrFixup:
17562 * @item: an schema attribute declaration/use.
17563 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017564 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017565 *
17566 * Fixes finish doing the computations on attribute declarations/uses.
17567 */
17568static void
17569xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017570 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017571 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017572{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017574 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017575 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017576 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017577 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017578 * The simple type definition corresponding to the <simpleType> element
17579 * information item in the [children], if present, otherwise the simple
17580 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017581 * [attribute], if present, otherwise the ·simple ur-type definition·.
17582 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017583 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017584 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017585 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17586 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017587 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017588 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017589 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017590
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017591 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17592 item->typeNs);
17593 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017594 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017595 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017596 (xmlSchemaTypePtr) item, item->node,
17597 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017598 XML_SCHEMA_TYPE_SIMPLE, NULL);
17599 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017600 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017601
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017602 } else if (item->ref != NULL) {
17603 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017604
Daniel Veillardc0826a72004-08-10 14:17:33 +000017605 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017606 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017607 * attribute declaration.
17608 */
17609 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017610 * TODO: Evaluate, what errors could occur if the declaration is not
17611 * found. It might be possible that the "typefixup" might crash if
17612 * no ref declaration was found.
17613 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017614 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017615 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017616 xmlSchemaPResCompAttrErr(ctxt,
17617 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017618 (xmlSchemaTypePtr) item, item->node,
17619 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017620 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017621 return;
17622 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017623 item->refDecl = decl;
17624 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017625 item->subtypes = decl->subtypes;
17626 /*
17627 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017628 * au-props-correct.2: If the {attribute declaration} has a fixed
17629 * {value constraint}, then if the attribute use itself has a
17630 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017631 * that of the {attribute declaration}'s {value constraint}.
17632 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017633 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017634 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017635 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017636 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17638 NULL, NULL, item->node,
17639 "The attribute declaration has a 'fixed' value constraint "
17640 ", thus it must be 'fixed' in attribute use as well",
17641 NULL);
17642 } else {
17643 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17644 xmlSchemaPCustomErr(ctxt,
17645 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17646 NULL, NULL, item->node,
17647 "The 'fixed' value constraint of the attribute use "
17648 "must match the attribute declaration's value "
17649 "constraint '%s'",
17650 decl->defValue);
17651 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017652 }
17653 /*
17654 * FUTURE: One should change the values of the attr. use
17655 * if ever validation should be attempted even if the
17656 * schema itself was not fully valid.
17657 */
17658 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017659 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017660 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17661 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017662}
17663
17664/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017665 * xmlSchemaResolveIDCKeyRef:
17666 * @idc: the identity-constraint definition
17667 * @ctxt: the schema parser context
17668 * @name: the attribute name
17669 *
17670 * Resolve keyRef references to key/unique IDCs.
17671 */
17672static void
17673xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017674 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017675 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017676{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017677 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17678 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017679 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017680 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017681 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017682 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017683 idc->ref->targetNamespace);
17684 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017685 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017686 * TODO: It is actually not an error to fail to resolve.
17687 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017688 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017689 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017690 (xmlSchemaTypePtr) idc, idc->node,
17691 "refer", idc->ref->name,
17692 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017693 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17694 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017695 } else {
17696 if (idc->nbFields !=
17697 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17698 xmlChar *str = NULL;
17699 xmlSchemaIDCPtr refer;
17700
17701 refer = (xmlSchemaIDCPtr) idc->ref->item;
17702 /*
17703 * SPEC c-props-correct(2)
17704 * "If the {identity-constraint category} is keyref,
17705 * the cardinality of the {fields} must equal that of
17706 * the {fields} of the {referenced key}.
17707 */
17708 xmlSchemaPCustomErr(pctxt,
17709 XML_SCHEMAP_C_PROPS_CORRECT,
17710 NULL, (xmlSchemaTypePtr) idc, idc->node,
17711 "The cardinality of the keyref differs from the "
17712 "cardinality of the referenced key '%s'",
17713 xmlSchemaFormatQName(&str, refer->targetNamespace,
17714 refer->name)
17715 );
17716 FREE_AND_NULL(str)
17717 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017718 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017719 }
17720}
17721
17722/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017723 * xmlSchemaParse:
17724 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017725 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017726 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017727 * XML Shema struture which can be used to validate instances.
17728 * *WARNING* this interface is highly subject to change
17729 *
17730 * Returns the internal XML Schema structure built from the resource or
17731 * NULL in case of error
17732 */
17733xmlSchemaPtr
17734xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17735{
17736 xmlSchemaPtr ret = NULL;
17737 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017738 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017739 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017740
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017741 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017742 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017743 * the API; i.e. not automatically by the validated instance document.
17744 */
17745
Daniel Veillard4255d502002-04-16 15:50:10 +000017746 xmlSchemaInitTypes();
17747
Daniel Veillard6045c902002-10-09 21:13:59 +000017748 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017749 return (NULL);
17750
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017751 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017752 ctxt->counter = 0;
17753 ctxt->container = NULL;
17754
17755 /*
17756 * First step is to parse the input document into an DOM/Infoset
17757 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017758 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017759 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017760 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017761 if (doc == NULL) {
17762 xmlSchemaPErr(ctxt, NULL,
17763 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017764 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017765 ctxt->URL, NULL);
17766 return (NULL);
17767 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017768 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017769 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17770 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017771 if (doc == NULL) {
17772 xmlSchemaPErr(ctxt, NULL,
17773 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017774 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017775 NULL, NULL);
17776 return (NULL);
17777 }
17778 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017779 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017780 } else if (ctxt->doc != NULL) {
17781 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017782 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017783 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017784 xmlSchemaPErr(ctxt, NULL,
17785 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017786 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017787 NULL, NULL);
17788 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017789 }
17790
17791 /*
17792 * Then extract the root and Schema parse it
17793 */
17794 root = xmlDocGetRootElement(doc);
17795 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017796 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17797 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017798 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017799 if (!preserve) {
17800 xmlFreeDoc(doc);
17801 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017802 return (NULL);
17803 }
17804
17805 /*
17806 * Remove all the blank text nodes
17807 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017808 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017809
17810 /*
17811 * Then do the parsing for good
17812 */
17813 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017814 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017815 if (!preserve) {
17816 xmlFreeDoc(doc);
17817 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017818 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017819 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017820 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017821 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017822 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017823 ctxt->ctxtType = NULL;
17824 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017825
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017826 /*
17827 * Resolve base types of simple/complex types.
17828 */
17829 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017830
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017831 if (ctxt->nberrors != 0)
17832 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017833
17834 if (ret->volatiles != NULL) {
17835 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17836 int i;
17837 xmlSchemaTreeItemPtr item;
17838
17839 for (i = 0; i < list->nbItems; i++) {
17840 item = (xmlSchemaTreeItemPtr) list->items[i];
17841 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17842 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017843 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017844 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017845 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017846 * Then fixup all attributes declarations
17847 */
17848 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017849 /*
17850 * Then fixup all attributes group declarations
17851 */
17852 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17853 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017854 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017855 * Resolve identity-constraint keyRefs.
17856 */
17857 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017858 /*
17859 * Check type defnitions for circular references.
17860 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017861 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017862 xmlSchemaCheckTypeDefCircular, ctxt);
17863 /*
17864 * Check model groups defnitions for circular references.
17865 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017866 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017867 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017868 /*
17869 * Set the "term" of particles pointing to model group definitions
17870 * to the contained model group.
17871 */
17872 if (ret->volatiles != NULL) {
17873 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17874 int i;
17875 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017876
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017877 for (i = 0; i < list->nbItems; i++) {
17878 item = (xmlSchemaParticlePtr) list->items[i];
17879 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17880 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17881 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017882 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017883 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017884 * Check attribute groups for circular references.
17885 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017886 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17887 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017888 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017889 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017890 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017891 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017892 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017893 /*
17894 * We will stop here if the schema was not valid to avoid internal errors
17895 * on missing sub-components. This is not conforming to the spec, since it
17896 * allows missing components, but it might make further processing crash.
17897 * So see it as a very strict handling, which might be made more lax in the
17898 * future.
17899 */
17900 if (ctxt->nberrors != 0)
17901 goto exit;
17902 /*
17903 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017904 */
17905 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017906 /*
17907 * Validate the value constraint of attribute declarations/uses.
17908 */
17909 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017910 /*
17911 * Validate the value constraint of element declarations.
17912 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017913 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017914
17915 if (ctxt->nberrors != 0)
17916 goto exit;
17917
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017918 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017919 * TODO: cos-element-consistent, cos-all-limited
17920 *
17921 * Then build the content model for all complex types
17922 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017923 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017924 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017925
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017926exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017927 if (ctxt->nberrors != 0) {
17928 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017929 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017930 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017931 return (ret);
17932}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017933
Daniel Veillard4255d502002-04-16 15:50:10 +000017934/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017935 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017936 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017937 * @err: the error callback
17938 * @warn: the warning callback
17939 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017940 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017941 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017942 */
17943void
17944xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017945 xmlSchemaValidityErrorFunc err,
17946 xmlSchemaValidityWarningFunc warn, void *ctx)
17947{
Daniel Veillard4255d502002-04-16 15:50:10 +000017948 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017949 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017950 ctxt->error = err;
17951 ctxt->warning = warn;
17952 ctxt->userData = ctx;
17953}
17954
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017955/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017956 * xmlSchemaGetParserErrors:
17957 * @ctxt: a XMl-Schema parser context
17958 * @err: the error callback result
17959 * @warn: the warning callback result
17960 * @ctx: contextual data for the callbacks result
17961 *
17962 * Get the callback information used to handle errors for a parser context
17963 *
17964 * Returns -1 in case of failure, 0 otherwise
17965 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017966int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017967xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17968 xmlSchemaValidityErrorFunc * err,
17969 xmlSchemaValidityWarningFunc * warn, void **ctx)
17970{
17971 if (ctxt == NULL)
17972 return(-1);
17973 if (err != NULL)
17974 *err = ctxt->error;
17975 if (warn != NULL)
17976 *warn = ctxt->warning;
17977 if (ctx != NULL)
17978 *ctx = ctxt->userData;
17979 return(0);
17980}
17981
17982/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017983 * xmlSchemaFacetTypeToString:
17984 * @type: the facet type
17985 *
17986 * Convert the xmlSchemaTypeType to a char string.
17987 *
17988 * Returns the char string representation of the facet type if the
17989 * type is a facet and an "Internal Error" string otherwise.
17990 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017991static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017992xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17993{
17994 switch (type) {
17995 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017996 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017997 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017998 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017999 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018000 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018001 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018002 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018003 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018004 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018005 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018006 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018007 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018008 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018009 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018010 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018011 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018012 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018013 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018014 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018015 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018016 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018017 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018018 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018019 default:
18020 break;
18021 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018022 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018023}
18024
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018025static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000018026xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
18027{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018028 /*
18029 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000018030 * from xsd:string.
18031 */
18032 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018033 /*
18034 * Note that we assume a whitespace of preserve for anySimpleType.
18035 */
18036 if ((type->builtInType == XML_SCHEMAS_STRING) ||
18037 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18038 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000018039 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018040 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018041 else {
18042 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018043 * For all ·atomic· datatypes other than string (and types ·derived·
18044 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018045 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018046 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018048 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018049 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018050 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018051 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018052 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018053 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018054 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18055 } else if (VARIETY_UNION(type)) {
18056 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18057 } else if (VARIETY_ATOMIC(type)) {
18058 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18059 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18060 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18061 return (XML_SCHEMA_WHITESPACE_REPLACE);
18062 else
18063 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018064 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018065 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018066}
18067
Daniel Veillard4255d502002-04-16 15:50:10 +000018068/************************************************************************
18069 * *
18070 * Simple type validation *
18071 * *
18072 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018073
Daniel Veillard4255d502002-04-16 15:50:10 +000018074
18075/************************************************************************
18076 * *
18077 * DOM Validation code *
18078 * *
18079 ************************************************************************/
18080
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018081static void
18082xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18083{
18084 int i, nbItems;
18085 xmlSchemaTypePtr item, *items;
18086
18087
18088 /*
18089 * During the Assemble of the schema ctxt->curItems has
18090 * been filled with the relevant new items. Fix those up.
18091 */
18092 nbItems = ctxt->assemble->nbItems;
18093 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018094
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018095 for (i = 0; i < nbItems; i++) {
18096 item = items[i];
18097 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018098 case XML_SCHEMA_TYPE_COMPLEX:
18099 case XML_SCHEMA_TYPE_SIMPLE:
18100 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18101 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018102 case XML_SCHEMA_TYPE_ATTRIBUTE:
18103 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18104 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018105 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018106 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018107 ctxt, NULL);
18108 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018109 case XML_SCHEMA_TYPE_PARTICLE:
18110 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018111 break;
18112 case XML_SCHEMA_TYPE_IDC_KEY:
18113 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18114 case XML_SCHEMA_TYPE_IDC_KEYREF:
18115 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18116 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018117 default:
18118 break;
18119 }
18120 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018121 if (ctxt->nberrors != 0)
18122 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018123 /*
18124 * Circularity checks.
18125 */
18126 for (i = 0; i < nbItems; i++) {
18127 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018128 switch (item->type) {
18129 case XML_SCHEMA_TYPE_COMPLEX:
18130 case XML_SCHEMA_TYPE_SIMPLE:
18131 xmlSchemaCheckTypeDefCircular(
18132 (xmlSchemaTypePtr) item, ctxt, NULL);
18133 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018135 xmlSchemaCheckGroupDefCircular(
18136 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018137 break;
18138 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18139 xmlSchemaCheckAttributeGroupCircular(
18140 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18141 break;
18142 default:
18143 break;
18144 }
18145 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018146 if (ctxt->nberrors != 0)
18147 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018148 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018149 * Set the "term" of particles pointing to model group definitions
18150 * to the contained model group.
18151 */
18152 for (i = 0; i < nbItems; i++) {
18153 item = items[i];
18154 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18155 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018156 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018157 XML_SCHEMA_TYPE_GROUP)) {
18158 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18159 ctxt, NULL);
18160 }
18161 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018162 if (ctxt->nberrors != 0)
18163 return;
18164 for (i = 0; i < nbItems; i++) {
18165 item = items[i];
18166 switch (item->type) {
18167 case XML_SCHEMA_TYPE_ELEMENT:
18168 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18169 NULL, NULL, NULL);
18170 break;
18171 default:
18172 break;
18173 }
18174 }
18175 if (ctxt->nberrors != 0)
18176 return;
18177
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018178 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018179 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018180 */
18181 for (i = 0; i < nbItems; i++) {
18182 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018183 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018184 case XML_SCHEMA_TYPE_SIMPLE:
18185 case XML_SCHEMA_TYPE_COMPLEX:
18186 xmlSchemaTypeFixup(item, ctxt, NULL);
18187 break;
18188 default:
18189 break;
18190 }
18191 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018192 if (ctxt->nberrors != 0)
18193 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018194 /*
18195 * Validate value contraint values.
18196 */
18197 for (i = 0; i < nbItems; i++) {
18198 item = items[i];
18199 switch (item->type) {
18200 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018201 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18202 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018203 break;
18204 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018205 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018206 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018207 break;
18208 default:
18209 break;
18210 }
18211 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018212 if (ctxt->nberrors != 0)
18213 return;
18214 /*
18215 * Build the content model for complex types.
18216 */
18217 for (i = 0; i < nbItems; i++) {
18218 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018219 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018220 case XML_SCHEMA_TYPE_COMPLEX:
18221 xmlSchemaBuildContentModel(item, ctxt, NULL);
18222 break;
18223 default:
18224 break;
18225 }
18226 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018227}
18228
18229/**
18230 * xmlSchemaAssembleByLocation:
18231 * @pctxt: a schema parser context
18232 * @vctxt: a schema validation context
18233 * @schema: the existing schema
18234 * @node: the node that fired the assembling
18235 * @nsName: the namespace name of the new schema
18236 * @location: the location of the schema
18237 *
18238 * Expands an existing schema by an additional schema.
18239 *
18240 * Returns 0 if the new schema is correct, a positive error code
18241 * number otherwise and -1 in case of an internal or API error.
18242 */
18243static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018244xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018245 xmlSchemaPtr schema,
18246 xmlNodePtr node,
18247 const xmlChar *nsName,
18248 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018250 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018251 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018252 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018253 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018254 xmlSchemaParserCtxtPtr pctxt;
18255
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018256 /*
18257 * This should be used:
18258 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018259 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018260 * 3. if requested via the API
18261 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018262 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018263 return (-1);
18264 /*
18265 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018266 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018267 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018268 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18269 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018270 pctxt = vctxt->pctxt;
18271 /*
18272 * Set the counter to produce unique names for anonymous items.
18273 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018274 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018275 /*
18276 * Acquire the schema document.
18277 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018278 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18279 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018280 if (ret != 0) {
18281 if (doc != NULL)
18282 xmlFreeDoc(doc);
18283 } else if (doc != NULL) {
18284 docElem = xmlDocGetRootElement(doc);
18285 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018286 * Create new assemble info.
18287 */
18288 if (pctxt->assemble == NULL) {
18289 pctxt->assemble = xmlSchemaNewAssemble();
18290 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018291 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018292 "Memory error: xmlSchemaAssembleByLocation, "
18293 "allocating assemble info", NULL);
18294 xmlFreeDoc(doc);
18295 return (-1);
18296 }
18297 }
18298 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018299 * Save and reset the context & schema.
18300 */
18301 oldflags = schema->flags;
18302 oldtns = schema->targetNamespace;
18303 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018304 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018305
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018306 xmlSchemaClearSchemaDefaults(schema);
18307 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018308 if ((targetNs != NULL) &&
18309 xmlStrEqual(targetNs, xmlSchemaNs)) {
18310 /*
18311 * We are parsing the schema for schema!
18312 */
18313 vctxt->pctxt->isS4S = 1;
18314 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018315 /* schema->nbCurItems = 0; */
18316 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018317 pctxt->ctxtType = NULL;
18318 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018319
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018320 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18321 if (pctxt->nberrors != 0) {
18322 vctxt->nberrors += pctxt->nberrors;
18323 goto finally;
18324 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018325 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018326 if (pctxt->nberrors != 0) {
18327 vctxt->nberrors += pctxt->nberrors;
18328 goto finally;
18329 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018330 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018331 if (pctxt->nberrors != 0)
18332 vctxt->nberrors += pctxt->nberrors;
18333finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018334 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018335 * Set the counter of items.
18336 */
18337 schema->counter = pctxt->counter;
18338 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018339 * Free the list of assembled components.
18340 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018341 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018342 /*
18343 * Restore the context & schema.
18344 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018345 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018346 schema->flags = oldflags;
18347 schema->targetNamespace = oldtns;
18348 schema->doc = olddoc;
18349 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018350 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018351 return (ret);
18352}
18353
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018354static xmlSchemaAttrInfoPtr
18355xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18356 int metaType)
18357{
18358 if (vctxt->nbAttrInfos == 0)
18359 return (NULL);
18360 {
18361 int i;
18362 xmlSchemaAttrInfoPtr iattr;
18363
18364 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18365 iattr = vctxt->attrInfos[i];
18366 if (iattr->metaType == metaType)
18367 return (iattr);
18368 }
18369
18370 }
18371 return (NULL);
18372}
18373
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018374/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018375 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018376 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018377 *
18378 * Expands an existing schema by an additional schema using
18379 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18380 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18381 * must be set to 1.
18382 *
18383 * Returns 0 if the new schema is correct, a positive error code
18384 * number otherwise and -1 in case of an internal or API error.
18385 */
18386static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018387xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018388{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018389 const xmlChar *cur, *end;
18390 const xmlChar *nsname = NULL, *location;
18391 int count = 0;
18392 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018393 xmlSchemaAttrInfoPtr iattr;
18394
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018395 /*
18396 * Parse the value; we will assume an even number of values
18397 * to be given (this is how Xerces and XSV work).
18398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018399 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18400 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18401 if (iattr == NULL)
18402 xmlSchemaGetMetaAttrInfo(vctxt,
18403 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18404 if (iattr == NULL)
18405 return (0);
18406 cur = iattr->value;
18407 do {
18408 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018409 /*
18410 * Get the namespace name.
18411 */
18412 while (IS_BLANK_CH(*cur))
18413 cur++;
18414 end = cur;
18415 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18416 end++;
18417 if (end == cur)
18418 break;
18419 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018420 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018421 cur = end;
18422 }
18423 /*
18424 * Get the URI.
18425 */
18426 while (IS_BLANK_CH(*cur))
18427 cur++;
18428 end = cur;
18429 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18430 end++;
18431 if (end == cur)
18432 break;
18433 count++;
18434 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018435 cur = end;
18436 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18437 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018438 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018439 VERROR_INT("xmlSchemaAssembleByXSI",
18440 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018441 return (-1);
18442 }
18443 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018444 return (ret);
18445}
18446
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018447#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018448
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018449static const xmlChar *
18450xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18451 const xmlChar *prefix)
18452{
18453 if (vctxt->sax != NULL) {
18454 int i, j;
18455 xmlSchemaNodeInfoPtr inode;
18456
18457 for (i = vctxt->depth; i >= 0; i--) {
18458 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18459 inode = vctxt->elemInfos[i];
18460 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18461 if (((prefix == NULL) &&
18462 (inode->nsBindings[j] == NULL)) ||
18463 ((prefix != NULL) && xmlStrEqual(prefix,
18464 inode->nsBindings[j]))) {
18465
18466 /*
18467 * Note that the namespace bindings are already
18468 * in a string dict.
18469 */
18470 return (inode->nsBindings[j+1]);
18471 }
18472 }
18473 }
18474 }
18475 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018476#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018477 } else if (vctxt->reader != NULL) {
18478 xmlChar *nsName;
18479
18480 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18481 if (nsName != NULL) {
18482 const xmlChar *ret;
18483
18484 VAL_CREATE_DICT;
18485 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18486 xmlFree(nsName);
18487 return (ret);
18488 } else
18489 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018490#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018491 } else {
18492 xmlNsPtr ns;
18493
18494 if ((vctxt->inode->node == NULL) ||
18495 (vctxt->inode->node->doc == NULL)) {
18496 VERROR_INT("xmlSchemaLookupNamespace",
18497 "no node or node's doc avaliable");
18498 return (NULL);
18499 }
18500 ns = xmlSearchNs(vctxt->inode->node->doc,
18501 vctxt->inode->node, prefix);
18502 if (ns != NULL)
18503 return (ns->href);
18504 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018505 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018506}
18507
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018508/*
18509* This one works on the schema of the validation context.
18510*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018511static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018512xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18513 xmlSchemaPtr schema,
18514 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018515 const xmlChar *value,
18516 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018517 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018518{
18519 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520
18521 if (vctxt && (vctxt->schema == NULL)) {
18522 VERROR_INT("xmlSchemaValidateNotation",
18523 "a schema is needed on the validation context");
18524 return (-1);
18525 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018526 ret = xmlValidateQName(value, 1);
18527 if (ret != 0)
18528 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018529 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018530 xmlChar *localName = NULL;
18531 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018532
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018533 localName = xmlSplitQName2(value, &prefix);
18534 if (prefix != NULL) {
18535 const xmlChar *nsName = NULL;
18536
18537 if (vctxt != NULL)
18538 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18539 else if (node != NULL) {
18540 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18541 if (ns != NULL)
18542 nsName = ns->href;
18543 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018544 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018545 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018546 return (1);
18547 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018548 if (nsName == NULL) {
18549 xmlFree(prefix);
18550 xmlFree(localName);
18551 return (1);
18552 }
18553 if (xmlHashLookup2(schema->notaDecl, localName,
18554 nsName) != NULL) {
18555 if (valNeeded && (val != NULL)) {
18556 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18557 BAD_CAST xmlStrdup(nsName));
18558 if (*val == NULL)
18559 ret = -1;
18560 }
18561 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018562 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018563 xmlFree(prefix);
18564 xmlFree(localName);
18565 } else {
18566 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18567 if (valNeeded && (val != NULL)) {
18568 (*val) = xmlSchemaNewNOTATIONValue(
18569 BAD_CAST xmlStrdup(value), NULL);
18570 if (*val == NULL)
18571 ret = -1;
18572 }
18573 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018574 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018575 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018577 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018578}
18579
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018580/************************************************************************
18581 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018582 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018583 * *
18584 ************************************************************************/
18585
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018586/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018587 * xmlSchemaAugmentIDC:
18588 * @idcDef: the IDC definition
18589 *
18590 * Creates an augmented IDC definition item.
18591 *
18592 * Returns the item, or NULL on internal errors.
18593 */
18594static void
18595xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18596 xmlSchemaValidCtxtPtr vctxt)
18597{
18598 xmlSchemaIDCAugPtr aidc;
18599
18600 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18601 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018602 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018603 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18604 NULL);
18605 return;
18606 }
18607 aidc->bubbleDepth = -1;
18608 aidc->def = idcDef;
18609 aidc->next = NULL;
18610 if (vctxt->aidcs == NULL)
18611 vctxt->aidcs = aidc;
18612 else {
18613 aidc->next = vctxt->aidcs;
18614 vctxt->aidcs = aidc;
18615 }
18616}
18617
18618/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018619 * xmlSchemaIDCNewBinding:
18620 * @idcDef: the IDC definition of this binding
18621 *
18622 * Creates a new IDC binding.
18623 *
18624 * Returns the new binding in case of succeeded, NULL on internal errors.
18625 */
18626static xmlSchemaPSVIIDCBindingPtr
18627xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18628{
18629 xmlSchemaPSVIIDCBindingPtr ret;
18630
18631 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18632 sizeof(xmlSchemaPSVIIDCBinding));
18633 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018634 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018635 "allocating a PSVI IDC binding item", NULL);
18636 return (NULL);
18637 }
18638 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18639 ret->definition = idcDef;
18640 return (ret);
18641}
18642
18643/**
18644 * xmlSchemaIDCStoreNodeTableItem:
18645 * @vctxt: the WXS validation context
18646 * @item: the IDC node table item
18647 *
18648 * The validation context is used to store an IDC node table items.
18649 * They are stored to avoid copying them if IDC node-tables are merged
18650 * with corresponding parent IDC node-tables (bubbling).
18651 *
18652 * Returns 0 if succeeded, -1 on internal errors.
18653 */
18654static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018655xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018656 xmlSchemaPSVIIDCNodePtr item)
18657{
18658 /*
18659 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018660 */
18661 if (vctxt->idcNodes == NULL) {
18662 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018663 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18664 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018665 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018666 "allocating the IDC node table item list", NULL);
18667 return (-1);
18668 }
18669 vctxt->sizeIdcNodes = 20;
18670 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18671 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18673 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018674 sizeof(xmlSchemaPSVIIDCNodePtr));
18675 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018676 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018677 "re-allocating the IDC node table item list", NULL);
18678 return (-1);
18679 }
18680 }
18681 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018682
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018683 return (0);
18684}
18685
18686/**
18687 * xmlSchemaIDCStoreKey:
18688 * @vctxt: the WXS validation context
18689 * @item: the IDC key
18690 *
18691 * The validation context is used to store an IDC key.
18692 *
18693 * Returns 0 if succeeded, -1 on internal errors.
18694 */
18695static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018696xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018697 xmlSchemaPSVIIDCKeyPtr key)
18698{
18699 /*
18700 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018701 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018702 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018703 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018704 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18705 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018706 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018707 "allocating the IDC key storage list", NULL);
18708 return (-1);
18709 }
18710 vctxt->sizeIdcKeys = 40;
18711 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18712 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018713 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18714 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018715 sizeof(xmlSchemaPSVIIDCKeyPtr));
18716 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018717 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018718 "re-allocating the IDC key storage list", NULL);
18719 return (-1);
18720 }
18721 }
18722 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018723
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018724 return (0);
18725}
18726
18727/**
18728 * xmlSchemaIDCAppendNodeTableItem:
18729 * @bind: the IDC binding
18730 * @ntItem: the node-table item
18731 *
18732 * Appends the IDC node-table item to the binding.
18733 *
18734 * Returns 0 on success and -1 on internal errors.
18735 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018736static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018737xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18738 xmlSchemaPSVIIDCNodePtr ntItem)
18739{
18740 if (bind->nodeTable == NULL) {
18741 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018742 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018743 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18744 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018745 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018746 "allocating an array of IDC node-table items", NULL);
18747 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018748 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018749 } else if (bind->sizeNodes <= bind->nbNodes) {
18750 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018751 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18752 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018753 sizeof(xmlSchemaPSVIIDCNodePtr));
18754 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018755 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018756 "re-allocating an array of IDC node-table items", NULL);
18757 return(-1);
18758 }
18759 }
18760 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018761 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018762}
18763
18764/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018765 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018766 * @vctxt: the WXS validation context
18767 * @matcher: the IDC matcher
18768 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018769 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018770 * of the given matcher. If none found, a new one is created
18771 * and added to the IDC table.
18772 *
18773 * Returns an IDC binding or NULL on internal errors.
18774 */
18775static xmlSchemaPSVIIDCBindingPtr
18776xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18777 xmlSchemaIDCMatcherPtr matcher)
18778{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018779 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018780
18781 info = vctxt->elemInfos[matcher->depth];
18782
18783 if (info->idcTable == NULL) {
18784 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18785 if (info->idcTable == NULL)
18786 return (NULL);
18787 return(info->idcTable);
18788 } else {
18789 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018790
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018791 bind = info->idcTable;
18792 do {
18793 if (bind->definition == matcher->aidc->def)
18794 return(bind);
18795 if (bind->next == NULL) {
18796 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18797 if (bind->next == NULL)
18798 return (NULL);
18799 return(bind->next);
18800 }
18801 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018802 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018803 }
18804 return (NULL);
18805}
18806
18807/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018808 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018809 * @key: the IDC key
18810 *
18811 * Frees an IDC key together with its compiled value.
18812 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018813static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018814xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18815{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018816 if (key->val != NULL)
18817 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018818 xmlFree(key);
18819}
18820
18821/**
18822 * xmlSchemaIDCFreeBinding:
18823 *
18824 * Frees an IDC binding. Note that the node table-items
18825 * are not freed.
18826 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018827static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018828xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18829{
18830 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018831 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18832 int i;
18833 /*
18834 * Node-table items for keyrefs are not stored globally
18835 * to the validation context, since they are not bubbled.
18836 * We need to free them here.
18837 */
18838 for (i = 0; i < bind->nbNodes; i++) {
18839 xmlFree(bind->nodeTable[i]->keys);
18840 xmlFree(bind->nodeTable[i]);
18841 }
18842 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018843 xmlFree(bind->nodeTable);
18844 }
18845 xmlFree(bind);
18846}
18847
18848/**
18849 * xmlSchemaIDCFreeIDCTable:
18850 * @bind: the first IDC binding in the list
18851 *
18852 * Frees an IDC table, i.e. all the IDC bindings in the list.
18853 */
18854static void
18855xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18856{
18857 xmlSchemaPSVIIDCBindingPtr prev;
18858
18859 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018860 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018861 bind = bind->next;
18862 xmlSchemaIDCFreeBinding(prev);
18863 }
18864}
18865
18866/**
18867 * xmlSchemaIDCFreeMatcherList:
18868 * @matcher: the first IDC matcher in the list
18869 *
18870 * Frees a list of IDC matchers.
18871 */
18872static void
18873xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18874{
18875 xmlSchemaIDCMatcherPtr next;
18876
18877 while (matcher != NULL) {
18878 next = matcher->next;
18879 if (matcher->keySeqs != NULL) {
18880 int i;
18881 for (i = 0; i < matcher->sizeKeySeqs; i++)
18882 if (matcher->keySeqs[i] != NULL)
18883 xmlFree(matcher->keySeqs[i]);
18884 xmlFree(matcher->keySeqs);
18885 }
18886 xmlFree(matcher);
18887 matcher = next;
18888 }
18889}
18890
18891/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018892 * xmlSchemaIDCAddStateObject:
18893 * @vctxt: the WXS validation context
18894 * @matcher: the IDC matcher
18895 * @sel: the XPath information
18896 * @parent: the parent "selector" state object if any
18897 * @type: "selector" or "field"
18898 *
18899 * Creates/reuses and activates state objects for the given
18900 * XPath information; if the XPath expression consists of unions,
18901 * multiple state objects are created for every unioned expression.
18902 *
18903 * Returns 0 on success and -1 on internal errors.
18904 */
18905static int
18906xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18907 xmlSchemaIDCMatcherPtr matcher,
18908 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018909 int type)
18910{
18911 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018912
18913 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018914 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018915 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018916 if (vctxt->xpathStatePool != NULL) {
18917 sto = vctxt->xpathStatePool;
18918 vctxt->xpathStatePool = sto->next;
18919 sto->next = NULL;
18920 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018921 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018922 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018923 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018924 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18925 if (sto == NULL) {
18926 xmlSchemaVErrMemory(NULL,
18927 "allocating an IDC state object", NULL);
18928 return (-1);
18929 }
18930 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18931 }
18932 /*
18933 * Add to global list.
18934 */
18935 if (vctxt->xpathStates != NULL)
18936 sto->next = vctxt->xpathStates;
18937 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018938
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018939 /*
18940 * Free the old xpath validation context.
18941 */
18942 if (sto->xpathCtxt != NULL)
18943 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18944
18945 /*
18946 * Create a new XPath (pattern) validation context.
18947 */
18948 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18949 (xmlPatternPtr) sel->xpathComp);
18950 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018951 VERROR_INT("xmlSchemaIDCAddStateObject",
18952 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018953 return (-1);
18954 }
18955 sto->type = type;
18956 sto->depth = vctxt->depth;
18957 sto->matcher = matcher;
18958 sto->sel = sel;
18959 sto->nbHistory = 0;
18960
18961#if DEBUG_IDC
18962 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18963 sto->sel->xpath);
18964#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018965 return (0);
18966}
18967
18968/**
18969 * xmlSchemaXPathEvaluate:
18970 * @vctxt: the WXS validation context
18971 * @nodeType: the nodeType of the current node
18972 *
18973 * Evaluates all active XPath state objects.
18974 *
18975 * Returns the number of IC "field" state objects which resolved to
18976 * this node, 0 if none resolved and -1 on internal errors.
18977 */
18978static int
18979xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018980 xmlElementType nodeType)
18981{
18982 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018983 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018984
18985 if (vctxt->xpathStates == NULL)
18986 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018987
18988 if (nodeType == XML_ATTRIBUTE_NODE)
18989 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018990#if DEBUG_IDC
18991 {
18992 xmlChar *str = NULL;
18993 xmlGenericError(xmlGenericErrorContext,
18994 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018995 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18996 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018997 FREE_AND_NULL(str)
18998 }
18999#endif
19000 /*
19001 * Process all active XPath state objects.
19002 */
19003 first = vctxt->xpathStates;
19004 sto = first;
19005 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019006#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019007 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019008 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19009 sto->matcher->aidc->def->name, sto->sel->xpath);
19010 else
19011 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19012 sto->matcher->aidc->def->name, sto->sel->xpath);
19013#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019014 if (nodeType == XML_ELEMENT_NODE)
19015 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019016 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019017 else
19018 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019019 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019020
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019021 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019022 VERROR_INT("xmlSchemaXPathEvaluate",
19023 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019024 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019025 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019026 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019027 goto next_sto;
19028 /*
19029 * Full match.
19030 */
19031#if DEBUG_IDC
19032 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019033 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019034#endif
19035 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019036 * Register a match in the state object history.
19037 */
19038 if (sto->history == NULL) {
19039 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19040 if (sto->history == NULL) {
19041 xmlSchemaVErrMemory(NULL,
19042 "allocating the state object history", NULL);
19043 return(-1);
19044 }
19045 sto->sizeHistory = 10;
19046 } else if (sto->sizeHistory <= sto->nbHistory) {
19047 sto->sizeHistory *= 2;
19048 sto->history = (int *) xmlRealloc(sto->history,
19049 sto->sizeHistory * sizeof(int));
19050 if (sto->history == NULL) {
19051 xmlSchemaVErrMemory(NULL,
19052 "re-allocating the state object history", NULL);
19053 return(-1);
19054 }
19055 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019056 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019057
19058#ifdef DEBUG_IDC
19059 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19060 vctxt->depth);
19061#endif
19062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019063 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19064 xmlSchemaIDCSelectPtr sel;
19065 /*
19066 * Activate state objects for the IDC fields of
19067 * the IDC selector.
19068 */
19069#if DEBUG_IDC
19070 xmlGenericError(xmlGenericErrorContext, "IDC: "
19071 "activating field states\n");
19072#endif
19073 sel = sto->matcher->aidc->def->fields;
19074 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019075 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19076 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19077 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019078 sel = sel->next;
19079 }
19080 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19081 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019082 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019083 */
19084#if DEBUG_IDC
19085 xmlGenericError(xmlGenericErrorContext,
19086 "IDC: key found\n");
19087#endif
19088 /*
19089 * Notify that the character value of this node is
19090 * needed.
19091 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019092 if (resolved == 0) {
19093 if ((vctxt->inode->flags &
19094 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19095 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19096 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019097 resolved++;
19098 }
19099next_sto:
19100 if (sto->next == NULL) {
19101 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019102 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019103 */
19104 head = first;
19105 sto = vctxt->xpathStates;
19106 } else
19107 sto = sto->next;
19108 }
19109 return (resolved);
19110}
19111
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019112static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019113xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019114 xmlChar **buf,
19115 xmlSchemaPSVIIDCKeyPtr *seq,
19116 int count)
19117{
19118 int i, res;
19119 const xmlChar *value = NULL;
19120
19121 *buf = xmlStrdup(BAD_CAST "[");
19122 for (i = 0; i < count; i++) {
19123 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019124 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19125 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019126 if (res == 0)
19127 *buf = xmlStrcat(*buf, value);
19128 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019129 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19130 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019131 *buf = xmlStrcat(*buf, BAD_CAST "???");
19132 }
19133 if (i < count -1)
19134 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19135 else
19136 *buf = xmlStrcat(*buf, BAD_CAST "'");
19137 if (value != NULL) {
19138 xmlFree((xmlChar *) value);
19139 value = NULL;
19140 }
19141 }
19142 *buf = xmlStrcat(*buf, BAD_CAST "]");
19143
19144 return (BAD_CAST *buf);
19145}
19146
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019147/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019148 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019149 * @vctxt: the WXS validation context
19150 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019151 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019152 *
19153 * Processes and pops the history items of the IDC state objects.
19154 * IDC key-sequences are validated/created on IDC bindings.
19155 *
19156 * Returns 0 on success and -1 on internal errors.
19157 */
19158static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019159xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019160 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019161{
19162 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019163 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019164 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019165 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019166
19167 if (vctxt->xpathStates == NULL)
19168 return (0);
19169 sto = vctxt->xpathStates;
19170
19171#if DEBUG_IDC
19172 {
19173 xmlChar *str = NULL;
19174 xmlGenericError(xmlGenericErrorContext,
19175 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019176 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19177 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019178 FREE_AND_NULL(str)
19179 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019180#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019181 /*
19182 * Evaluate the state objects.
19183 */
19184 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019185 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19186 if (res == -1) {
19187 VERROR_INT("xmlSchemaXPathProcessHistory",
19188 "calling xmlStreamPop()");
19189 return (-1);
19190 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019191#if DEBUG_IDC
19192 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19193 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019194#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019195 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019196 goto deregister_check;
19197
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019198 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019199
19200 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019201 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019202 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019203 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019204 sto = sto->next;
19205 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019206 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019207 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19208 if (! IS_SIMPLE_TYPE(type)) {
19209 /*
19210 * Not qualified if the field resolves to a node of non
19211 * simple type.
19212 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019213 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19214 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019215 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19216 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019217 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019218
19219 sto->nbHistory--;
19220 goto deregister_check;
19221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019222 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019223 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019224 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019225 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019226 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019227 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019228 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19229 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019230 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019231 sto->nbHistory--;
19232 goto deregister_check;
19233 } else {
19234 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19235 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019236 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019237
19238 /*
19239 * The key will be anchored on the matcher's list of
19240 * key-sequences. The position in this list is determined
19241 * by the target node's depth relative to the matcher's
19242 * depth of creation (i.e. the depth of the scope element).
19243 */
19244 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019245 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019246
19247 /*
19248 * Create/grow the array of key-sequences.
19249 */
19250 if (matcher->keySeqs == NULL) {
19251 if (pos > 9)
19252 matcher->sizeKeySeqs = pos * 2;
19253 else
19254 matcher->sizeKeySeqs = 10;
19255 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19256 xmlMalloc(matcher->sizeKeySeqs *
19257 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19258 if (matcher->keySeqs == NULL) {
19259 xmlSchemaVErrMemory(NULL,
19260 "allocating an array of key-sequences",
19261 NULL);
19262 return(-1);
19263 }
19264 memset(matcher->keySeqs, 0,
19265 matcher->sizeKeySeqs *
19266 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19267 } else if (pos >= matcher->sizeKeySeqs) {
19268 int i = matcher->sizeKeySeqs;
19269
19270 matcher->sizeKeySeqs *= 2;
19271 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19272 xmlRealloc(matcher->keySeqs,
19273 matcher->sizeKeySeqs *
19274 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019275 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019276 xmlSchemaVErrMemory(NULL,
19277 "reallocating an array of key-sequences",
19278 NULL);
19279 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019280 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019281 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019282 * The array needs to be NULLed.
19283 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019284 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019285 for (; i < matcher->sizeKeySeqs; i++)
19286 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019287 }
19288
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019289 /*
19290 * Get/create the key-sequence.
19291 */
19292 keySeq = matcher->keySeqs[pos];
19293 if (keySeq == NULL) {
19294 goto create_sequence;
19295 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019296 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019297 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019298 * cvc-identity-constraint:
19299 * 3 For each node in the ·target node set· all
19300 * of the {fields}, with that node as the context
19301 * node, evaluate to either an empty node-set or
19302 * a node-set with exactly one member, which must
19303 * have a simple type.
19304 *
19305 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019306 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019307 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19308 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019309 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019310 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019311 "with more than one member",
19312 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019313 sto->nbHistory--;
19314 goto deregister_check;
19315 } else {
19316 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019317 }
19318 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019319
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019320create_sequence:
19321 /*
19322 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019323 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019324 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19325 matcher->aidc->def->nbFields *
19326 sizeof(xmlSchemaPSVIIDCKeyPtr));
19327 if (keySeq == NULL) {
19328 xmlSchemaVErrMemory(NULL,
19329 "allocating an IDC key-sequence", NULL);
19330 return(-1);
19331 }
19332 memset(keySeq, 0, matcher->aidc->def->nbFields *
19333 sizeof(xmlSchemaPSVIIDCKeyPtr));
19334 matcher->keySeqs[pos] = keySeq;
19335create_key:
19336 /*
19337 * Created a key once per node only.
19338 */
19339 if (key == NULL) {
19340 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19341 sizeof(xmlSchemaPSVIIDCKey));
19342 if (key == NULL) {
19343 xmlSchemaVErrMemory(NULL,
19344 "allocating a IDC key", NULL);
19345 xmlFree(keySeq);
19346 matcher->keySeqs[pos] = NULL;
19347 return(-1);
19348 }
19349 /*
19350 * Consume the compiled value.
19351 */
19352 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019353 key->val = vctxt->inode->val;
19354 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019355 /*
19356 * Store the key in a global list.
19357 */
19358 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19359 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019360 return (-1);
19361 }
19362 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019363 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019364 }
19365 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019366
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019367 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19368 xmlSchemaPSVIIDCBindingPtr bind;
19369 xmlSchemaPSVIIDCNodePtr ntItem;
19370 xmlSchemaIDCMatcherPtr matcher;
19371 xmlSchemaIDCPtr idc;
19372 int pos, i, j, nbKeys;
19373 /*
19374 * Here we have the following scenario:
19375 * An IDC 'selector' state object resolved to a target node,
19376 * during the time this target node was in the
19377 * ancestor-or-self axis, the 'field' state object(s) looked
19378 * out for matching nodes to create a key-sequence for this
19379 * target node. Now we are back to this target node and need
19380 * to put the key-sequence, together with the target node
19381 * itself, into the node-table of the corresponding IDC
19382 * binding.
19383 */
19384 matcher = sto->matcher;
19385 idc = matcher->aidc->def;
19386 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019387 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019388 /*
19389 * Check if the matcher has any key-sequences at all, plus
19390 * if it has a key-sequence for the current target node.
19391 */
19392 if ((matcher->keySeqs == NULL) ||
19393 (matcher->sizeKeySeqs <= pos)) {
19394 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19395 goto selector_key_error;
19396 else
19397 goto selector_leave;
19398 }
19399
19400 keySeq = &(matcher->keySeqs[pos]);
19401 if (*keySeq == NULL) {
19402 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19403 goto selector_key_error;
19404 else
19405 goto selector_leave;
19406 }
19407
19408 for (i = 0; i < nbKeys; i++) {
19409 if ((*keySeq)[i] == NULL) {
19410 /*
19411 * Not qualified, if not all fields did resolve.
19412 */
19413 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19414 /*
19415 * All fields of a "key" IDC must resolve.
19416 */
19417 goto selector_key_error;
19418 }
19419 goto selector_leave;
19420 }
19421 }
19422 /*
19423 * All fields did resolve.
19424 */
19425
19426 /*
19427 * 4.1 If the {identity-constraint category} is unique(/key),
19428 * then no two members of the ·qualified node set· have
19429 * ·key-sequences· whose members are pairwise equal, as
19430 * defined by Equal in [XML Schemas: Datatypes].
19431 *
19432 * Get the IDC binding from the matcher and check for
19433 * duplicate key-sequences.
19434 */
19435 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19436 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19437 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019438 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019439
19440 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019441 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019442 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019443 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019444 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019445 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019446 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019447 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019448 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019449 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019450 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019451 if (res == -1) {
19452 return (-1);
19453 } else if (res == 0)
19454 break;
19455 }
19456 if (res == 1) {
19457 /*
19458 * Duplicate found.
19459 */
19460 break;
19461 }
19462 i++;
19463 } while (i < bind->nbNodes);
19464 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019465 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019466 /*
19467 * TODO: Try to report the key-sequence.
19468 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019469 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19470 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019471 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019472 "Duplicate key-sequence %s",
19473 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19474 (*keySeq), nbKeys), NULL);
19475 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019476 goto selector_leave;
19477 }
19478 }
19479 /*
19480 * Add a node-table item to the IDC binding.
19481 */
19482 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19483 sizeof(xmlSchemaPSVIIDCNode));
19484 if (ntItem == NULL) {
19485 xmlSchemaVErrMemory(NULL,
19486 "allocating an IDC node-table item", NULL);
19487 xmlFree(*keySeq);
19488 *keySeq = NULL;
19489 return(-1);
19490 }
19491 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19492
19493 /*
19494 * Store the node-table item on global list.
19495 */
19496 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19497 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19498 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019499 xmlFree(*keySeq);
19500 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019501 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019502 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019503 }
19504 /*
19505 * Init the node-table item. Consume the key-sequence.
19506 */
19507 ntItem->node = vctxt->node;
19508 ntItem->keys = *keySeq;
19509 *keySeq = NULL;
19510 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19511 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19512 /*
19513 * Free the item, since keyref items won't be
19514 * put on a global list.
19515 */
19516 xmlFree(ntItem->keys);
19517 xmlFree(ntItem);
19518 }
19519 return (-1);
19520 }
19521
19522 goto selector_leave;
19523selector_key_error:
19524 /*
19525 * 4.2.1 (KEY) The ·target node set· and the
19526 * ·qualified node set· are equal, that is, every
19527 * member of the ·target node set· is also a member
19528 * of the ·qualified node set· and vice versa.
19529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019530 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19531 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019532selector_leave:
19533 /*
19534 * Free the key-sequence if not added to the IDC table.
19535 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019536 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019537 xmlFree(*keySeq);
19538 *keySeq = NULL;
19539 }
19540 } /* if selector */
19541
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019542 sto->nbHistory--;
19543
19544deregister_check:
19545 /*
19546 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019547 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019548 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019549#if DEBUG_IDC
19550 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19551 sto->sel->xpath);
19552#endif
19553 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019554 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019555 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019556 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019557 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019558 nextsto = sto->next;
19559 /*
19560 * Unlink from the list of active XPath state objects.
19561 */
19562 vctxt->xpathStates = sto->next;
19563 sto->next = vctxt->xpathStatePool;
19564 /*
19565 * Link it to the pool of reusable state objects.
19566 */
19567 vctxt->xpathStatePool = sto;
19568 sto = nextsto;
19569 } else
19570 sto = sto->next;
19571 } /* while (sto != NULL) */
19572 return (0);
19573}
19574
19575/**
19576 * xmlSchemaIDCRegisterMatchers:
19577 * @vctxt: the WXS validation context
19578 * @elemDecl: the element declaration
19579 *
19580 * Creates helper objects to evaluate IDC selectors/fields
19581 * successively.
19582 *
19583 * Returns 0 if OK and -1 on internal errors.
19584 */
19585static int
19586xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19587 xmlSchemaElementPtr elemDecl)
19588{
19589 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19590 xmlSchemaIDCPtr idc, refIdc;
19591 xmlSchemaIDCAugPtr aidc;
19592
19593 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19594 if (idc == NULL)
19595 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019596
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019597#if DEBUG_IDC
19598 {
19599 xmlChar *str = NULL;
19600 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019601 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019602 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19603 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019604 FREE_AND_NULL(str)
19605 }
19606#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019607 if (vctxt->inode->idcMatchers != NULL) {
19608 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19609 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019610 return (-1);
19611 }
19612 do {
19613 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19614 /*
19615 * Since IDCs bubbles are expensive we need to know the
19616 * depth at which the bubbles should stop; this will be
19617 * the depth of the top-most keyref IDC. If no keyref
19618 * references a key/unique IDC, the bubbleDepth will
19619 * be -1, indicating that no bubbles are needed.
19620 */
19621 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19622 if (refIdc != NULL) {
19623 /*
19624 * Lookup the augmented IDC.
19625 */
19626 aidc = vctxt->aidcs;
19627 while (aidc != NULL) {
19628 if (aidc->def == refIdc)
19629 break;
19630 aidc = aidc->next;
19631 }
19632 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019633 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019634 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019635 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019636 return (-1);
19637 }
19638 if ((aidc->bubbleDepth == -1) ||
19639 (vctxt->depth < aidc->bubbleDepth))
19640 aidc->bubbleDepth = vctxt->depth;
19641 }
19642 }
19643 /*
19644 * Lookup the augmented IDC item for the IDC definition.
19645 */
19646 aidc = vctxt->aidcs;
19647 while (aidc != NULL) {
19648 if (aidc->def == idc)
19649 break;
19650 aidc = aidc->next;
19651 }
19652 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019653 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19654 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019655 return (-1);
19656 }
19657 /*
19658 * Create an IDC matcher for every IDC definition.
19659 */
19660 matcher = (xmlSchemaIDCMatcherPtr)
19661 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19662 if (matcher == NULL) {
19663 xmlSchemaVErrMemory(vctxt,
19664 "allocating an IDC matcher", NULL);
19665 return (-1);
19666 }
19667 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19668 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019669 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019670 else
19671 last->next = matcher;
19672 last = matcher;
19673
19674 matcher->type = IDC_MATCHER;
19675 matcher->depth = vctxt->depth;
19676 matcher->aidc = aidc;
19677#if DEBUG_IDC
19678 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19679#endif
19680 /*
19681 * Init the automaton state object.
19682 */
19683 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019684 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019685 return (-1);
19686
19687 idc = idc->next;
19688 } while (idc != NULL);
19689 return (0);
19690}
19691
19692/**
19693 * xmlSchemaBubbleIDCNodeTables:
19694 * @depth: the current tree depth
19695 *
19696 * Merges IDC bindings of an element at @depth into the corresponding IDC
19697 * bindings of its parent element. If a duplicate note-table entry is found,
19698 * both, the parent node-table entry and child entry are discarded from the
19699 * node-table of the parent.
19700 *
19701 * Returns 0 if OK and -1 on internal errors.
19702 */
19703static int
19704xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19705{
19706 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019707 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19708 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019709 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19710 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019711 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019712 int duplTop;
19713
19714 /*
19715 * The node table has the following sections:
19716 *
19717 * O --> old node-table entries (first)
19718 * O
19719 * + --> new node-table entries
19720 * +
19721 * % --> new duplicate node-table entries
19722 * %
19723 * # --> old duplicate node-table entries
19724 * # (last)
19725 *
19726 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019727 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019728 if (bind == NULL) {
19729 /* Fine, no table, no bubbles. */
19730 return (0);
19731 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019732
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019733 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19734 /*
19735 * Walk all bindings; create new or add to existing bindings.
19736 * Remove duplicate key-sequences.
19737 */
19738start_binding:
19739 while (bind != NULL) {
19740 /*
19741 * Skip keyref IDCs.
19742 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019743 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19744 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019745 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019746 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019747 /*
19748 * Check if the key/unique IDC table needs to be bubbled.
19749 */
19750 aidc = vctxt->aidcs;
19751 do {
19752 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019753 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019754 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019755 bind = bind->next;
19756 goto start_binding;
19757 }
19758 break;
19759 }
19760 aidc = aidc->next;
19761 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019762
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019763 if (parTable != NULL)
19764 parBind = *parTable;
19765 while (parBind != NULL) {
19766 /*
19767 * Search a matching parent binding for the
19768 * IDC definition.
19769 */
19770 if (parBind->definition == bind->definition) {
19771
19772 /*
19773 * Compare every node-table entry of the child node,
19774 * i.e. the key-sequence within, ...
19775 */
19776 oldNum = parBind->nbNodes; /* Skip newly added items. */
19777 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019778 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019779
19780 for (i = 0; i < bind->nbNodes; i++) {
19781 node = bind->nodeTable[i];
19782 if (node == NULL)
19783 continue;
19784 /*
19785 * ...with every key-sequence of the parent node, already
19786 * evaluated to be a duplicate key-sequence.
19787 */
19788 if (parBind->nbDupls != 0) {
19789 j = bind->nbNodes + newDupls;
19790 while (j < duplTop) {
19791 parNode = parBind->nodeTable[j];
19792 for (k = 0; k < bind->definition->nbFields; k++) {
19793 key = node->keys[k];
19794 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019795 ret = xmlSchemaAreValuesEqual(key->val,
19796 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019797 if (ret == -1) {
19798 /* TODO: Internal error */
19799 return(-1);
19800 } else if (ret == 0)
19801 break;
19802
19803 }
19804 if (ret == 1)
19805 /* Duplicate found. */
19806 break;
19807 j++;
19808 }
19809 if (j != duplTop) {
19810 /* Duplicate found. */
19811 continue;
19812 }
19813 }
19814 /*
19815 * ... and with every key-sequence of the parent node.
19816 */
19817 j = 0;
19818 while (j < oldNum) {
19819 parNode = parBind->nodeTable[j];
19820 /*
19821 * Compare key by key.
19822 */
19823 for (k = 0; k < parBind->definition->nbFields; k++) {
19824 key = node->keys[k];
19825 parKey = parNode->keys[k];
19826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019827 ret = xmlSchemaAreValuesEqual(key->val,
19828 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019829 if (ret == -1) {
19830 /* TODO: Internal error */
19831 } else if (ret == 0)
19832 break;
19833
19834 }
19835 if (ret == 1)
19836 /*
19837 * The key-sequences are equal.
19838 */
19839 break;
19840 j++;
19841 }
19842 if (j != oldNum) {
19843 /*
19844 * Handle duplicates.
19845 */
19846 newDupls++;
19847 oldNum--;
19848 parBind->nbNodes--;
19849 /*
19850 * Move last old item to pos of duplicate.
19851 */
19852 parBind->nodeTable[j] =
19853 parBind->nodeTable[oldNum];
19854
19855 if (parBind->nbNodes != oldNum) {
19856 /*
19857 * If new items exist, move last new item to
19858 * last of old items.
19859 */
19860 parBind->nodeTable[oldNum] =
19861 parBind->nodeTable[parBind->nbNodes];
19862 }
19863 /*
19864 * Move duplicate to last pos of new/old items.
19865 */
19866 parBind->nodeTable[parBind->nbNodes] = parNode;
19867
19868 } else {
19869 /*
19870 * Add the node-table entry (node and key-sequence) of
19871 * the child node to the node table of the parent node.
19872 */
19873 if (parBind->nodeTable == NULL) {
19874 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019875 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019876 if (parBind->nodeTable == NULL) {
19877 xmlSchemaVErrMemory(NULL,
19878 "allocating IDC list of node-table items", NULL);
19879 return(-1);
19880 }
19881 parBind->sizeNodes = 1;
19882 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019883 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019884 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19885 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19886 sizeof(xmlSchemaPSVIIDCNodePtr));
19887 if (parBind->nodeTable == NULL) {
19888 xmlSchemaVErrMemory(NULL,
19889 "re-allocating IDC list of node-table items", NULL);
19890 return(-1);
19891 }
19892 }
19893
19894 /*
19895 * Move first old duplicate to last position
19896 * of old duplicates +1.
19897 */
19898 if (parBind->nbDupls != 0) {
19899 parBind->nodeTable[duplTop] =
19900 parBind->nodeTable[parBind->nbNodes + newDupls];
19901 }
19902 /*
19903 * Move first new duplicate to last position of
19904 * new duplicates +1.
19905 */
19906 if (newDupls != 0) {
19907 parBind->nodeTable[parBind->nbNodes + newDupls] =
19908 parBind->nodeTable[parBind->nbNodes];
19909 }
19910 /*
19911 * Append the new node-table entry to the 'new node-table
19912 * entries' section.
19913 */
19914 parBind->nodeTable[parBind->nbNodes] = node;
19915 parBind->nbNodes++;
19916 duplTop++;
19917 }
19918 }
19919 parBind->nbDupls += newDupls;
19920 break;
19921 }
19922 if (parBind->next == NULL)
19923 lastParBind = parBind;
19924 parBind = parBind->next;
19925 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019926 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019927 /*
19928 * No binding for the IDC was found: create a new one and
19929 * copy all node-tables.
19930 */
19931 parBind = xmlSchemaIDCNewBinding(bind->definition);
19932 if (parBind == NULL)
19933 return(-1);
19934
19935 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19936 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19937 if (parBind->nodeTable == NULL) {
19938 xmlSchemaVErrMemory(NULL,
19939 "allocating an array of IDC node-table items", NULL);
19940 xmlSchemaIDCFreeBinding(parBind);
19941 return(-1);
19942 }
19943 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019944 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019945 memcpy(parBind->nodeTable, bind->nodeTable,
19946 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019947 if (*parTable == NULL)
19948 *parTable = parBind;
19949 else
19950 lastParBind->next = parBind;
19951 }
19952 bind = bind->next;
19953 }
19954 return (0);
19955}
19956
19957/**
19958 * xmlSchemaCheckCVCIDCKeyRef:
19959 * @vctxt: the WXS validation context
19960 * @elemDecl: the element declaration
19961 *
19962 * Check the cvc-idc-keyref constraints.
19963 */
19964static int
19965xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19966{
19967 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019969 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019970 /*
19971 * Find a keyref.
19972 */
19973 while (refbind != NULL) {
19974 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19975 int i, j, k, res;
19976 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19977 xmlSchemaPSVIIDCKeyPtr refKey, key;
19978
19979 /*
19980 * Find the referred key/unique.
19981 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019982 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019983 do {
19984 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19985 bind->definition)
19986 break;
19987 bind = bind->next;
19988 } while (bind != NULL);
19989
19990 /*
19991 * Search for a matching key-sequences.
19992 */
19993 for (i = 0; i < refbind->nbNodes; i++) {
19994 res = 0;
19995 if (bind != NULL) {
19996 refKeys = refbind->nodeTable[i]->keys;
19997 for (j = 0; j < bind->nbNodes; j++) {
19998 keys = bind->nodeTable[j]->keys;
19999 for (k = 0; k < bind->definition->nbFields; k++) {
20000 refKey = refKeys[k];
20001 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020002 res = xmlSchemaAreValuesEqual(key->val,
20003 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020004 if (res == 0)
20005 break;
20006 else if (res == -1) {
20007 return (-1);
20008 }
20009 }
20010 if (res == 1) {
20011 /*
20012 * Match found.
20013 */
20014 break;
20015 }
20016 }
20017 }
20018 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020019 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020020 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020021 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20022 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020023 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020024 "No match found for key-sequence %s of key "
20025 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020026 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020027 refbind->nodeTable[i]->keys,
20028 refbind->definition->nbFields),
20029 xmlSchemaFormatQName(&strB,
20030 refbind->definition->targetNamespace,
20031 refbind->definition->name));
20032 FREE_AND_NULL(str);
20033 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020034 }
20035 }
20036 }
20037 refbind = refbind->next;
20038 }
20039 return (0);
20040}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020041
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020042/************************************************************************
20043 * *
20044 * XML Reader validation code *
20045 * *
20046 ************************************************************************/
20047
20048static xmlSchemaAttrInfoPtr
20049xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020050{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020051 xmlSchemaAttrInfoPtr iattr;
20052 /*
20053 * Grow/create list of attribute infos.
20054 */
20055 if (vctxt->attrInfos == NULL) {
20056 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20057 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20058 vctxt->sizeAttrInfos = 1;
20059 if (vctxt->attrInfos == NULL) {
20060 xmlSchemaVErrMemory(vctxt,
20061 "allocating attribute info list", NULL);
20062 return (NULL);
20063 }
20064 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20065 vctxt->sizeAttrInfos++;
20066 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20067 xmlRealloc(vctxt->attrInfos,
20068 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20069 if (vctxt->attrInfos == NULL) {
20070 xmlSchemaVErrMemory(vctxt,
20071 "re-allocating attribute info list", NULL);
20072 return (NULL);
20073 }
20074 } else {
20075 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20076 if (iattr->localName != NULL) {
20077 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20078 "attr info not cleared");
20079 return (NULL);
20080 }
20081 iattr->nodeType = XML_ATTRIBUTE_NODE;
20082 return (iattr);
20083 }
20084 /*
20085 * Create an attribute info.
20086 */
20087 iattr = (xmlSchemaAttrInfoPtr)
20088 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20089 if (iattr == NULL) {
20090 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20091 return (NULL);
20092 }
20093 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20094 iattr->nodeType = XML_ATTRIBUTE_NODE;
20095 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20096
20097 return (iattr);
20098}
20099
20100static int
20101xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20102 xmlNodePtr attrNode,
20103 const xmlChar *localName,
20104 const xmlChar *nsName,
20105 int ownedNames,
20106 xmlChar *value,
20107 int ownedValue)
20108{
20109 xmlSchemaAttrInfoPtr attr;
20110
20111 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20112 if (attr == NULL) {
20113 VERROR_INT("xmlSchemaPushAttribute",
20114 "calling xmlSchemaGetFreshAttrInfo()");
20115 return (-1);
20116 }
20117 attr->node = attrNode;
20118 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20119 attr->localName = localName;
20120 attr->nsName = nsName;
20121 if (ownedNames)
20122 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20123 /*
20124 * Evaluate if it's an XSI attribute.
20125 */
20126 if (nsName != NULL) {
20127 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20128 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20129 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20130 }
20131 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20132 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20133 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20134 }
20135 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20136 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20137 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20138 }
20139 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20140 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20141 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20142 }
20143 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20144 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20145 }
20146 }
20147 attr->value = value;
20148 if (ownedValue)
20149 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20150 if (attr->metaType != 0)
20151 attr->state = XML_SCHEMAS_ATTR_META;
20152 return (0);
20153}
20154
20155static void
20156xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20157{
20158 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20159 FREE_AND_NULL(ielem->localName);
20160 FREE_AND_NULL(ielem->nsName);
20161 } else {
20162 ielem->localName = NULL;
20163 ielem->nsName = NULL;
20164 }
20165 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20166 FREE_AND_NULL(ielem->value);
20167 } else {
20168 ielem->value = NULL;
20169 }
20170 if (ielem->val != NULL) {
20171 xmlSchemaFreeValue(ielem->val);
20172 ielem->val = NULL;
20173 }
20174 if (ielem->idcMatchers != NULL) {
20175 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20176 ielem->idcMatchers = NULL;
20177 }
20178 if (ielem->idcTable != NULL) {
20179 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20180 ielem->idcTable = NULL;
20181 }
20182 if (ielem->regexCtxt != NULL) {
20183 xmlRegFreeExecCtxt(ielem->regexCtxt);
20184 ielem->regexCtxt = NULL;
20185 }
20186 if (ielem->nsBindings != NULL) {
20187 xmlFree((xmlChar **)ielem->nsBindings);
20188 ielem->nsBindings = NULL;
20189 ielem->nbNsBindings = 0;
20190 ielem->sizeNsBindings = 0;
20191 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020192}
20193
20194/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020195 * xmlSchemaGetFreshElemInfo:
20196 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020197 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020198 * Creates/reuses and initializes the element info item for
20199 * the currect tree depth.
20200 *
20201 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020202 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020203static xmlSchemaNodeInfoPtr
20204xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020205{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020206 xmlSchemaNodeInfoPtr info = NULL;
20207
20208 if (vctxt->depth > vctxt->sizeElemInfos) {
20209 VERROR_INT("xmlSchemaGetFreshElemInfo",
20210 "inconsistent depth encountered");
20211 return (NULL);
20212 }
20213 if (vctxt->elemInfos == NULL) {
20214 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20215 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20216 if (vctxt->elemInfos == NULL) {
20217 xmlSchemaVErrMemory(vctxt,
20218 "allocating the element info array", NULL);
20219 return (NULL);
20220 }
20221 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20222 vctxt->sizeElemInfos = 10;
20223 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20224 int i = vctxt->sizeElemInfos;
20225
20226 vctxt->sizeElemInfos *= 2;
20227 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20228 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20229 sizeof(xmlSchemaNodeInfoPtr));
20230 if (vctxt->elemInfos == NULL) {
20231 xmlSchemaVErrMemory(vctxt,
20232 "re-allocating the element info array", NULL);
20233 return (NULL);
20234 }
20235 /*
20236 * We need the new memory to be NULLed.
20237 * TODO: Use memset instead?
20238 */
20239 for (; i < vctxt->sizeElemInfos; i++)
20240 vctxt->elemInfos[i] = NULL;
20241 } else
20242 info = vctxt->elemInfos[vctxt->depth];
20243
20244 if (info == NULL) {
20245 info = (xmlSchemaNodeInfoPtr)
20246 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20247 if (info == NULL) {
20248 xmlSchemaVErrMemory(vctxt,
20249 "allocating an element info", NULL);
20250 return (NULL);
20251 }
20252 vctxt->elemInfos[vctxt->depth] = info;
20253 } else {
20254 if (info->localName != NULL) {
20255 VERROR_INT("xmlSchemaGetFreshElemInfo",
20256 "elem info has not been cleared");
20257 return (NULL);
20258 }
20259 }
20260 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20261 info->nodeType = XML_ELEMENT_NODE;
20262 info->depth = vctxt->depth;
20263
20264 return (info);
20265}
20266
20267#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20268#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20269#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20270
20271static int
20272xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20273 xmlNodePtr node,
20274 xmlSchemaTypePtr type,
20275 xmlSchemaValType valType,
20276 const xmlChar * value,
20277 xmlSchemaValPtr val,
20278 unsigned long length,
20279 int fireErrors)
20280{
20281 int ret, error = 0;
20282
20283 xmlSchemaTypePtr tmpType;
20284 xmlSchemaFacetLinkPtr facetLink;
20285 xmlSchemaFacetPtr facet;
20286 unsigned long len = 0;
20287 xmlSchemaWhitespaceValueType ws;
20288
20289 /*
20290 * In Libxml2, derived built-in types have currently no explicit facets.
20291 */
20292 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020293 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020294
20295 /*
20296 * NOTE: Do not jump away, if the facetSet of the given type is
20297 * empty: until now, "pattern" and "enumeration" facets of the
20298 * *base types* need to be checked as well.
20299 */
20300 if (type->facetSet == NULL)
20301 goto pattern_and_enum;
20302
20303 if (! VARIETY_ATOMIC(type)) {
20304 if (VARIETY_LIST(type))
20305 goto variety_list;
20306 else
20307 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020308 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020309 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020310 * Whitespace handling is only of importance for string-based
20311 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020312 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020313 tmpType = xmlSchemaGetPrimitiveType(type);
20314 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20315 IS_ANY_SIMPLE_TYPE(tmpType)) {
20316 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20317 } else
20318 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20319 /*
20320 * If the value was not computed (for string or
20321 * anySimpleType based types), then use the provided
20322 * type.
20323 */
20324 if (val == NULL)
20325 valType = valType;
20326 else
20327 valType = xmlSchemaGetValType(val);
20328
20329 ret = 0;
20330 for (facetLink = type->facetSet; facetLink != NULL;
20331 facetLink = facetLink->next) {
20332 /*
20333 * Skip the pattern "whiteSpace": it is used to
20334 * format the character content beforehand.
20335 */
20336 switch (facetLink->facet->type) {
20337 case XML_SCHEMA_FACET_WHITESPACE:
20338 case XML_SCHEMA_FACET_PATTERN:
20339 case XML_SCHEMA_FACET_ENUMERATION:
20340 continue;
20341 case XML_SCHEMA_FACET_LENGTH:
20342 case XML_SCHEMA_FACET_MINLENGTH:
20343 case XML_SCHEMA_FACET_MAXLENGTH:
20344 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20345 valType, value, val, &len, ws);
20346 break;
20347 default:
20348 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20349 valType, value, val, ws);
20350 break;
20351 }
20352 if (ret < 0) {
20353 AERROR_INT("xmlSchemaValidateFacets",
20354 "validating against a atomic type facet");
20355 return (-1);
20356 } else if (ret > 0) {
20357 if (fireErrors)
20358 xmlSchemaFacetErr(actxt, ret, node,
20359 value, len, type, facetLink->facet, NULL, NULL, NULL);
20360 else
20361 return (ret);
20362 if (error == 0)
20363 error = ret;
20364 }
20365 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020367
20368variety_list:
20369 if (! VARIETY_LIST(type))
20370 goto pattern_and_enum;
20371 /*
20372 * "length", "minLength" and "maxLength" of list types.
20373 */
20374 ret = 0;
20375 for (facetLink = type->facetSet; facetLink != NULL;
20376 facetLink = facetLink->next) {
20377
20378 switch (facetLink->facet->type) {
20379 case XML_SCHEMA_FACET_LENGTH:
20380 case XML_SCHEMA_FACET_MINLENGTH:
20381 case XML_SCHEMA_FACET_MAXLENGTH:
20382 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20383 value, length, NULL);
20384 break;
20385 default:
20386 continue;
20387 }
20388 if (ret < 0) {
20389 AERROR_INT("xmlSchemaValidateFacets",
20390 "validating against a list type facet");
20391 return (-1);
20392 } else if (ret > 0) {
20393 if (fireErrors)
20394 xmlSchemaFacetErr(actxt, ret, node,
20395 value, length, type, facetLink->facet, NULL, NULL, NULL);
20396 else
20397 return (ret);
20398 if (error == 0)
20399 error = ret;
20400 }
20401 ret = 0;
20402 }
20403
20404pattern_and_enum:
20405 if (error >= 0) {
20406 int found = 0;
20407 /*
20408 * Process enumerations. Facet values are in the value space
20409 * of the defining type's base type. This seems to be a bug in the
20410 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20411 * Only the first set of enumerations in the ancestor-or-self axis
20412 * is used for validation.
20413 */
20414 ret = 0;
20415 tmpType = type;
20416 do {
20417 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20418 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20419 continue;
20420 found = 1;
20421 ret = xmlSchemaAreValuesEqual(facet->val, val);
20422 if (ret == 1)
20423 break;
20424 else if (ret < 0) {
20425 AERROR_INT("xmlSchemaValidateFacets",
20426 "validating against an enumeration facet");
20427 return (-1);
20428 }
20429 }
20430 if (ret != 0)
20431 break;
20432 tmpType = tmpType->baseType;
20433 } while ((tmpType != NULL) &&
20434 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20435 if (found && (ret == 0)) {
20436 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20437 if (fireErrors) {
20438 xmlSchemaFacetErr(actxt, ret, node,
20439 value, 0, type, NULL, NULL, NULL, NULL);
20440 } else
20441 return (ret);
20442 if (error == 0)
20443 error = ret;
20444 }
20445 }
20446
20447 if (error >= 0) {
20448 int found;
20449 /*
20450 * Process patters. Pattern facets are ORed at type level
20451 * and ANDed if derived. Walk the base type axis.
20452 */
20453 tmpType = type;
20454 facet = NULL;
20455 do {
20456 found = 0;
20457 for (facetLink = tmpType->facetSet; facetLink != NULL;
20458 facetLink = facetLink->next) {
20459 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20460 continue;
20461 found = 1;
20462 /*
20463 * NOTE that for patterns, @value needs to be the
20464 * normalized vaule.
20465 */
20466 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20467 if (ret == 1)
20468 break;
20469 else if (ret < 0) {
20470 AERROR_INT("xmlSchemaValidateFacets",
20471 "validating against a pattern facet");
20472 return (-1);
20473 } else {
20474 /*
20475 * Save the last non-validating facet.
20476 */
20477 facet = facetLink->facet;
20478 }
20479 }
20480 if (found && (ret != 1)) {
20481 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20482 if (fireErrors) {
20483 xmlSchemaFacetErr(actxt, ret, node,
20484 value, 0, type, facet, NULL, NULL, NULL);
20485 } else
20486 return (ret);
20487 if (error == 0)
20488 error = ret;
20489 break;
20490 }
20491 tmpType = tmpType->baseType;
20492 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20493 }
20494
20495 return (error);
20496}
20497
20498static xmlChar *
20499xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20500 const xmlChar *value)
20501{
20502 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20503 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20504 return (xmlSchemaCollapseString(value));
20505 case XML_SCHEMA_WHITESPACE_REPLACE:
20506 return (xmlSchemaWhiteSpaceReplace(value));
20507 default:
20508 return (NULL);
20509 }
20510}
20511
20512static int
20513xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20514 const xmlChar *value,
20515 xmlSchemaValPtr *val,
20516 int valNeeded)
20517{
20518 int ret;
20519 const xmlChar *nsName;
20520 xmlChar *local, *prefix = NULL;
20521
20522 ret = xmlValidateQName(value, 1);
20523 if (ret != 0) {
20524 if (ret == -1) {
20525 VERROR_INT("xmlSchemaValidateQName",
20526 "calling xmlValidateQName()");
20527 return (-1);
20528 }
20529 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20530 }
20531 /*
20532 * NOTE: xmlSplitQName2 will always return a duplicated
20533 * strings.
20534 */
20535 local = xmlSplitQName2(value, &prefix);
20536 if (local == NULL)
20537 local = xmlStrdup(value);
20538 /*
20539 * OPTIMIZE TODO: Use flags for:
20540 * - is there any namespace binding?
20541 * - is there a default namespace?
20542 */
20543 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20544
20545 if (prefix != NULL) {
20546 xmlFree(prefix);
20547 /*
20548 * A namespace must be found if the prefix is
20549 * NOT NULL.
20550 */
20551 if (nsName == NULL) {
20552 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20553 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20554 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20555 "The QName value '%s' has no "
20556 "corresponding namespace declaration in "
20557 "scope", value, NULL);
20558 if (local != NULL)
20559 xmlFree(local);
20560 return (ret);
20561 }
20562 }
20563 if (valNeeded && val) {
20564 if (nsName != NULL)
20565 *val = xmlSchemaNewQNameValue(
20566 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20567 else
20568 *val = xmlSchemaNewQNameValue(NULL,
20569 BAD_CAST local);
20570 } else
20571 xmlFree(local);
20572 return (0);
20573}
20574
20575/*
20576* cvc-simple-type
20577*/
20578static int
20579xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20580 xmlNodePtr node,
20581 xmlSchemaTypePtr type,
20582 const xmlChar *value,
20583 xmlSchemaValPtr *retVal,
20584 int fireErrors,
20585 int normalize,
20586 int isNormalized)
20587{
20588 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20589 xmlSchemaValPtr val = NULL;
20590 xmlSchemaWhitespaceValueType ws;
20591 xmlChar *normValue = NULL;
20592
20593#define NORMALIZE(atype) \
20594 if ((! isNormalized) && \
20595 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20596 normValue = xmlSchemaNormalizeValue(atype, value); \
20597 if (normValue != NULL) \
20598 value = normValue; \
20599 isNormalized = 1; \
20600 }
20601
20602 if ((retVal != NULL) && (*retVal != NULL)) {
20603 xmlSchemaFreeValue(*retVal);
20604 *retVal = NULL;
20605 }
20606 /*
20607 * 3.14.4 Simple Type Definition Validation Rules
20608 * Validation Rule: String Valid
20609 */
20610 /*
20611 * 1 It is schema-valid with respect to that definition as defined
20612 * by Datatype Valid in [XML Schemas: Datatypes].
20613 */
20614 /*
20615 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20616 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20617 * the string must be a ·declared entity name·.
20618 */
20619 /*
20620 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20621 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20622 * then every whitespace-delimited substring of the string must be a ·declared
20623 * entity name·.
20624 */
20625 /*
20626 * 2.3 otherwise no further condition applies.
20627 */
20628 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20629 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020630 if (value == NULL)
20631 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020632 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20633 xmlSchemaTypePtr biType; /* The built-in type. */
20634 /*
20635 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20636 * a literal in the ·lexical space· of {base type definition}"
20637 */
20638 /*
20639 * Whitespace-normalize.
20640 */
20641 NORMALIZE(type);
20642 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20643 /*
20644 * Get the built-in type.
20645 */
20646 biType = type->baseType;
20647 while ((biType != NULL) &&
20648 (biType->type != XML_SCHEMA_TYPE_BASIC))
20649 biType = biType->baseType;
20650
20651 if (biType == NULL) {
20652 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20653 "could not get the built-in type");
20654 goto internal_error;
20655 }
20656 } else
20657 biType = type;
20658 /*
20659 * NOTATIONs need to be processed here, since they need
20660 * to lookup in the hashtable of NOTATION declarations of the schema.
20661 */
20662 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20663 switch (biType->builtInType) {
20664 case XML_SCHEMAS_NOTATION:
20665 ret = xmlSchemaValidateNotation(
20666 (xmlSchemaValidCtxtPtr) actxt,
20667 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20668 NULL, value, &val, valNeeded);
20669 break;
20670 case XML_SCHEMAS_QNAME:
20671 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20672 value, &val, valNeeded);
20673 break;
20674 default:
20675 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20676 if (valNeeded)
20677 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20678 value, &val, NULL);
20679 else
20680 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20681 value, NULL, NULL);
20682 break;
20683 }
20684 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20685 switch (biType->builtInType) {
20686 case XML_SCHEMAS_NOTATION:
20687 ret = xmlSchemaValidateNotation(NULL,
20688 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20689 value, &val, valNeeded);
20690 break;
20691 default:
20692 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20693 if (valNeeded)
20694 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20695 value, &val, node);
20696 else
20697 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20698 value, NULL, node);
20699 break;
20700 }
20701 } else {
20702 /*
20703 * Validation via a public API is not implemented yet.
20704 */
20705 TODO
20706 goto internal_error;
20707 }
20708 if (ret != 0) {
20709 if (ret < 0) {
20710 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20711 "validating against a built-in type");
20712 goto internal_error;
20713 }
20714 if (VARIETY_LIST(type))
20715 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20716 else
20717 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20718 }
20719 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20720 /*
20721 * Check facets.
20722 */
20723 ret = xmlSchemaValidateFacets(actxt, node, type,
20724 (xmlSchemaValType) biType->builtInType, value, val,
20725 0, fireErrors);
20726 if (ret != 0) {
20727 if (ret < 0) {
20728 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20729 "validating facets of atomic simple type");
20730 goto internal_error;
20731 }
20732 if (VARIETY_LIST(type))
20733 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20734 else
20735 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20736 }
20737 }
20738 if (fireErrors && (ret > 0))
20739 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20740 } else if (VARIETY_LIST(type)) {
20741
20742 xmlSchemaTypePtr itemType;
20743 const xmlChar *cur, *end;
20744 xmlChar *tmpValue = NULL;
20745 unsigned long len = 0;
20746 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20747 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20748 * of white space separated tokens, each of which ·match·es a literal
20749 * in the ·lexical space· of {item type definition}
20750 */
20751 /*
20752 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20753 * the list type has an enum or pattern facet.
20754 */
20755 NORMALIZE(type);
20756 /*
20757 * VAL TODO: Optimize validation of empty values.
20758 * VAL TODO: We do not have computed values for lists.
20759 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020760 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020761 cur = value;
20762 do {
20763 while (IS_BLANK_CH(*cur))
20764 cur++;
20765 end = cur;
20766 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20767 end++;
20768 if (end == cur)
20769 break;
20770 tmpValue = xmlStrndup(cur, end - cur);
20771 len++;
20772
20773 if (valNeeded)
20774 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20775 tmpValue, &curVal, fireErrors, 0, 1);
20776 else
20777 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20778 tmpValue, NULL, fireErrors, 0, 1);
20779 FREE_AND_NULL(tmpValue);
20780 if (curVal != NULL) {
20781 /*
20782 * Add to list of computed values.
20783 */
20784 if (val == NULL)
20785 val = curVal;
20786 else
20787 xmlSchemaValueAppend(prevVal, curVal);
20788 prevVal = curVal;
20789 curVal = NULL;
20790 }
20791 if (ret != 0) {
20792 if (ret < 0) {
20793 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20794 "validating an item of list simple type");
20795 goto internal_error;
20796 }
20797 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20798 break;
20799 }
20800 cur = end;
20801 } while (*cur != 0);
20802 FREE_AND_NULL(tmpValue);
20803 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20804 /*
20805 * Apply facets (pattern, enumeration).
20806 */
20807 ret = xmlSchemaValidateFacets(actxt, node, type,
20808 XML_SCHEMAS_UNKNOWN, value, val,
20809 len, fireErrors);
20810 if (ret != 0) {
20811 if (ret < 0) {
20812 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20813 "validating facets of list simple type");
20814 goto internal_error;
20815 }
20816 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20817 }
20818 }
20819 if (fireErrors && (ret > 0)) {
20820 /*
20821 * Report the normalized value.
20822 */
20823 normalize = 1;
20824 NORMALIZE(type);
20825 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20826 }
20827 } else if (VARIETY_UNION(type)) {
20828 xmlSchemaTypeLinkPtr memberLink;
20829 /*
20830 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20831 * not apply directly; however, the normalization behavior of ·union·
20832 * types is controlled by the value of whiteSpace on that one of the
20833 * ·memberTypes· against which the ·union· is successfully validated.
20834 *
20835 * This means that the value is normalized by the first validating
20836 * member type, then the facets of the union type are applied. This
20837 * needs changing of the value!
20838 */
20839
20840 /*
20841 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20842 * literal in the ·lexical space· of at least one member of
20843 * {member type definitions}
20844 */
20845 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20846 if (memberLink == NULL) {
20847 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20848 "union simple type has no member types");
20849 goto internal_error;
20850 }
20851 /*
20852 * Always normalize union type values, since we currently
20853 * cannot store the whitespace information with the value
20854 * itself; otherwise a later value-comparison would be
20855 * not possible.
20856 */
20857 while (memberLink != NULL) {
20858 if (valNeeded)
20859 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20860 memberLink->type, value, &val, 0, 1, 0);
20861 else
20862 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20863 memberLink->type, value, NULL, 0, 1, 0);
20864 if (ret <= 0)
20865 break;
20866 memberLink = memberLink->next;
20867 }
20868 if (ret != 0) {
20869 if (ret < 0) {
20870 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20871 "validating members of union simple type");
20872 goto internal_error;
20873 }
20874 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20875 }
20876 /*
20877 * Apply facets (pattern, enumeration).
20878 */
20879 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20880 /*
20881 * The normalization behavior of ·union· types is controlled by
20882 * the value of whiteSpace on that one of the ·memberTypes·
20883 * against which the ·union· is successfully validated.
20884 */
20885 NORMALIZE(memberLink->type);
20886 ret = xmlSchemaValidateFacets(actxt, node, type,
20887 XML_SCHEMAS_UNKNOWN, value, val,
20888 0, fireErrors);
20889 if (ret != 0) {
20890 if (ret < 0) {
20891 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20892 "validating facets of union simple type");
20893 goto internal_error;
20894 }
20895 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20896 }
20897 }
20898 if (fireErrors && (ret > 0))
20899 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20900 }
20901
20902 if (normValue != NULL)
20903 xmlFree(normValue);
20904 if (ret == 0) {
20905 if (retVal != NULL)
20906 *retVal = val;
20907 else if (val != NULL)
20908 xmlSchemaFreeValue(val);
20909 } else if (val != NULL)
20910 xmlSchemaFreeValue(val);
20911 return (ret);
20912internal_error:
20913 if (normValue != NULL)
20914 xmlFree(normValue);
20915 if (val != NULL)
20916 xmlSchemaFreeValue(val);
20917 return (-1);
20918}
20919
20920static int
20921xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20922 const xmlChar *value,
20923 const xmlChar **nsName,
20924 const xmlChar **localName)
20925{
20926 int ret = 0;
20927
20928 if ((nsName == NULL) || (localName == NULL))
20929 return (-1);
20930 *nsName = NULL;
20931 *localName = NULL;
20932
20933 ret = xmlValidateQName(value, 1);
20934 if (ret == -1)
20935 return (-1);
20936 if (ret > 0) {
20937 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20938 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20939 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20940 return (1);
20941 }
20942 {
20943 xmlChar *local = NULL;
20944 xmlChar *prefix;
20945
20946 /*
20947 * NOTE: xmlSplitQName2 will return a duplicated
20948 * string.
20949 */
20950 local = xmlSplitQName2(value, &prefix);
20951 VAL_CREATE_DICT;
20952 if (local == NULL)
20953 *localName = xmlDictLookup(vctxt->dict, value, -1);
20954 else {
20955 *localName = xmlDictLookup(vctxt->dict, local, -1);
20956 xmlFree(local);
20957 }
20958
20959 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20960
20961 if (prefix != NULL) {
20962 xmlFree(prefix);
20963 /*
20964 * A namespace must be found if the prefix is NOT NULL.
20965 */
20966 if (*nsName == NULL) {
20967 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20968 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20969 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20970 "The QName value '%s' has no "
20971 "corresponding namespace declaration in scope",
20972 value, NULL);
20973 return (2);
20974 }
20975 }
20976 }
20977 return (0);
20978}
20979
20980static int
20981xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20982 xmlSchemaAttrInfoPtr iattr,
20983 xmlSchemaTypePtr *localType,
20984 xmlSchemaElementPtr elemDecl)
20985{
20986 int ret = 0;
20987 /*
20988 * cvc-elt (3.3.4) : (4)
20989 * AND
20990 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20991 * (1.2.1.2.1) - (1.2.1.2.4)
20992 * Handle 'xsi:type'.
20993 */
20994 if (localType == NULL)
20995 return (-1);
20996 *localType = NULL;
20997 if (iattr == NULL)
20998 return (0);
20999 else {
21000 const xmlChar *nsName = NULL, *local = NULL;
21001 /*
21002 * TODO: We should report a *warning* that the type was overriden
21003 * by the instance.
21004 */
21005 ACTIVATE_ATTRIBUTE(iattr);
21006 /*
21007 * (cvc-elt) (3.3.4) : (4.1)
21008 * (cvc-assess-elt) (1.2.1.2.2)
21009 */
21010 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
21011 &nsName, &local);
21012 if (ret != 0) {
21013 if (ret < 0) {
21014 VERROR_INT("xmlSchemaValidateElementByDeclaration",
21015 "calling xmlSchemaQNameExpand() to validate the "
21016 "attribute 'xsi:type'");
21017 goto internal_error;
21018 }
21019 goto exit;
21020 }
21021 /*
21022 * (cvc-elt) (3.3.4) : (4.2)
21023 * (cvc-assess-elt) (1.2.1.2.3)
21024 */
21025 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
21026 if (*localType == NULL) {
21027 xmlChar *str = NULL;
21028
21029 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21030 XML_SCHEMAV_CVC_ELT_4_2, NULL,
21031 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21032 "The QName value '%s' of the xsi:type attribute does not "
21033 "resolve to a type definition",
21034 xmlSchemaFormatQName(&str, nsName, local), NULL);
21035 FREE_AND_NULL(str);
21036 ret = vctxt->err;
21037 goto exit;
21038 }
21039 if (elemDecl != NULL) {
21040 int set = 0;
21041
21042 /*
21043 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21044 * "The ·local type definition· must be validly
21045 * derived from the {type definition} given the union of
21046 * the {disallowed substitutions} and the {type definition}'s
21047 * {prohibited substitutions}, as defined in
21048 * Type Derivation OK (Complex) (§3.4.6)
21049 * (if it is a complex type definition),
21050 * or given {disallowed substitutions} as defined in Type
21051 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21052 * definition)."
21053 *
21054 * {disallowed substitutions}: the "block" on the element decl.
21055 * {prohibited substitutions}: the "block" on the type def.
21056 */
21057 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21058 (elemDecl->subtypes->flags &
21059 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21060 set |= SUBSET_EXTENSION;
21061
21062 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21063 (elemDecl->subtypes->flags &
21064 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21065 set |= SUBSET_RESTRICTION;
21066
21067 if (xmlSchemaCheckCOSDerivedOK(*localType,
21068 elemDecl->subtypes, set) != 0) {
21069 xmlChar *str = NULL;
21070
21071 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21072 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21073 "The type definition '%s', specified by xsi:type, is "
21074 "blocked or not validly derived from the type definition "
21075 "of the element declaration",
21076 xmlSchemaFormatQName(&str,
21077 (*localType)->targetNamespace,
21078 (*localType)->name),
21079 NULL);
21080 FREE_AND_NULL(str);
21081 ret = vctxt->err;
21082 *localType = NULL;
21083 }
21084 }
21085 }
21086exit:
21087 ACTIVATE_ELEM;
21088 return (ret);
21089internal_error:
21090 ACTIVATE_ELEM;
21091 return (-1);
21092}
21093
21094static int
21095xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21096{
21097 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21098 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21099
21100 /*
21101 * cvc-elt (3.3.4) : 1
21102 */
21103 if (elemDecl == NULL) {
21104 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21105 "No matching declaration available");
21106 return (vctxt->err);
21107 }
21108 /*
21109 * cvc-elt (3.3.4) : 2
21110 */
21111 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21112 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21113 "The element declaration is abstract");
21114 return (vctxt->err);
21115 }
21116 if (actualType == NULL) {
21117 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21118 "The type definition is absent");
21119 return (XML_SCHEMAV_CVC_TYPE_1);
21120 }
21121 if (vctxt->nbAttrInfos != 0) {
21122 int ret;
21123 xmlSchemaAttrInfoPtr iattr;
21124 /*
21125 * cvc-elt (3.3.4) : 3
21126 * Handle 'xsi:nil'.
21127 */
21128 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21129 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21130 if (iattr) {
21131 ACTIVATE_ATTRIBUTE(iattr);
21132 /*
21133 * Validate the value.
21134 */
21135 ret = xmlSchemaVCheckCVCSimpleType(
21136 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21137 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21138 iattr->value, &(iattr->val), 1, 0, 0);
21139 ACTIVATE_ELEM;
21140 if (ret < 0) {
21141 VERROR_INT("xmlSchemaValidateElemDecl",
21142 "calling xmlSchemaVCheckCVCSimpleType() to "
21143 "validate the attribute 'xsi:nil'");
21144 return (-1);
21145 }
21146 if (ret == 0) {
21147 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21148 /*
21149 * cvc-elt (3.3.4) : 3.1
21150 */
21151 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21152 "The element is not 'nillable'");
21153 /* Does not return an error on purpose. */
21154 } else {
21155 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21156 /*
21157 * cvc-elt (3.3.4) : 3.2.2
21158 */
21159 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21160 (elemDecl->value != NULL)) {
21161 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21162 "The element cannot be 'nilled' because "
21163 "there is a fixed value constraint defined "
21164 "for it");
21165 /* Does not return an error on purpose. */
21166 } else
21167 vctxt->inode->flags |=
21168 XML_SCHEMA_ELEM_INFO_NILLED;
21169 }
21170 }
21171 }
21172 }
21173 /*
21174 * cvc-elt (3.3.4) : 4
21175 * Handle 'xsi:type'.
21176 */
21177 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21178 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21179 if (iattr) {
21180 xmlSchemaTypePtr localType = NULL;
21181
21182 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21183 elemDecl);
21184 if (ret != 0) {
21185 if (ret == -1) {
21186 VERROR_INT("xmlSchemaValidateElemDecl",
21187 "calling xmlSchemaProcessXSIType() to "
21188 "process the attribute 'xsi:type'");
21189 return (-1);
21190 }
21191 /* Does not return an error on purpose. */
21192 }
21193 if (localType != NULL) {
21194 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21195 actualType = localType;
21196 }
21197 }
21198 }
21199 /*
21200 * IDC: Register identity-constraint XPath matchers.
21201 */
21202 if ((elemDecl->idcs != NULL) &&
21203 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21204 return (-1);
21205 /*
21206 * No actual type definition.
21207 */
21208 if (actualType == NULL) {
21209 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21210 "The type definition is absent");
21211 return (XML_SCHEMAV_CVC_TYPE_1);
21212 }
21213 /*
21214 * Remember the actual type definition.
21215 */
21216 vctxt->inode->typeDef = actualType;
21217
21218 return (0);
21219}
21220
21221static int
21222xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21223{
21224 xmlSchemaAttrInfoPtr iattr;
21225 int ret = 0, i;
21226
21227 /*
21228 * SPEC cvc-type (3.1.1)
21229 * "The attributes of must be empty, excepting those whose namespace
21230 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21231 * whose local name is one of type, nil, schemaLocation or
21232 * noNamespaceSchemaLocation."
21233 */
21234 if (vctxt->nbAttrInfos == 0)
21235 return (0);
21236 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21237 iattr = vctxt->attrInfos[i];
21238 if (! iattr->metaType) {
21239 ACTIVATE_ATTRIBUTE(iattr)
21240 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21241 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21242 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21243 }
21244 }
21245 ACTIVATE_ELEM
21246 return (ret);
21247}
21248
21249/*
21250* Cleanup currently used attribute infos.
21251*/
21252static void
21253xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21254{
21255 int i;
21256 xmlSchemaAttrInfoPtr attr;
21257
21258 if (vctxt->nbAttrInfos == 0)
21259 return;
21260 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21261 attr = vctxt->attrInfos[i];
21262 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21263 if (attr->localName != NULL)
21264 xmlFree((xmlChar *) attr->localName);
21265 if (attr->nsName != NULL)
21266 xmlFree((xmlChar *) attr->nsName);
21267 }
21268 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21269 if (attr->value != NULL)
21270 xmlFree((xmlChar *) attr->value);
21271 }
21272 if (attr->val != NULL) {
21273 xmlSchemaFreeValue(attr->val);
21274 attr->val = NULL;
21275 }
21276 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21277 }
21278 vctxt->nbAttrInfos = 0;
21279}
21280
21281/*
21282* 3.4.4 Complex Type Definition Validation Rules
21283* Element Locally Valid (Complex Type) (cvc-complex-type)
21284* 3.2.4 Attribute Declaration Validation Rules
21285* Validation Rule: Attribute Locally Valid (cvc-attribute)
21286* Attribute Locally Valid (Use) (cvc-au)
21287*
21288* Only "assessed" attribute information items will be visible to
21289* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21290*/
21291static int
21292xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21293{
21294 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21295 xmlSchemaAttributeLinkPtr attrUseLink;
21296 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21297 xmlSchemaAttrInfoPtr attr, tmpAttr;
21298 int i, found, nbAttrs;
21299 int xpathRes = 0, res, wildIDs = 0, fixed;
21300
21301 /*
21302 * SPEC (cvc-attribute)
21303 * (1) "The declaration must not be ·absent· (see Missing
21304 * Sub-components (§5.3) for how this can fail to be
21305 * the case)."
21306 * (2) "Its {type definition} must not be absent."
21307 *
21308 * NOTE (1) + (2): This is not handled here, since we currently do not
21309 * allow validation against schemas which have missing sub-components.
21310 *
21311 * SPEC (cvc-complex-type)
21312 * (3) "For each attribute information item in the element information
21313 * item's [attributes] excepting those whose [namespace name] is
21314 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21315 * [local name] is one of type, nil, schemaLocation or
21316 * noNamespaceSchemaLocation, the appropriate case among the following
21317 * must be true:
21318 *
21319 */
21320 nbAttrs = vctxt->nbAttrInfos;
21321 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21322 attrUseLink = attrUseLink->next) {
21323
21324 found = 0;
21325 attrUse = attrUseLink->attr;
21326 /*
21327 * VAL TODO: Implement a real "attribute use" component.
21328 */
21329 if (attrUse->refDecl != NULL)
21330 attrDecl = attrUse->refDecl;
21331 else
21332 attrDecl = attrUse;
21333 for (i = 0; i < nbAttrs; i++) {
21334 attr = vctxt->attrInfos[i];
21335 /*
21336 * SPEC (cvc-complex-type) (3)
21337 * Skip meta attributes.
21338 */
21339 if (attr->metaType)
21340 continue;
21341 if (attr->localName[0] != attrDecl->name[0])
21342 continue;
21343 if (!xmlStrEqual(attr->localName, attrDecl->name))
21344 continue;
21345 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21346 continue;
21347 found = 1;
21348 /*
21349 * SPEC (cvc-complex-type)
21350 * (3.1) "If there is among the {attribute uses} an attribute
21351 * use with an {attribute declaration} whose {name} matches
21352 * the attribute information item's [local name] and whose
21353 * {target namespace} is identical to the attribute information
21354 * item's [namespace name] (where an ·absent· {target namespace}
21355 * is taken to be identical to a [namespace name] with no value),
21356 * then the attribute information must be ·valid· with respect
21357 * to that attribute use as per Attribute Locally Valid (Use)
21358 * (§3.5.4). In this case the {attribute declaration} of that
21359 * attribute use is the ·context-determined declaration· for the
21360 * attribute information item with respect to Schema-Validity
21361 * Assessment (Attribute) (§3.2.4) and
21362 * Assessment Outcome (Attribute) (§3.2.5).
21363 */
21364 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21365 attr->use = attrUse;
21366 /*
21367 * Context-determined declaration.
21368 */
21369 attr->decl = attrDecl;
21370 attr->typeDef = attrDecl->subtypes;
21371 break;
21372 }
21373
21374 if (found)
21375 continue;
21376
21377 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21378 /*
21379 * Handle non-existent, required attributes.
21380 *
21381 * SPEC (cvc-complex-type)
21382 * (4) "The {attribute declaration} of each attribute use in
21383 * the {attribute uses} whose {required} is true matches one
21384 * of the attribute information items in the element information
21385 * item's [attributes] as per clause 3.1 above."
21386 */
21387 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21388 if (tmpAttr == NULL) {
21389 VERROR_INT(
21390 "xmlSchemaVAttributesComplex",
21391 "calling xmlSchemaGetFreshAttrInfo()");
21392 return (-1);
21393 }
21394 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21395 tmpAttr->use = attrUse;
21396 tmpAttr->decl = attrDecl;
21397 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21398 ((attrUse->defValue != NULL) ||
21399 (attrDecl->defValue != NULL))) {
21400 /*
21401 * Handle non-existent, optional, default/fixed attributes.
21402 */
21403 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21404 if (tmpAttr == NULL) {
21405 VERROR_INT(
21406 "xmlSchemaVAttributesComplex",
21407 "calling xmlSchemaGetFreshAttrInfo()");
21408 return (-1);
21409 }
21410 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21411 tmpAttr->use = attrUse;
21412 tmpAttr->decl = attrDecl;
21413 tmpAttr->typeDef = attrDecl->subtypes;
21414 tmpAttr->localName = attrDecl->name;
21415 tmpAttr->nsName = attrDecl->targetNamespace;
21416 }
21417 }
21418 if (vctxt->nbAttrInfos == 0)
21419 return (0);
21420 /*
21421 * Validate against the wildcard.
21422 */
21423 if (type->attributeWildcard != NULL) {
21424 /*
21425 * SPEC (cvc-complex-type)
21426 * (3.2.1) "There must be an {attribute wildcard}."
21427 */
21428 for (i = 0; i < nbAttrs; i++) {
21429 attr = vctxt->attrInfos[i];
21430 /*
21431 * SPEC (cvc-complex-type) (3)
21432 * Skip meta attributes.
21433 */
21434 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21435 continue;
21436 /*
21437 * SPEC (cvc-complex-type)
21438 * (3.2.2) "The attribute information item must be ·valid· with
21439 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21440 *
21441 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21442 * "... its [namespace name] must be ·valid· with respect to
21443 * the wildcard constraint, as defined in Wildcard allows
21444 * Namespace Name (§3.10.4)."
21445 */
21446 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21447 attr->nsName)) {
21448 /*
21449 * Handle processContents.
21450 *
21451 * SPEC (cvc-wildcard):
21452 * processContents | context-determined declaration:
21453 * "strict" "mustFind"
21454 * "lax" "none"
21455 * "skip" "skip"
21456 */
21457 if (type->attributeWildcard->processContents ==
21458 XML_SCHEMAS_ANY_SKIP) {
21459 /*
21460 * context-determined declaration = "skip"
21461 *
21462 * SPEC PSVI Assessment Outcome (Attribute)
21463 * [validity] = "notKnown"
21464 * [validation attempted] = "none"
21465 */
21466 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21467 continue;
21468 }
21469 /*
21470 * Find an attribute declaration.
21471 */
21472 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21473 attr->localName, attr->nsName);
21474 if (attr->decl != NULL) {
21475 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21476 /*
21477 * SPEC (cvc-complex-type)
21478 * (5) "Let [Definition:] the wild IDs be the set of
21479 * all attribute information item to which clause 3.2
21480 * applied and whose ·validation· resulted in a
21481 * ·context-determined declaration· of mustFind or no
21482 * ·context-determined declaration· at all, and whose
21483 * [local name] and [namespace name] resolve (as
21484 * defined by QName resolution (Instance) (§3.15.4)) to
21485 * an attribute declaration whose {type definition} is
21486 * or is derived from ID. Then all of the following
21487 * must be true:"
21488 */
21489 attr->typeDef = attr->decl->subtypes;
21490 if (xmlSchemaIsDerivedFromBuiltInType(
21491 attr->typeDef, XML_SCHEMAS_ID)) {
21492 /*
21493 * SPEC (5.1) "There must be no more than one
21494 * item in ·wild IDs·."
21495 */
21496 if (wildIDs != 0) {
21497 /* VAL TODO */
21498 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21499 TODO
21500 continue;
21501 }
21502 wildIDs++;
21503 /*
21504 * SPEC (cvc-complex-type)
21505 * (5.2) "If ·wild IDs· is non-empty, there must not
21506 * be any attribute uses among the {attribute uses}
21507 * whose {attribute declaration}'s {type definition}
21508 * is or is derived from ID."
21509 */
21510 for (attrUseLink = type->attributeUses;
21511 attrUseLink != NULL;
21512 attrUseLink = attrUseLink->next) {
21513 if (xmlSchemaIsDerivedFromBuiltInType(
21514 attrUseLink->attr->subtypes,
21515 XML_SCHEMAS_ID)) {
21516 /* VAL TODO */
21517 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21518 TODO
21519 }
21520 }
21521 }
21522 } else if (type->attributeWildcard->processContents ==
21523 XML_SCHEMAS_ANY_LAX) {
21524 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21525 /*
21526 * SPEC PSVI Assessment Outcome (Attribute)
21527 * [validity] = "notKnown"
21528 * [validation attempted] = "none"
21529 */
21530 } else {
21531 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21532 }
21533 }
21534 }
21535 }
21536
21537
21538 if (vctxt->nbAttrInfos == 0)
21539 return (0);
21540
21541 /*
21542 * Validate values, create default attributes, evaluate IDCs.
21543 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021544 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21545 attr = vctxt->attrInfos[i];
21546 /*
21547 * VAL TODO: Note that we won't try to resolve IDCs to
21548 * "lax" and "skip" validated attributes. Check what to
21549 * do in this case.
21550 */
21551 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21552 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21553 continue;
21554 /*
21555 * VAL TODO: What to do if the type definition is missing?
21556 */
21557 if (attr->typeDef == NULL) {
21558 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21559 continue;
21560 }
21561
21562 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021563 fixed = 0;
21564 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021565
21566 if (vctxt->xpathStates != NULL) {
21567 /*
21568 * Evaluate IDCs.
21569 */
21570 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21571 XML_ATTRIBUTE_NODE);
21572 if (xpathRes == -1) {
21573 VERROR_INT("xmlSchemaVAttributesComplex",
21574 "calling xmlSchemaXPathEvaluate()");
21575 goto internal_error;
21576 }
21577 }
21578
21579 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21580 /*
21581 * Default/fixed attributes.
21582 */
21583 if (xpathRes) {
21584 if (attr->use->defValue == NULL) {
21585 attr->value = (xmlChar *) attr->use->defValue;
21586 attr->val = attr->use->defVal;
21587 } else {
21588 attr->value = (xmlChar *) attr->decl->defValue;
21589 attr->val = attr->decl->defVal;
21590 }
21591 /*
21592 * IDCs will consume the precomputed default value,
21593 * so we need to clone it.
21594 */
21595 if (attr->val == NULL) {
21596 VERROR_INT("xmlSchemaVAttributesComplex",
21597 "default/fixed value on an attribute use was "
21598 "not precomputed");
21599 goto internal_error;
21600 }
21601 attr->val = xmlSchemaCopyValue(attr->val);
21602 if (attr->val == NULL) {
21603 VERROR_INT("xmlSchemaVAttributesComplex",
21604 "calling xmlSchemaCopyValue()");
21605 goto internal_error;
21606 }
21607 }
21608 /*
21609 * PSVI: Add the default attribute to the current element.
21610 * VAL TODO: Should we use the *normalized* value? This currently
21611 * uses the *initial* value.
21612 */
21613 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21614 (attr->node != NULL) && (attr->node->doc != NULL)) {
21615 xmlChar *normValue;
21616 const xmlChar *value;
21617
21618 value = attr->value;
21619 /*
21620 * Normalize the value.
21621 */
21622 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21623 attr->value);
21624 if (normValue != NULL)
21625 value = BAD_CAST normValue;
21626
21627 if (attr->nsName == NULL) {
21628 if (xmlNewProp(attr->node->parent,
21629 attr->localName, value) == NULL) {
21630 VERROR_INT("xmlSchemaVAttributesComplex",
21631 "callling xmlNewProp()");
21632 if (normValue != NULL)
21633 xmlFree(normValue);
21634 goto internal_error;
21635 }
21636 } else {
21637 xmlNsPtr ns;
21638
21639 ns = xmlSearchNsByHref(attr->node->doc,
21640 attr->node->parent, attr->nsName);
21641 if (ns == NULL) {
21642 xmlChar prefix[12];
21643 int counter = 0;
21644
21645 /*
21646 * Create a namespace declaration on the validation
21647 * root node if no namespace declaration is in scope.
21648 */
21649 do {
21650 snprintf((char *) prefix, 12, "p%d", counter++);
21651 ns = xmlSearchNs(attr->node->doc,
21652 attr->node->parent, BAD_CAST prefix);
21653 if (counter > 1000) {
21654 VERROR_INT(
21655 "xmlSchemaVAttributesComplex",
21656 "could not compute a ns prefix for a "
21657 "default/fixed attribute");
21658 if (normValue != NULL)
21659 xmlFree(normValue);
21660 goto internal_error;
21661 }
21662 } while (ns != NULL);
21663 ns = xmlNewNs(vctxt->validationRoot,
21664 attr->nsName, BAD_CAST prefix);
21665 }
21666 xmlNewNsProp(attr->node->parent, ns,
21667 attr->localName, value);
21668 }
21669 if (normValue != NULL)
21670 xmlFree(normValue);
21671 }
21672 /*
21673 * Go directly to IDC evaluation.
21674 */
21675 goto eval_idcs;
21676 }
21677 /*
21678 * Validate the value.
21679 */
21680 if (vctxt->value != NULL) {
21681 /*
21682 * Free last computed value; just for safety reasons.
21683 */
21684 xmlSchemaFreeValue(vctxt->value);
21685 vctxt->value = NULL;
21686 }
21687 /*
21688 * Note that the attribute *use* can be unavailable, if
21689 * the attribute was a wild attribute.
21690 */
21691 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21692 ((attr->use != NULL) &&
21693 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21694 fixed = 1;
21695 else
21696 fixed = 0;
21697 /*
21698 * SPEC (cvc-attribute)
21699 * (3) "The item's ·normalized value· must be locally ·valid·
21700 * with respect to that {type definition} as per
21701 * String Valid (§3.14.4)."
21702 *
21703 * VAL TODO: Do we already have the
21704 * "normalized attribute value" here?
21705 */
21706 if (xpathRes || fixed) {
21707 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21708 /*
21709 * Request a computed value.
21710 */
21711 res = xmlSchemaVCheckCVCSimpleType(
21712 (xmlSchemaAbstractCtxtPtr) vctxt,
21713 attr->node, attr->typeDef, attr->value, &(attr->val),
21714 1, 1, 0);
21715 } else {
21716 res = xmlSchemaVCheckCVCSimpleType(
21717 (xmlSchemaAbstractCtxtPtr) vctxt,
21718 attr->node, attr->typeDef, attr->value, NULL,
21719 1, 0, 0);
21720 }
21721
21722 if (res != 0) {
21723 if (res == -1) {
21724 VERROR_INT("xmlSchemaVAttributesComplex",
21725 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21726 goto internal_error;
21727 }
21728 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21729 /*
21730 * SPEC PSVI Assessment Outcome (Attribute)
21731 * [validity] = "invalid"
21732 */
21733 goto eval_idcs;
21734 }
21735
21736 if (fixed) {
21737 int ws;
21738 /*
21739 * SPEC Attribute Locally Valid (Use) (cvc-au)
21740 * "For an attribute information item to be·valid·
21741 * with respect to an attribute use its *normalized*
21742 * value· must match the *canonical* lexical
21743 * representation of the attribute use's {value
21744 * constraint}value, if it is present and fixed."
21745 *
21746 * VAL TODO: The requirement for the *canonical* value
21747 * will be removed in XML Schema 1.1.
21748 */
21749 /*
21750 * SPEC Attribute Locally Valid (cvc-attribute)
21751 * (4) "The item's *actual* value· must match the *value* of
21752 * the {value constraint}, if it is present and fixed."
21753 */
21754 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21755 if (attr->val == NULL) {
21756 /* VAL TODO: A value was not precomputed. */
21757 TODO
21758 goto eval_idcs;
21759 }
21760 if ((attr->use != NULL) &&
21761 (attr->use->defValue != NULL)) {
21762 if (attr->use->defVal == NULL) {
21763 /* VAL TODO: A default value was not precomputed. */
21764 TODO
21765 goto eval_idcs;
21766 }
21767 attr->vcValue = attr->use->defValue;
21768 /*
21769 if (xmlSchemaCompareValuesWhtsp(attr->val,
21770 (xmlSchemaWhitespaceValueType) ws,
21771 attr->use->defVal,
21772 (xmlSchemaWhitespaceValueType) ws) != 0) {
21773 */
21774 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21775 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21776 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021777 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021778 /* VAL TODO: A default value was not precomputed. */
21779 TODO
21780 goto eval_idcs;
21781 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021782 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021783 /*
21784 if (xmlSchemaCompareValuesWhtsp(attr->val,
21785 (xmlSchemaWhitespaceValueType) ws,
21786 attrDecl->defVal,
21787 (xmlSchemaWhitespaceValueType) ws) != 0) {
21788 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021789 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021790 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21791 }
21792 /*
21793 * [validity] = "valid"
21794 */
21795 }
21796eval_idcs:
21797 /*
21798 * Evaluate IDCs.
21799 */
21800 if (xpathRes) {
21801 if (xmlSchemaXPathProcessHistory(vctxt,
21802 vctxt->depth +1) == -1) {
21803 VERROR_INT("xmlSchemaVAttributesComplex",
21804 "calling xmlSchemaXPathEvaluate()");
21805 goto internal_error;
21806 }
21807 }
21808 }
21809
21810 /*
21811 * Report errors.
21812 */
21813 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21814 attr = vctxt->attrInfos[i];
21815 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21816 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21817 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21818 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21819 continue;
21820 ACTIVATE_ATTRIBUTE(attr);
21821 switch (attr->state) {
21822 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21823 xmlChar *str = NULL;
21824 ACTIVATE_ELEM;
21825 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21826 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21827 "The attribute '%s' is required but missing",
21828 xmlSchemaFormatQName(&str,
21829 attr->decl->targetNamespace,
21830 attr->decl->name),
21831 NULL);
21832 FREE_AND_NULL(str)
21833 break;
21834 }
21835 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21836 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21837 "The type definition is absent");
21838 break;
21839 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21840 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21841 XML_SCHEMAV_CVC_AU, NULL, NULL,
21842 "The value '%s' does not match the fixed "
21843 "value constraint '%s'",
21844 attr->value, attr->vcValue);
21845 break;
21846 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21847 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21848 "No matching global attribute declaration available, but "
21849 "demanded by the strict wildcard");
21850 break;
21851 case XML_SCHEMAS_ATTR_UNKNOWN:
21852 if (attr->metaType)
21853 break;
21854 /*
21855 * MAYBE VAL TODO: One might report different error messages
21856 * for the following errors.
21857 */
21858 if (type->attributeWildcard == NULL) {
21859 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21860 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21861 } else {
21862 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21863 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21864 }
21865 break;
21866 default:
21867 break;
21868 }
21869 }
21870
21871 ACTIVATE_ELEM;
21872 return (0);
21873internal_error:
21874 ACTIVATE_ELEM;
21875 return (-1);
21876}
21877
21878static int
21879xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21880 int *skip)
21881{
21882 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21883 /*
21884 * The namespace of the element was already identified to be
21885 * matching the wildcard.
21886 */
21887 if ((skip == NULL) || (wild == NULL) ||
21888 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21889 VERROR_INT("xmlSchemaValidateElemWildcard",
21890 "bad arguments");
21891 return (-1);
21892 }
21893 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021894 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21895 /*
21896 * URGENT VAL TODO: Either we need to position the stream to the
21897 * next sibling, or walk the whole subtree.
21898 */
21899 *skip = 1;
21900 return (0);
21901 }
21902 {
21903 xmlSchemaElementPtr decl = NULL;
21904
21905 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21906 vctxt->inode->localName, vctxt->inode->nsName,
21907 NULL);
21908 if (decl != NULL) {
21909 vctxt->inode->decl = decl;
21910 return (0);
21911 }
21912 }
21913 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21914 /* VAL TODO: Change to proper error code. */
21915 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21916 "No matching global element declaration available, but "
21917 "demanded by the strict wildcard");
21918 return (vctxt->err);
21919 }
21920 if (vctxt->nbAttrInfos != 0) {
21921 xmlSchemaAttrInfoPtr iattr;
21922 /*
21923 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21924 * (1.2.1.2.1) - (1.2.1.2.3 )
21925 *
21926 * Use the xsi:type attribute for the type definition.
21927 */
21928 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21929 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21930 if (iattr != NULL) {
21931 if (xmlSchemaProcessXSIType(vctxt, iattr,
21932 &(vctxt->inode->typeDef), NULL) == -1) {
21933 VERROR_INT("xmlSchemaValidateElemWildcard",
21934 "calling xmlSchemaProcessXSIType() to "
21935 "process the attribute 'xsi:nil'");
21936 return (-1);
21937 }
21938 /*
21939 * Don't return an error on purpose.
21940 */
21941 return (0);
21942 }
21943 }
21944 /*
21945 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21946 *
21947 * Fallback to "anyType".
21948 */
21949 vctxt->inode->typeDef =
21950 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21951 return (0);
21952}
21953
21954/*
21955* xmlSchemaCheckCOSValidDefault:
21956*
21957* This will be called if: not nilled, no content and a default/fixed
21958* value is provided.
21959*/
21960
21961static int
21962xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21963 const xmlChar *value,
21964 xmlSchemaValPtr *val)
21965{
21966 int ret = 0;
21967 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21968
21969 /*
21970 * cos-valid-default:
21971 * Schema Component Constraint: Element Default Valid (Immediate)
21972 * For a string to be a valid default with respect to a type
21973 * definition the appropriate case among the following must be true:
21974 */
21975 if IS_COMPLEX_TYPE(inode->typeDef) {
21976 /*
21977 * Complex type.
21978 *
21979 * SPEC (2.1) "its {content type} must be a simple type definition
21980 * or mixed."
21981 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21982 * type}'s particle must be ·emptiable· as defined by
21983 * Particle Emptiable (§3.9.6)."
21984 */
21985 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21986 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21987 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21988 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21989 /* NOTE that this covers (2.2.2) as well. */
21990 VERROR(ret, NULL,
21991 "For a string to be a valid default, the type definition "
21992 "must be a simple type or a complex type with simple content "
21993 "or mixed content and a particle emptiable");
21994 return(ret);
21995 }
21996 }
21997 /*
21998 * 1 If the type definition is a simple type definition, then the string
21999 * must be ·valid· with respect to that definition as defined by String
22000 * Valid (§3.14.4).
22001 *
22002 * AND
22003 *
22004 * 2.2.1 If the {content type} is a simple type definition, then the
22005 * string must be ·valid· with respect to that simple type definition
22006 * as defined by String Valid (§3.14.4).
22007 */
22008 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22009
22010 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22011 NULL, inode->typeDef, value, val, 1, 1, 0);
22012
22013 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22014
22015 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22016 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22017 }
22018 if (ret < 0) {
22019 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22020 "calling xmlSchemaVCheckCVCSimpleType()");
22021 }
22022 return (ret);
22023}
22024
22025static void
22026xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22027 const xmlChar * name ATTRIBUTE_UNUSED,
22028 xmlSchemaElementPtr item,
22029 xmlSchemaNodeInfoPtr inode)
22030{
22031 inode->decl = item;
22032#ifdef DEBUG_CONTENT
22033 {
22034 xmlChar *str = NULL;
22035
22036 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22037 xmlGenericError(xmlGenericErrorContext,
22038 "AUTOMATON callback for '%s' [declaration]\n",
22039 xmlSchemaFormatQName(&str,
22040 inode->localName, inode->nsName));
22041 } else {
22042 xmlGenericError(xmlGenericErrorContext,
22043 "AUTOMATON callback for '%s' [wildcard]\n",
22044 xmlSchemaFormatQName(&str,
22045 inode->localName, inode->nsName));
22046
22047 }
22048 FREE_AND_NULL(str)
22049 }
22050#endif
22051}
22052
22053static int
22054xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022055{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022056 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22057 if (vctxt->inode == NULL) {
22058 VERROR_INT("xmlSchemaValidatorPushElem",
22059 "calling xmlSchemaGetFreshElemInfo()");
22060 return (-1);
22061 }
22062 vctxt->nbAttrInfos = 0;
22063 return (0);
22064}
22065
22066static int
22067xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22068 xmlSchemaNodeInfoPtr inode,
22069 xmlSchemaTypePtr type,
22070 const xmlChar *value)
22071{
22072 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22073 return (xmlSchemaVCheckCVCSimpleType(
22074 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22075 type, value, &(inode->val), 1, 1, 0));
22076 else
22077 return (xmlSchemaVCheckCVCSimpleType(
22078 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22079 type, value, NULL, 1, 0, 0));
22080}
22081
22082
22083
22084/*
22085* Process END of element.
22086*/
22087static int
22088xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22089{
22090 int ret = 0;
22091 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22092
22093 if (vctxt->nbAttrInfos != 0)
22094 xmlSchemaClearAttrInfos(vctxt);
22095 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22096 /*
22097 * This element was not expected;
22098 * we will not validate child elements of broken parents.
22099 * Skip validation of all content of the parent.
22100 */
22101 vctxt->skipDepth = vctxt->depth -1;
22102 goto end_elem;
22103 }
22104 if ((inode->typeDef == NULL) ||
22105 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22106 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022107 * 1. the type definition might be missing if the element was
22108 * error prone
22109 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022110 */
22111 goto end_elem;
22112 }
22113 /*
22114 * Check the content model.
22115 */
22116 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22117 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22118
22119 /*
22120 * Workaround for "anyType".
22121 */
22122 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22123 goto character_content;
22124
22125 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22126 xmlChar *values[10];
22127 int terminal, nbval = 10, nbneg;
22128
22129 if (inode->regexCtxt == NULL) {
22130 /*
22131 * Create the regex context.
22132 */
22133 inode->regexCtxt =
22134 xmlRegNewExecCtxt(inode->typeDef->contModel,
22135 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22136 vctxt);
22137 if (inode->regexCtxt == NULL) {
22138 VERROR_INT("xmlSchemaValidatorPopElem",
22139 "failed to create a regex context");
22140 goto internal_error;
22141 }
22142#ifdef DEBUG_AUTOMATA
22143 xmlGenericError(xmlGenericErrorContext,
22144 "AUTOMATON create on '%s'\n", inode->localName);
22145#endif
22146 }
22147 /*
22148 * Get hold of the still expected content, since a further
22149 * call to xmlRegExecPushString() will loose this information.
22150 */
22151 xmlRegExecNextValues(inode->regexCtxt,
22152 &nbval, &nbneg, &values[0], &terminal);
22153 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22154 if (ret <= 0) {
22155 /*
22156 * Still missing something.
22157 */
22158 ret = 1;
22159 inode->flags |=
22160 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22161 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22162 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22163 "Missing child element(s)",
22164 nbval, nbneg, values);
22165#ifdef DEBUG_AUTOMATA
22166 xmlGenericError(xmlGenericErrorContext,
22167 "AUTOMATON missing ERROR on '%s'\n",
22168 inode->localName);
22169#endif
22170 } else {
22171 /*
22172 * Content model is satisfied.
22173 */
22174 ret = 0;
22175#ifdef DEBUG_AUTOMATA
22176 xmlGenericError(xmlGenericErrorContext,
22177 "AUTOMATON succeeded on '%s'\n",
22178 inode->localName);
22179#endif
22180 }
22181
22182 }
22183 }
22184 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22185 goto end_elem;
22186
22187character_content:
22188
22189 if (vctxt->value != NULL) {
22190 xmlSchemaFreeValue(vctxt->value);
22191 vctxt->value = NULL;
22192 }
22193 /*
22194 * Check character content.
22195 */
22196 if (inode->decl == NULL) {
22197 /*
22198 * Speedup if no declaration exists.
22199 */
22200 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22201 ret = xmlSchemaVCheckINodeDataType(vctxt,
22202 inode, inode->typeDef, inode->value);
22203 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22204 ret = xmlSchemaVCheckINodeDataType(vctxt,
22205 inode, inode->typeDef->contentTypeDef,
22206 inode->value);
22207 }
22208 if (ret < 0) {
22209 VERROR_INT("xmlSchemaValidatorPopElem",
22210 "calling xmlSchemaVCheckCVCSimpleType()");
22211 goto internal_error;
22212 }
22213 goto end_elem;
22214 }
22215 /*
22216 * cvc-elt (3.3.4) : 5
22217 * The appropriate case among the following must be true:
22218 */
22219 /*
22220 * cvc-elt (3.3.4) : 5.1
22221 * If the declaration has a {value constraint},
22222 * the item has neither element nor character [children] and
22223 * clause 3.2 has not applied, then all of the following must be true:
22224 */
22225 if ((inode->decl->value != NULL) &&
22226 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22227 (! INODE_NILLED(inode))) {
22228 /*
22229 * cvc-elt (3.3.4) : 5.1.1
22230 * If the ·actual type definition· is a ·local type definition·
22231 * then the canonical lexical representation of the {value constraint}
22232 * value must be a valid default for the ·actual type definition· as
22233 * defined in Element Default Valid (Immediate) (§3.3.6).
22234 */
22235 /*
22236 * NOTE: 'local' above means types aquired by xsi:type.
22237 * NOTE: Although the *canonical* value is stated, it is not
22238 * relevant if canonical or not. Additionally XML Schema 1.1
22239 * will removed this requirement as well.
22240 */
22241 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22242
22243 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22244 inode->decl->value, &(inode->val));
22245 if (ret != 0) {
22246 if (ret < 0) {
22247 VERROR_INT("xmlSchemaValidatorPopElem",
22248 "calling xmlSchemaCheckCOSValidDefault()");
22249 goto internal_error;
22250 }
22251 goto end_elem;
22252 }
22253 /*
22254 * Stop here, to avoid redundant validation of the value
22255 * (see following).
22256 */
22257 goto default_psvi;
22258 }
22259 /*
22260 * cvc-elt (3.3.4) : 5.1.2
22261 * The element information item with the canonical lexical
22262 * representation of the {value constraint} value used as its
22263 * ·normalized value· must be ·valid· with respect to the
22264 * ·actual type definition· as defined by Element Locally Valid (Type)
22265 * (§3.3.4).
22266 */
22267 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22268 ret = xmlSchemaVCheckINodeDataType(vctxt,
22269 inode, inode->typeDef, inode->decl->value);
22270 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22271 ret = xmlSchemaVCheckINodeDataType(vctxt,
22272 inode, inode->typeDef->contentTypeDef,
22273 inode->decl->value);
22274 }
22275 if (ret != 0) {
22276 if (ret < 0) {
22277 VERROR_INT("xmlSchemaValidatorPopElem",
22278 "calling xmlSchemaVCheckCVCSimpleType()");
22279 goto internal_error;
22280 }
22281 goto end_elem;
22282 }
22283
22284default_psvi:
22285 /*
22286 * PSVI: Create a text node on the instance element.
22287 */
22288 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22289 (inode->node != NULL)) {
22290 xmlNodePtr textChild;
22291 xmlChar *normValue;
22292 /*
22293 * VAL TODO: Normalize the value.
22294 */
22295 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22296 inode->decl->value);
22297 if (normValue != NULL) {
22298 textChild = xmlNewText(BAD_CAST normValue);
22299 xmlFree(normValue);
22300 } else
22301 textChild = xmlNewText(inode->decl->value);
22302 if (textChild == NULL) {
22303 VERROR_INT("xmlSchemaValidatorPopElem",
22304 "calling xmlNewText()");
22305 goto internal_error;
22306 } else
22307 xmlAddChild(inode->node, textChild);
22308 }
22309
22310 } else if (! INODE_NILLED(inode)) {
22311 /*
22312 * 5.2.1 The element information item must be ·valid· with respect
22313 * to the ·actual type definition· as defined by Element Locally
22314 * Valid (Type) (§3.3.4).
22315 */
22316 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22317 /*
22318 * SPEC (cvc-type) (3.1)
22319 * "If the type definition is a simple type definition, ..."
22320 * (3.1.3) "If clause 3.2 of Element Locally Valid
22321 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22322 * must be ·valid· with respect to the type definition as defined
22323 * by String Valid (§3.14.4).
22324 */
22325 ret = xmlSchemaVCheckINodeDataType(vctxt,
22326 inode, inode->typeDef, inode->value);
22327 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22328 /*
22329 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22330 * definition, then the element information item must be
22331 * ·valid· with respect to the type definition as per
22332 * Element Locally Valid (Complex Type) (§3.4.4);"
22333 *
22334 * SPEC (cvc-complex-type) (2.2)
22335 * "If the {content type} is a simple type definition, ...
22336 * the ·normalized value· of the element information item is
22337 * ·valid· with respect to that simple type definition as
22338 * defined by String Valid (§3.14.4)."
22339 */
22340 ret = xmlSchemaVCheckINodeDataType(vctxt,
22341 inode, inode->typeDef->contentTypeDef, inode->value);
22342 }
22343 if (ret != 0) {
22344 if (ret < 0) {
22345 VERROR_INT("xmlSchemaValidatorPopElem",
22346 "calling xmlSchemaVCheckCVCSimpleType()");
22347 goto internal_error;
22348 }
22349 goto end_elem;
22350 }
22351 /*
22352 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22353 * not applied, all of the following must be true:
22354 */
22355 if ((inode->decl->value != NULL) &&
22356 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22357
22358 /*
22359 * TODO: We will need a computed value, when comparison is
22360 * done on computed values.
22361 */
22362 /*
22363 * 5.2.2.1 The element information item must have no element
22364 * information item [children].
22365 */
22366 if (inode->flags &
22367 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22368 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22369 VERROR(ret, NULL,
22370 "The content must not containt element nodes since "
22371 "there is a fixed value constraint");
22372 goto end_elem;
22373 } else {
22374 /*
22375 * 5.2.2.2 The appropriate case among the following must
22376 * be true:
22377 */
22378 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22379 /*
22380 * 5.2.2.2.1 If the {content type} of the ·actual type
22381 * definition· is mixed, then the *initial value* of the
22382 * item must match the canonical lexical representation
22383 * of the {value constraint} value.
22384 *
22385 * ... the *initial value* of an element information
22386 * item is the string composed of, in order, the
22387 * [character code] of each character information item in
22388 * the [children] of that element information item.
22389 */
22390 if (! xmlStrEqual(inode->value, inode->decl->value)){
22391 /*
22392 * VAL TODO: Report invalid & expected values as well.
22393 * VAL TODO: Implement the canonical stuff.
22394 */
22395 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22396 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22397 ret, NULL, NULL,
22398 "The initial value '%s' does not match the fixed "
22399 "value constraint '%s'",
22400 inode->value, inode->decl->value);
22401 goto end_elem;
22402 }
22403 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22404 /*
22405 * 5.2.2.2.2 If the {content type} of the ·actual type
22406 * definition· is a simple type definition, then the
22407 * *actual value* of the item must match the canonical
22408 * lexical representation of the {value constraint} value.
22409 */
22410 /*
22411 * VAL TODO: *actual value* is the normalized value, impl.
22412 * this.
22413 * VAL TODO: Report invalid & expected values as well.
22414 * VAL TODO: Implement a comparison with the computed values.
22415 */
22416 if (! xmlStrEqual(inode->value,
22417 inode->decl->value)) {
22418 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22419 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22420 ret, NULL, NULL,
22421 "The actual value '%s' does not match the fixed "
22422 "value constraint '%s'",
22423 inode->value,
22424 inode->decl->value);
22425 goto end_elem;
22426 }
22427 }
22428 }
22429 }
22430 }
22431
22432end_elem:
22433 if (vctxt->depth < 0) {
22434 /* TODO: raise error? */
22435 return (0);
22436 }
22437 if (vctxt->depth == vctxt->skipDepth)
22438 vctxt->skipDepth = -1;
22439 /*
22440 * Evaluate the history of XPath state objects.
22441 */
22442 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22443 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022444 /*
22445 * TODO: 6 The element information item must be ·valid· with respect to each of
22446 * the {identity-constraint definitions} as per Identity-constraint
22447 * Satisfied (§3.11.4).
22448 */
22449 /*
22450 * Validate IDC keyrefs.
22451 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022452 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22453 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022454 /*
22455 * Merge/free the IDC table.
22456 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022457 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022458#ifdef DEBUG_IDC
22459 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022460 inode->nsName,
22461 inode->localName,
22462 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022463#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022464 if (vctxt->depth > 0) {
22465 /*
22466 * Merge the IDC node table with the table of the parent node.
22467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022468 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22469 goto internal_error;
22470 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022471 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022472 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022473 * Clear the current ielem.
22474 * VAL TODO: Don't free the PSVI IDC tables if they are
22475 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022476 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022477 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022478 /*
22479 * Skip further processing if we are on the validation root.
22480 */
22481 if (vctxt->depth == 0) {
22482 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022483 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022484 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022485 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022486 /*
22487 * Reset the bubbleDepth if needed.
22488 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022489 if (vctxt->aidcs != NULL) {
22490 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22491 do {
22492 if (aidc->bubbleDepth == vctxt->depth) {
22493 /*
22494 * A bubbleDepth of a key/unique IDC matches the current
22495 * depth, this means that we are leaving the scope of the
22496 * top-most keyref IDC.
22497 */
22498 aidc->bubbleDepth = -1;
22499 }
22500 aidc = aidc->next;
22501 } while (aidc != NULL);
22502 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022503 vctxt->depth--;
22504 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022506 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022507 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22508 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022509 return (ret);
22510
22511internal_error:
22512 vctxt->err = -1;
22513 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022514}
22515
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022516/*
22517* 3.4.4 Complex Type Definition Validation Rules
22518* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22519*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022520static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022521xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022522{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022523 xmlSchemaNodeInfoPtr pielem;
22524 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022525 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022526
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022527 if (vctxt->depth <= 0) {
22528 VERROR_INT("xmlSchemaValidateChildElem",
22529 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022530 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022531 }
22532 pielem = vctxt->elemInfos[vctxt->depth -1];
22533 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22534 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022535 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022536 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022538 if (INODE_NILLED(pielem)) {
22539 /*
22540 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22541 */
22542 ACTIVATE_PARENT_ELEM;
22543 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22544 VERROR(ret, NULL,
22545 "Neither character nor element content is allowed, "
22546 "because the element was 'nilled'");
22547 ACTIVATE_ELEM;
22548 goto unexpected_elem;
22549 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022550
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022551 ptype = pielem->typeDef;
22552
22553 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22554 /*
22555 * Workaround for "anyType": we have currently no content model
22556 * assigned for "anyType", so handle it explicitely.
22557 * "anyType" has an unbounded, lax "any" wildcard.
22558 */
22559 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22560 vctxt->inode->localName,
22561 vctxt->inode->nsName);
22562
22563 if (vctxt->inode->decl == NULL) {
22564 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022565 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022566 * Process "xsi:type".
22567 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022568 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022569 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22570 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22571 if (iattr != NULL) {
22572 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22573 &(vctxt->inode->typeDef), NULL);
22574 if (ret != 0) {
22575 if (ret == -1) {
22576 VERROR_INT("xmlSchemaValidateChildElem",
22577 "calling xmlSchemaProcessXSIType() to "
22578 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022579 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022580 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022581 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022583 } else {
22584 /*
22585 * Fallback to "anyType".
22586 *
22587 * SPEC (cvc-assess-elt)
22588 * "If the item cannot be ·strictly assessed·, [...]
22589 * an element information item's schema validity may be laxly
22590 * assessed if its ·context-determined declaration· is not
22591 * skip by ·validating· with respect to the ·ur-type
22592 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22593 */
22594 vctxt->inode->typeDef =
22595 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022596 }
22597 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022598 return (0);
22599 }
22600
22601 switch (ptype->contentType) {
22602 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022603 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022604 * SPEC (2.1) "If the {content type} is empty, then the
22605 * element information item has no character or element
22606 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022607 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022608 ACTIVATE_PARENT_ELEM
22609 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22610 VERROR(ret, NULL,
22611 "Element content is not allowed, "
22612 "because the content type is empty");
22613 ACTIVATE_ELEM
22614 goto unexpected_elem;
22615 break;
22616
22617 case XML_SCHEMA_CONTENT_MIXED:
22618 case XML_SCHEMA_CONTENT_ELEMENTS: {
22619 xmlRegExecCtxtPtr regexCtxt;
22620 xmlChar *values[10];
22621 int terminal, nbval = 10, nbneg;
22622
22623 /* VAL TODO: Optimized "anyType" validation.*/
22624
22625 if (ptype->contModel == NULL) {
22626 VERROR_INT("xmlSchemaValidateChildElem",
22627 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022628 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022629 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022630 /*
22631 * Safety belf for evaluation if the cont. model was already
22632 * examined to be invalid.
22633 */
22634 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22635 VERROR_INT("xmlSchemaValidateChildElem",
22636 "validating elem, but elem content is already invalid");
22637 return (-1);
22638 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022639
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022640 regexCtxt = pielem->regexCtxt;
22641 if (regexCtxt == NULL) {
22642 /*
22643 * Create the regex context.
22644 */
22645 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22646 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22647 vctxt);
22648 if (regexCtxt == NULL) {
22649 VERROR_INT("xmlSchemaValidateChildElem",
22650 "failed to create a regex context");
22651 return (-1);
22652 }
22653 pielem->regexCtxt = regexCtxt;
22654#ifdef DEBUG_AUTOMATA
22655 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22656 pielem->localName);
22657#endif
22658 }
22659
22660 /*
22661 * SPEC (2.4) "If the {content type} is element-only or mixed,
22662 * then the sequence of the element information item's
22663 * element information item [children], if any, taken in
22664 * order, is ·valid· with respect to the {content type}'s
22665 * particle, as defined in Element Sequence Locally Valid
22666 * (Particle) (§3.9.4)."
22667 */
22668 ret = xmlRegExecPushString2(regexCtxt,
22669 vctxt->inode->localName,
22670 vctxt->inode->nsName,
22671 vctxt->inode);
22672#ifdef DEBUG_AUTOMATA
22673 if (ret < 0)
22674 xmlGenericError(xmlGenericErrorContext,
22675 "AUTOMATON push ERROR for '%s' on '%s'\n",
22676 vctxt->inode->localName, pielem->localName);
22677 else
22678 xmlGenericError(xmlGenericErrorContext,
22679 "AUTOMATON push OK for '%s' on '%s'\n",
22680 vctxt->inode->localName, pielem->localName);
22681#endif
22682 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22683 VERROR_INT("xmlSchemaValidateChildElem",
22684 "calling xmlRegExecPushString2()");
22685 return (-1);
22686 }
22687 if (ret < 0) {
22688 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22689 &values[0], &terminal);
22690 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22691 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22692 "This element is not expected",
22693 nbval, nbneg, values);
22694 ret = vctxt->err;
22695 goto unexpected_elem;
22696 } else
22697 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022698 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022699 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022700 case XML_SCHEMA_CONTENT_SIMPLE:
22701 case XML_SCHEMA_CONTENT_BASIC:
22702 ACTIVATE_PARENT_ELEM
22703 if (IS_COMPLEX_TYPE(ptype)) {
22704 /*
22705 * SPEC (cvc-complex-type) (2.2)
22706 * "If the {content type} is a simple type definition, then
22707 * the element information item has no element information
22708 * item [children], ..."
22709 */
22710 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22711 VERROR(ret, NULL, "Element content is not allowed, "
22712 "because the content type is a simple type definition");
22713 } else {
22714 /*
22715 * SPEC (cvc-type) (3.1.2) "The element information item must
22716 * have no element information item [children]."
22717 */
22718 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22719 VERROR(ret, NULL, "Element content is not allowed, "
22720 "because the type definition is simple");
22721 }
22722 ACTIVATE_ELEM
22723 ret = vctxt->err;
22724 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022725 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022726
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022727 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022728 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022729 }
22730 return (ret);
22731unexpected_elem:
22732 /*
22733 * Pop this element and set the skipDepth to skip
22734 * all further content of the parent element.
22735 */
22736 vctxt->skipDepth = vctxt->depth;
22737 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22738 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22739 return (ret);
22740}
22741
22742#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22743#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22744#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22745
22746static int
22747xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22748 int nodeType, const xmlChar *value, int len,
22749 int mode, int *consumed)
22750{
22751 /*
22752 * Unfortunately we have to duplicate the text sometimes.
22753 * OPTIMIZE: Maybe we could skip it, if:
22754 * 1. content type is simple
22755 * 2. whitespace is "collapse"
22756 * 3. it consists of whitespace only
22757 *
22758 * Process character content.
22759 */
22760 if (consumed != NULL)
22761 *consumed = 0;
22762 if (INODE_NILLED(vctxt->inode)) {
22763 /*
22764 * SPEC cvc-elt (3.3.4 - 3.2.1)
22765 * "The element information item must have no character or
22766 * element information item [children]."
22767 */
22768 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22769 "Neither character nor element content is allowed "
22770 "because the element is 'nilled'");
22771 return (vctxt->err);
22772 }
22773 /*
22774 * SPEC (2.1) "If the {content type} is empty, then the
22775 * element information item has no character or element
22776 * information item [children]."
22777 */
22778 if (vctxt->inode->typeDef->contentType ==
22779 XML_SCHEMA_CONTENT_EMPTY) {
22780 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22781 "Character content is not allowed, "
22782 "because the content type is empty");
22783 return (vctxt->err);
22784 }
22785
22786 if (vctxt->inode->typeDef->contentType ==
22787 XML_SCHEMA_CONTENT_ELEMENTS) {
22788 if ((nodeType != XML_TEXT_NODE) ||
22789 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22790 /*
22791 * SPEC cvc-complex-type (2.3)
22792 * "If the {content type} is element-only, then the
22793 * element information item has no character information
22794 * item [children] other than those whose [character
22795 * code] is defined as a white space in [XML 1.0 (Second
22796 * Edition)]."
22797 */
22798 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22799 "Character content other than whitespace is not allowed "
22800 "because the content type is 'element-only'");
22801 return (vctxt->err);
22802 }
22803 return (0);
22804 }
22805
22806 if ((value == NULL) || (value[0] == 0))
22807 return (0);
22808 /*
22809 * Save the value.
22810 * NOTE that even if the content type is *mixed*, we need the
22811 * *initial value* for default/fixed value constraints.
22812 */
22813 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22814 ((vctxt->inode->decl == NULL) ||
22815 (vctxt->inode->decl->value == NULL)))
22816 return (0);
22817
22818 if (vctxt->inode->value == NULL) {
22819 /*
22820 * Set the value.
22821 */
22822 switch (mode) {
22823 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22824 /*
22825 * When working on a tree.
22826 */
22827 vctxt->inode->value = value;
22828 break;
22829 case XML_SCHEMA_PUSH_TEXT_CREATED:
22830 /*
22831 * When working with the reader.
22832 * The value will be freed by the element info.
22833 */
22834 vctxt->inode->value = value;
22835 if (consumed != NULL)
22836 *consumed = 1;
22837 vctxt->inode->flags |=
22838 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22839 break;
22840 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22841 /*
22842 * When working with SAX.
22843 * The value will be freed by the element info.
22844 */
22845 if (len != -1)
22846 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22847 else
22848 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22849 vctxt->inode->flags |=
22850 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22851 break;
22852 default:
22853 break;
22854 }
22855 } else {
22856 /*
22857 * Concat the value.
22858 */
22859 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022860 vctxt->inode->value = BAD_CAST xmlStrncat(
22861 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022862 } else {
22863 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022864 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022865 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22866 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022867 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022868
22869 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022870}
22871
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022872static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022873xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022874{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022875 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022876
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022877 if ((vctxt->skipDepth != -1) &&
22878 (vctxt->depth >= vctxt->skipDepth)) {
22879 VERROR_INT("xmlSchemaValidateElem",
22880 "in skip-state");
22881 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022882 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022883 if (vctxt->xsiAssemble) {
22884 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22885 goto internal_error;
22886 }
22887 if (vctxt->depth > 0) {
22888 /*
22889 * Validate this element against the content model
22890 * of the parent.
22891 */
22892 ret = xmlSchemaValidateChildElem(vctxt);
22893 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022894 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022895 VERROR_INT("xmlSchemaValidateElem",
22896 "calling xmlSchemaStreamValidateChildElement()");
22897 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022898 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022899 goto exit;
22900 }
22901 if (vctxt->depth == vctxt->skipDepth)
22902 goto exit;
22903 if ((vctxt->inode->decl == NULL) &&
22904 (vctxt->inode->typeDef == NULL)) {
22905 VERROR_INT("xmlSchemaValidateElem",
22906 "the child element was valid but neither the "
22907 "declaration nor the type was set");
22908 goto internal_error;
22909 }
22910 } else {
22911 /*
22912 * Get the declaration of the validation root.
22913 */
22914 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22915 vctxt->inode->localName,
22916 vctxt->inode->nsName);
22917 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022918 ret = XML_SCHEMAV_CVC_ELT_1;
22919 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022920 "No matching global declaration available "
22921 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022922 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022923 }
22924 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022925
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022926 if (vctxt->inode->decl == NULL)
22927 goto type_validation;
22928
22929 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22930 int skip;
22931 /*
22932 * Wildcards.
22933 */
22934 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22935 if (ret != 0) {
22936 if (ret < 0) {
22937 VERROR_INT("xmlSchemaValidateElem",
22938 "calling xmlSchemaValidateElemWildcard()");
22939 goto internal_error;
22940 }
22941 goto exit;
22942 }
22943 if (skip) {
22944 vctxt->skipDepth = vctxt->depth;
22945 goto exit;
22946 }
22947 /*
22948 * The declaration might be set by the wildcard validation,
22949 * when the processContents is "lax" or "strict".
22950 */
22951 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22952 /*
22953 * Clear the "decl" field to not confuse further processing.
22954 */
22955 vctxt->inode->decl = NULL;
22956 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022957 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022958 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022959 /*
22960 * Validate against the declaration.
22961 */
22962 ret = xmlSchemaValidateElemDecl(vctxt);
22963 if (ret != 0) {
22964 if (ret < 0) {
22965 VERROR_INT("xmlSchemaValidateElem",
22966 "calling xmlSchemaValidateElemDecl()");
22967 goto internal_error;
22968 }
22969 goto exit;
22970 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022971 /*
22972 * Validate against the type definition.
22973 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022974type_validation:
22975
22976 if (vctxt->inode->typeDef == NULL) {
22977 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22978 ret = XML_SCHEMAV_CVC_TYPE_1;
22979 VERROR(ret, NULL,
22980 "The type definition is absent");
22981 goto exit;
22982 }
22983 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22984 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22985 ret = XML_SCHEMAV_CVC_TYPE_2;
22986 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022987 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022988 goto exit;
22989 }
22990 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022991 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022992 * during validation against the declaration. This must be done
22993 * _before_ attribute validation.
22994 */
22995 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22996 if (ret == -1) {
22997 VERROR_INT("xmlSchemaValidateElem",
22998 "calling xmlSchemaXPathEvaluate()");
22999 goto internal_error;
23000 }
23001 /*
23002 * Validate attributes.
23003 */
23004 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
23005 if ((vctxt->nbAttrInfos != 0) ||
23006 (vctxt->inode->typeDef->attributeUses != NULL)) {
23007
23008 ret = xmlSchemaVAttributesComplex(vctxt);
23009 }
23010 } else if (vctxt->nbAttrInfos != 0) {
23011
23012 ret = xmlSchemaVAttributesSimple(vctxt);
23013 }
23014 /*
23015 * Clear registered attributes.
23016 */
23017 if (vctxt->nbAttrInfos != 0)
23018 xmlSchemaClearAttrInfos(vctxt);
23019 if (ret == -1) {
23020 VERROR_INT("xmlSchemaValidateElem",
23021 "calling attributes validation");
23022 goto internal_error;
23023 }
23024 /*
23025 * Don't return an error if attributes are invalid on purpose.
23026 */
23027 ret = 0;
23028
23029exit:
23030 if (ret != 0)
23031 vctxt->skipDepth = vctxt->depth;
23032 return (ret);
23033internal_error:
23034 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023035}
23036
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023037#ifdef XML_SCHEMA_READER_ENABLED
23038static int
23039xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023040{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023041 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23042 int depth, nodeType, ret = 0, consumed;
23043 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023044
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023045 vctxt->depth = -1;
23046 ret = xmlTextReaderRead(vctxt->reader);
23047 /*
23048 * Move to the document element.
23049 */
23050 while (ret == 1) {
23051 nodeType = xmlTextReaderNodeType(vctxt->reader);
23052 if (nodeType == XML_ELEMENT_NODE)
23053 goto root_found;
23054 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023055 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023056 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023057
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023058root_found:
23059
23060 do {
23061 depth = xmlTextReaderDepth(vctxt->reader);
23062 nodeType = xmlTextReaderNodeType(vctxt->reader);
23063
23064 if (nodeType == XML_ELEMENT_NODE) {
23065
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023066 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023067 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23068 VERROR_INT("xmlSchemaVReaderWalk",
23069 "calling xmlSchemaValidatorPushElem()");
23070 goto internal_error;
23071 }
23072 ielem = vctxt->inode;
23073 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23074 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23075 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23076 /*
23077 * Is the element empty?
23078 */
23079 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23080 if (ret == -1) {
23081 VERROR_INT("xmlSchemaVReaderWalk",
23082 "calling xmlTextReaderIsEmptyElement()");
23083 goto internal_error;
23084 }
23085 if (ret) {
23086 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23087 }
23088 /*
23089 * Register attributes.
23090 */
23091 vctxt->nbAttrInfos = 0;
23092 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23093 if (ret == -1) {
23094 VERROR_INT("xmlSchemaVReaderWalk",
23095 "calling xmlTextReaderMoveToFirstAttribute()");
23096 goto internal_error;
23097 }
23098 if (ret == 1) {
23099 do {
23100 /*
23101 * VAL TODO: How do we know that the reader works on a
23102 * node tree, to be able to pass a node here?
23103 */
23104 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23105 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23106 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23107 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23108
23109 VERROR_INT("xmlSchemaVReaderWalk",
23110 "calling xmlSchemaValidatorPushAttribute()");
23111 goto internal_error;
23112 }
23113 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23114 if (ret == -1) {
23115 VERROR_INT("xmlSchemaVReaderWalk",
23116 "calling xmlTextReaderMoveToFirstAttribute()");
23117 goto internal_error;
23118 }
23119 } while (ret == 1);
23120 /*
23121 * Back to element position.
23122 */
23123 ret = xmlTextReaderMoveToElement(vctxt->reader);
23124 if (ret == -1) {
23125 VERROR_INT("xmlSchemaVReaderWalk",
23126 "calling xmlTextReaderMoveToElement()");
23127 goto internal_error;
23128 }
23129 }
23130 /*
23131 * Validate the element.
23132 */
23133 ret= xmlSchemaValidateElem(vctxt);
23134 if (ret != 0) {
23135 if (ret == -1) {
23136 VERROR_INT("xmlSchemaVReaderWalk",
23137 "calling xmlSchemaValidateElem()");
23138 goto internal_error;
23139 }
23140 goto exit;
23141 }
23142 if (vctxt->depth == vctxt->skipDepth) {
23143 int curDepth;
23144 /*
23145 * Skip all content.
23146 */
23147 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23148 ret = xmlTextReaderRead(vctxt->reader);
23149 curDepth = xmlTextReaderDepth(vctxt->reader);
23150 while ((ret == 1) && (curDepth != depth)) {
23151 ret = xmlTextReaderRead(vctxt->reader);
23152 curDepth = xmlTextReaderDepth(vctxt->reader);
23153 }
23154 if (ret < 0) {
23155 /*
23156 * VAL TODO: A reader error occured; what to do here?
23157 */
23158 ret = 1;
23159 goto exit;
23160 }
23161 }
23162 goto leave_elem;
23163 }
23164 /*
23165 * READER VAL TODO: Is an END_ELEM really never called
23166 * if the elem is empty?
23167 */
23168 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23169 goto leave_elem;
23170 } else if (nodeType == END_ELEM) {
23171 /*
23172 * Process END of element.
23173 */
23174leave_elem:
23175 ret = xmlSchemaValidatorPopElem(vctxt);
23176 if (ret != 0) {
23177 if (ret < 0) {
23178 VERROR_INT("xmlSchemaVReaderWalk",
23179 "calling xmlSchemaValidatorPopElem()");
23180 goto internal_error;
23181 }
23182 goto exit;
23183 }
23184 if (vctxt->depth >= 0)
23185 ielem = vctxt->inode;
23186 else
23187 ielem = NULL;
23188 } else if ((nodeType == XML_TEXT_NODE) ||
23189 (nodeType == XML_CDATA_SECTION_NODE) ||
23190 (nodeType == WHTSP) ||
23191 (nodeType == SIGN_WHTSP)) {
23192 /*
23193 * Process character content.
23194 */
23195 xmlChar *value;
23196
23197 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23198 nodeType = XML_TEXT_NODE;
23199
23200 value = xmlTextReaderValue(vctxt->reader);
23201 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23202 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23203 if (! consumed)
23204 xmlFree(value);
23205 if (ret == -1) {
23206 VERROR_INT("xmlSchemaVReaderWalk",
23207 "calling xmlSchemaVPushText()");
23208 goto internal_error;
23209 }
23210 } else if ((nodeType == XML_ENTITY_NODE) ||
23211 (nodeType == XML_ENTITY_REF_NODE)) {
23212 /*
23213 * VAL TODO: What to do with entities?
23214 */
23215 TODO
23216 }
23217 /*
23218 * Read next node.
23219 */
23220 ret = xmlTextReaderRead(vctxt->reader);
23221 } while (ret == 1);
23222
23223exit:
23224 return (ret);
23225internal_error:
23226 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023227}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023228#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023229
23230/************************************************************************
23231 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023232 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023233 * *
23234 ************************************************************************/
23235
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023236#ifdef XML_SCHEMA_SAX_ENABLED
23237/*
23238* Process text content.
23239*/
23240static void
23241xmlSchemaSAXHandleText(void *ctx,
23242 const xmlChar * ch,
23243 int len)
23244{
23245 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23246
23247 if (vctxt->depth < 0)
23248 return;
23249 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23250 return;
23251 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23252 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23253 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23254 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23255 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23256 "calling xmlSchemaVPushText()");
23257 vctxt->err = -1;
23258 xmlStopParser(vctxt->parserCtxt);
23259 }
23260}
23261
23262/*
23263* Process CDATA content.
23264*/
23265static void
23266xmlSchemaSAXHandleCDataSection(void *ctx,
23267 const xmlChar * ch,
23268 int len)
23269{
23270 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23271
23272 if (vctxt->depth < 0)
23273 return;
23274 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23275 return;
23276 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23277 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23278 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23279 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23280 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23281 "calling xmlSchemaVPushText()");
23282 vctxt->err = -1;
23283 xmlStopParser(vctxt->parserCtxt);
23284 }
23285}
23286
23287static void
23288xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23289 const xmlChar * name ATTRIBUTE_UNUSED)
23290{
23291 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23292
23293 if (vctxt->depth < 0)
23294 return;
23295 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23296 return;
23297 /* SAX VAL TODO: What to do here? */
23298 TODO
23299}
23300
23301static void
23302xmlSchemaSAXHandleStartElementNs(void *ctx,
23303 const xmlChar * localname,
23304 const xmlChar * prefix ATTRIBUTE_UNUSED,
23305 const xmlChar * URI,
23306 int nb_namespaces,
23307 const xmlChar ** namespaces,
23308 int nb_attributes,
23309 int nb_defaulted ATTRIBUTE_UNUSED,
23310 const xmlChar ** attributes)
23311{
23312 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23313 int ret;
23314 xmlSchemaNodeInfoPtr ielem;
23315 int i, j;
23316
23317 /*
23318 * SAX VAL TODO: What to do with nb_defaulted?
23319 */
23320 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023321 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023322 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023323 vctxt->depth++;
23324 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023325 return;
23326 /*
23327 * Push the element.
23328 */
23329 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23330 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23331 "calling xmlSchemaValidatorPushElem()");
23332 goto internal_error;
23333 }
23334 ielem = vctxt->inode;
23335 ielem->localName = localname;
23336 ielem->nsName = URI;
23337 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23338 /*
23339 * Register namespaces on the elem info.
23340 */
23341 if (nb_namespaces != 0) {
23342 /*
23343 * Although the parser builds its own namespace list,
23344 * we have no access to it, so we'll use an own one.
23345 */
23346 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23347 /*
23348 * Store prefix and namespace name.
23349 */
23350 if (ielem->nsBindings == NULL) {
23351 ielem->nsBindings =
23352 (const xmlChar **) xmlMalloc(10 *
23353 sizeof(const xmlChar *));
23354 if (ielem->nsBindings == NULL) {
23355 xmlSchemaVErrMemory(vctxt,
23356 "allocating namespace bindings for SAX validation",
23357 NULL);
23358 goto internal_error;
23359 }
23360 ielem->nbNsBindings = 0;
23361 ielem->sizeNsBindings = 5;
23362 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23363 ielem->sizeNsBindings *= 2;
23364 ielem->nsBindings =
23365 (const xmlChar **) xmlRealloc(
23366 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023367 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023368 if (ielem->nsBindings == NULL) {
23369 xmlSchemaVErrMemory(vctxt,
23370 "re-allocating namespace bindings for SAX validation",
23371 NULL);
23372 goto internal_error;
23373 }
23374 }
23375
23376 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23377 if (namespaces[j+1][0] == 0) {
23378 /*
23379 * Handle xmlns="".
23380 */
23381 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23382 } else
23383 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23384 namespaces[j+1];
23385 ielem->nbNsBindings++;
23386 }
23387 }
23388 /*
23389 * Register attributes.
23390 * SAX VAL TODO: We are not adding namespace declaration
23391 * attributes yet.
23392 */
23393 if (nb_attributes != 0) {
23394 xmlChar *value;
23395
23396 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23397 /*
23398 * Duplicate the value.
23399 */
23400 value = xmlStrndup(attributes[j+3],
23401 attributes[j+4] - attributes[j+3]);
23402 ret = xmlSchemaValidatorPushAttribute(vctxt,
23403 NULL, attributes[j], attributes[j+2], 0,
23404 value, 1);
23405 if (ret == -1) {
23406 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23407 "calling xmlSchemaValidatorPushAttribute()");
23408 goto internal_error;
23409 }
23410 }
23411 }
23412 /*
23413 * Validate the element.
23414 */
23415 ret = xmlSchemaValidateElem(vctxt);
23416 if (ret != 0) {
23417 if (ret == -1) {
23418 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23419 "calling xmlSchemaValidateElem()");
23420 goto internal_error;
23421 }
23422 goto exit;
23423 }
23424
23425exit:
23426 return;
23427internal_error:
23428 vctxt->err = -1;
23429 xmlStopParser(vctxt->parserCtxt);
23430 return;
23431}
23432
23433static void
23434xmlSchemaSAXHandleEndElementNs(void *ctx,
23435 const xmlChar * localname ATTRIBUTE_UNUSED,
23436 const xmlChar * prefix ATTRIBUTE_UNUSED,
23437 const xmlChar * URI ATTRIBUTE_UNUSED)
23438{
23439 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23440 int res;
23441
23442 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023443 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023444 */
23445 if (vctxt->skipDepth != -1) {
23446 if (vctxt->depth > vctxt->skipDepth) {
23447 vctxt->depth--;
23448 return;
23449 } else
23450 vctxt->skipDepth = -1;
23451 }
23452 /*
23453 * SAX VAL TODO: Just a temporary check.
23454 */
23455 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23456 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23457 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23458 "elem pop mismatch");
23459 }
23460 res = xmlSchemaValidatorPopElem(vctxt);
23461 if (res != 0) {
23462 if (res < 0) {
23463 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23464 "calling xmlSchemaValidatorPopElem()");
23465 goto internal_error;
23466 }
23467 goto exit;
23468 }
23469exit:
23470 return;
23471internal_error:
23472 vctxt->err = -1;
23473 xmlStopParser(vctxt->parserCtxt);
23474 return;
23475}
23476#endif
23477
Daniel Veillard4255d502002-04-16 15:50:10 +000023478/************************************************************************
23479 * *
23480 * Validation interfaces *
23481 * *
23482 ************************************************************************/
23483
23484/**
23485 * xmlSchemaNewValidCtxt:
23486 * @schema: a precompiled XML Schemas
23487 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023488 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023489 *
23490 * Returns the validation context or NULL in case of error
23491 */
23492xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023493xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23494{
Daniel Veillard4255d502002-04-16 15:50:10 +000023495 xmlSchemaValidCtxtPtr ret;
23496
23497 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23498 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023499 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023500 return (NULL);
23501 }
23502 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023503 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23504 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023505 return (ret);
23506}
23507
23508/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023509 * xmlSchemaClearValidCtxt:
23510 * @ctxt: the schema validation context
23511 *
23512 * Free the resources associated to the schema validation context;
23513 * leaves some fields alive intended for reuse of the context.
23514 */
23515static void
23516xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23517{
23518 if (vctxt == NULL)
23519 return;
23520
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023521 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023522 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023523 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023524#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023525 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023526#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023527 if (vctxt->value != NULL) {
23528 xmlSchemaFreeValue(vctxt->value);
23529 vctxt->value = NULL;
23530 }
23531 /*
23532 * Augmented IDC information.
23533 */
23534 if (vctxt->aidcs != NULL) {
23535 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23536 do {
23537 next = cur->next;
23538 xmlFree(cur);
23539 cur = next;
23540 } while (cur != NULL);
23541 vctxt->aidcs = NULL;
23542 }
23543 if (vctxt->idcNodes != NULL) {
23544 int i;
23545 xmlSchemaPSVIIDCNodePtr item;
23546
23547 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023548 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023549 xmlFree(item->keys);
23550 xmlFree(item);
23551 }
23552 xmlFree(vctxt->idcNodes);
23553 vctxt->idcNodes = NULL;
23554 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023555 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023556 * Note that we won't delete the XPath state pool here.
23557 */
23558 if (vctxt->xpathStates != NULL) {
23559 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23560 vctxt->xpathStates = NULL;
23561 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023562 /*
23563 * Attribute info.
23564 */
23565 if (vctxt->nbAttrInfos != 0) {
23566 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023567 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023568 /*
23569 * Element info.
23570 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023571 if (vctxt->elemInfos != NULL) {
23572 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023573 xmlSchemaNodeInfoPtr ei;
23574
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023575 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023576 ei = vctxt->elemInfos[i];
23577 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023578 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023579 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023580 }
23581 }
23582}
23583
23584/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023585 * xmlSchemaFreeValidCtxt:
23586 * @ctxt: the schema validation context
23587 *
23588 * Free the resources associated to the schema validation context
23589 */
23590void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023591xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23592{
Daniel Veillard4255d502002-04-16 15:50:10 +000023593 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023594 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023595 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023596 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023597 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023598 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023599 if (ctxt->idcNodes != NULL) {
23600 int i;
23601 xmlSchemaPSVIIDCNodePtr item;
23602
23603 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023604 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023605 xmlFree(item->keys);
23606 xmlFree(item);
23607 }
23608 xmlFree(ctxt->idcNodes);
23609 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023610 if (ctxt->idcKeys != NULL) {
23611 int i;
23612 for (i = 0; i < ctxt->nbIdcKeys; i++)
23613 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23614 xmlFree(ctxt->idcKeys);
23615 }
23616
23617 if (ctxt->xpathStates != NULL)
23618 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23619 if (ctxt->xpathStatePool != NULL)
23620 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23621
23622 /*
23623 * Augmented IDC information.
23624 */
23625 if (ctxt->aidcs != NULL) {
23626 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23627 do {
23628 next = cur->next;
23629 xmlFree(cur);
23630 cur = next;
23631 } while (cur != NULL);
23632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023633 if (ctxt->attrInfos != NULL) {
23634 int i;
23635 xmlSchemaAttrInfoPtr attr;
23636
23637 /* Just a paranoid call to the cleanup. */
23638 if (ctxt->nbAttrInfos != 0)
23639 xmlSchemaClearAttrInfos(ctxt);
23640 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23641 attr = ctxt->attrInfos[i];
23642 xmlFree(attr);
23643 }
23644 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023645 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023646 if (ctxt->elemInfos != NULL) {
23647 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023648 xmlSchemaNodeInfoPtr ei;
23649
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023650 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023651 ei = ctxt->elemInfos[i];
23652 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023653 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023654 xmlSchemaClearElemInfo(ei);
23655 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023656 }
23657 xmlFree(ctxt->elemInfos);
23658 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023659 if (ctxt->dict != NULL)
23660 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023661 xmlFree(ctxt);
23662}
23663
23664/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023665 * xmlSchemaIsValid:
23666 * @ctxt: the schema validation context
23667 *
23668 * Check if any error was detected during validation.
23669 *
23670 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23671 * of internal error.
23672 */
23673int
23674xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23675{
23676 if (ctxt == NULL)
23677 return(-1);
23678 return(ctxt->err == 0);
23679}
23680
23681/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023682 * xmlSchemaSetValidErrors:
23683 * @ctxt: a schema validation context
23684 * @err: the error function
23685 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023686 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023687 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023688 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023689 */
23690void
23691xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023692 xmlSchemaValidityErrorFunc err,
23693 xmlSchemaValidityWarningFunc warn, void *ctx)
23694{
Daniel Veillard4255d502002-04-16 15:50:10 +000023695 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023696 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023697 ctxt->error = err;
23698 ctxt->warning = warn;
23699 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023700 if (ctxt->pctxt != NULL)
23701 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023702}
23703
23704/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023705 * xmlSchemaSetValidStructuredErrors:
23706 * @ctxt: a schema validation context
23707 * @serror: the structured error function
23708 * @ctx: the functions context
23709 *
23710 * Set the structured error callback
23711 */
23712void
23713xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23714 xmlStructuredErrorFunc serror, void *ctx)
23715{
23716 if (ctxt == NULL)
23717 return;
23718 ctxt->serror = serror;
23719 ctxt->error = NULL;
23720 ctxt->warning = NULL;
23721 ctxt->userData = ctx;
23722}
23723
23724/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023725 * xmlSchemaGetValidErrors:
23726 * @ctxt: a XML-Schema validation context
23727 * @err: the error function result
23728 * @warn: the warning function result
23729 * @ctx: the functions context result
23730 *
23731 * Get the error and warning callback informations
23732 *
23733 * Returns -1 in case of error and 0 otherwise
23734 */
23735int
23736xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23737 xmlSchemaValidityErrorFunc * err,
23738 xmlSchemaValidityWarningFunc * warn, void **ctx)
23739{
23740 if (ctxt == NULL)
23741 return (-1);
23742 if (err != NULL)
23743 *err = ctxt->error;
23744 if (warn != NULL)
23745 *warn = ctxt->warning;
23746 if (ctx != NULL)
23747 *ctx = ctxt->userData;
23748 return (0);
23749}
23750
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023751
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023752/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023753 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023754 * @ctxt: a schema validation context
23755 * @options: a combination of xmlSchemaValidOption
23756 *
23757 * Sets the options to be used during the validation.
23758 *
23759 * Returns 0 in case of success, -1 in case of an
23760 * API error.
23761 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023762int
23763xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23764 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023765
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023766{
23767 int i;
23768
23769 if (ctxt == NULL)
23770 return (-1);
23771 /*
23772 * WARNING: Change the start value if adding to the
23773 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023774 * TODO: Is there an other, more easy to maintain,
23775 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023776 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023777 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023778 if (options & 1<<i)
23779 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023780 }
23781 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023782 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023783}
23784
23785/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023786 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023787 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023788 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023789 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023790 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023791 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023792 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023793int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023794xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023795
23796{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023797 if (ctxt == NULL)
23798 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023799 else
23800 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023801}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023802
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023803static int
23804xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23805{
23806 xmlAttrPtr attr;
23807 int ret = 0;
23808 xmlSchemaNodeInfoPtr ielem = NULL;
23809 xmlNodePtr node, valRoot;
23810 const xmlChar *nsName;
23811
23812 /* DOC VAL TODO: Move this to the start function. */
23813 valRoot = xmlDocGetRootElement(vctxt->doc);
23814 if (valRoot == NULL) {
23815 /* VAL TODO: Error code? */
23816 VERROR(1, NULL, "The document has no document element");
23817 return (1);
23818 }
23819 vctxt->depth = -1;
23820 vctxt->validationRoot = valRoot;
23821 node = valRoot;
23822 while (node != NULL) {
23823 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23824 goto next_sibling;
23825 if (node->type == XML_ELEMENT_NODE) {
23826
23827 /*
23828 * Init the node-info.
23829 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023830 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023831 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23832 goto internal_error;
23833 ielem = vctxt->inode;
23834 ielem->node = node;
23835 ielem->localName = node->name;
23836 if (node->ns != NULL)
23837 ielem->nsName = node->ns->href;
23838 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23839 /*
23840 * Register attributes.
23841 * DOC VAL TODO: We do not register namespace declaration
23842 * attributes yet.
23843 */
23844 vctxt->nbAttrInfos = 0;
23845 if (node->properties != NULL) {
23846 attr = node->properties;
23847 do {
23848 if (attr->ns != NULL)
23849 nsName = attr->ns->href;
23850 else
23851 nsName = NULL;
23852 ret = xmlSchemaValidatorPushAttribute(vctxt,
23853 (xmlNodePtr) attr,
23854 attr->name, nsName, 0,
23855 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23856 if (ret == -1) {
23857 VERROR_INT("xmlSchemaDocWalk",
23858 "calling xmlSchemaValidatorPushAttribute()");
23859 goto internal_error;
23860 }
23861 attr = attr->next;
23862 } while (attr);
23863 }
23864 /*
23865 * Validate the element.
23866 */
23867 ret = xmlSchemaValidateElem(vctxt);
23868 if (ret != 0) {
23869 if (ret == -1) {
23870 VERROR_INT("xmlSchemaDocWalk",
23871 "calling xmlSchemaValidateElem()");
23872 goto internal_error;
23873 }
23874 /*
23875 * Don't stop validation; just skip the content
23876 * of this element.
23877 */
23878 goto leave_node;
23879 }
23880 if ((vctxt->skipDepth != -1) &&
23881 (vctxt->depth >= vctxt->skipDepth))
23882 goto leave_node;
23883 } else if ((node->type == XML_TEXT_NODE) ||
23884 (node->type == XML_CDATA_SECTION_NODE)) {
23885 /*
23886 * Process character content.
23887 */
23888 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23889 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23890 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23891 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23892 if (ret < 0) {
23893 VERROR_INT("xmlSchemaVDocWalk",
23894 "calling xmlSchemaVPushText()");
23895 goto internal_error;
23896 }
23897 /*
23898 * DOC VAL TODO: Should we skip further validation of the
23899 * element content here?
23900 */
23901 } else if ((node->type == XML_ENTITY_NODE) ||
23902 (node->type == XML_ENTITY_REF_NODE)) {
23903 /*
23904 * DOC VAL TODO: What to do with entities?
23905 */
23906 TODO
23907 } else {
23908 goto leave_node;
23909 /*
23910 * DOC VAL TODO: XInclude nodes, etc.
23911 */
23912 }
23913 /*
23914 * Walk the doc.
23915 */
23916 if (node->children != NULL) {
23917 node = node->children;
23918 continue;
23919 }
23920leave_node:
23921 if (node->type == XML_ELEMENT_NODE) {
23922 /*
23923 * Leaving the scope of an element.
23924 */
23925 if (node != vctxt->inode->node) {
23926 VERROR_INT("xmlSchemaVDocWalk",
23927 "element position mismatch");
23928 goto internal_error;
23929 }
23930 ret = xmlSchemaValidatorPopElem(vctxt);
23931 if (ret != 0) {
23932 if (ret < 0) {
23933 VERROR_INT("xmlSchemaVDocWalk",
23934 "calling xmlSchemaValidatorPopElem()");
23935 goto internal_error;
23936 }
23937 }
23938 if (node == valRoot)
23939 goto exit;
23940 }
23941next_sibling:
23942 if (node->next != NULL)
23943 node = node->next;
23944 else {
23945 node = node->parent;
23946 goto leave_node;
23947 }
23948 }
23949
23950exit:
23951 return (ret);
23952internal_error:
23953 return (-1);
23954}
23955
23956static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023957xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023958 /*
23959 * Some initialization.
23960 */
23961 vctxt->err = 0;
23962 vctxt->nberrors = 0;
23963 vctxt->depth = -1;
23964 vctxt->skipDepth = -1;
23965 /*
23966 * Create a schema + parser if necessary.
23967 */
23968 if (vctxt->schema == NULL) {
23969
23970 if ((vctxt->pctxt == NULL) &&
23971 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23972 return (-1);
23973
23974 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23975 if (vctxt->schema == NULL) {
23976 VERROR_INT("xmlSchemaVStartValidation",
23977 "creating a schema");
23978 return (-1);
23979 }
23980 vctxt->xsiAssemble = 1;
23981 } else
23982 vctxt->xsiAssemble = 0;
23983 /*
23984 * Augment the IDC definitions.
23985 */
23986 if (vctxt->schema->idcDef != NULL) {
23987 xmlHashScan(vctxt->schema->idcDef,
23988 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23989 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023990 return(0);
23991}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023992
Daniel Veillardf10ae122005-07-10 19:03:16 +000023993static void
23994xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023995 if (vctxt->xsiAssemble) {
23996 if (vctxt->schema != NULL) {
23997 xmlSchemaFree(vctxt->schema);
23998 vctxt->schema = NULL;
23999 }
24000 }
24001 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024002}
24003
24004static int
24005xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
24006{
24007 int ret = 0;
24008
24009 if (xmlSchemaPreRun(vctxt) < 0)
24010 return(-1);
24011
24012 if (vctxt->doc != NULL) {
24013 /*
24014 * Tree validation.
24015 */
24016 ret = xmlSchemaVDocWalk(vctxt);
24017#ifdef LIBXML_READER_ENABLED
24018 } else if (vctxt->reader != NULL) {
24019 /*
24020 * XML Reader validation.
24021 */
24022#ifdef XML_SCHEMA_READER_ENABLED
24023 ret = xmlSchemaVReaderWalk(vctxt);
24024#endif
24025#endif
24026 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24027 /*
24028 * SAX validation.
24029 */
24030 ret = xmlParseDocument(vctxt->parserCtxt);
24031 } else {
24032 VERROR_INT("xmlSchemaVStartValidation",
24033 "no instance to validate");
24034 ret = -1;
24035 }
24036
24037 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024038 if (ret == 0)
24039 ret = vctxt->err;
24040 return (ret);
24041}
24042
24043/**
24044 * xmlSchemaValidateOneElement:
24045 * @ctxt: a schema validation context
24046 * @elem: an element node
24047 *
24048 * Validate a branch of a tree, starting with the given @elem.
24049 *
24050 * Returns 0 if the element and its subtree is valid, a positive error
24051 * code number otherwise and -1 in case of an internal or API error.
24052 */
24053int
24054xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24055{
24056 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24057 return (-1);
24058
24059 if (ctxt->schema == NULL)
24060 return (-1);
24061
24062 ctxt->doc = elem->doc;
24063 ctxt->node = elem;
24064 ctxt->validationRoot = elem;
24065 return(xmlSchemaVStart(ctxt));
24066}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024067
Daniel Veillard259f0df2004-08-18 09:13:18 +000024068/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024069 * xmlSchemaValidateDoc:
24070 * @ctxt: a schema validation context
24071 * @doc: a parsed document tree
24072 *
24073 * Validate a document tree in memory.
24074 *
24075 * Returns 0 if the document is schemas valid, a positive error code
24076 * number otherwise and -1 in case of internal or API error.
24077 */
24078int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024079xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24080{
Daniel Veillard4255d502002-04-16 15:50:10 +000024081 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024082 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024083
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024084 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024085 ctxt->node = xmlDocGetRootElement(doc);
24086 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024087 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024088 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24089 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024090 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024091 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024092 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024093 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024094 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024095}
24096
Daniel Veillardcdc82732005-07-08 15:04:06 +000024097
24098/************************************************************************
24099 * *
24100 * Function and data for SAX streaming API *
24101 * *
24102 ************************************************************************/
24103typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24104typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24105
24106struct _xmlSchemaSplitSAXData {
24107 xmlSAXHandlerPtr user_sax;
24108 void *user_data;
24109 xmlSchemaValidCtxtPtr ctxt;
24110 xmlSAXHandlerPtr schemas_sax;
24111};
24112
Daniel Veillard971771e2005-07-09 17:32:57 +000024113#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24114
24115struct _xmlSchemaSAXPlug {
24116 unsigned int magic;
24117
24118 /* the original callbacks informations */
24119 xmlSAXHandlerPtr *user_sax_ptr;
24120 xmlSAXHandlerPtr user_sax;
24121 void **user_data_ptr;
24122 void *user_data;
24123
24124 /* the block plugged back and validation informations */
24125 xmlSAXHandler schemas_sax;
24126 xmlSchemaValidCtxtPtr ctxt;
24127};
24128
Daniel Veillardcdc82732005-07-08 15:04:06 +000024129/* All those functions just bounces to the user provided SAX handlers */
24130static void
24131internalSubsetSplit(void *ctx, const xmlChar *name,
24132 const xmlChar *ExternalID, const xmlChar *SystemID)
24133{
Daniel Veillard971771e2005-07-09 17:32:57 +000024134 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024135 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24136 (ctxt->user_sax->internalSubset != NULL))
24137 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24138 SystemID);
24139}
24140
24141static int
24142isStandaloneSplit(void *ctx)
24143{
Daniel Veillard971771e2005-07-09 17:32:57 +000024144 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024145 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24146 (ctxt->user_sax->isStandalone != NULL))
24147 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24148 return(0);
24149}
24150
24151static int
24152hasInternalSubsetSplit(void *ctx)
24153{
Daniel Veillard971771e2005-07-09 17:32:57 +000024154 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024155 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24156 (ctxt->user_sax->hasInternalSubset != NULL))
24157 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24158 return(0);
24159}
24160
24161static int
24162hasExternalSubsetSplit(void *ctx)
24163{
Daniel Veillard971771e2005-07-09 17:32:57 +000024164 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024165 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24166 (ctxt->user_sax->hasExternalSubset != NULL))
24167 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24168 return(0);
24169}
24170
24171static void
24172externalSubsetSplit(void *ctx, const xmlChar *name,
24173 const xmlChar *ExternalID, const xmlChar *SystemID)
24174{
Daniel Veillard971771e2005-07-09 17:32:57 +000024175 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024176 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24177 (ctxt->user_sax->internalSubset != NULL))
24178 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24179 SystemID);
24180}
24181
24182static xmlParserInputPtr
24183resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24184{
Daniel Veillard971771e2005-07-09 17:32:57 +000024185 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024186 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24187 (ctxt->user_sax->resolveEntity != NULL))
24188 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24189 systemId));
24190 return(NULL);
24191}
24192
24193static xmlEntityPtr
24194getEntitySplit(void *ctx, const xmlChar *name)
24195{
Daniel Veillard971771e2005-07-09 17:32:57 +000024196 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024197 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24198 (ctxt->user_sax->getEntity != NULL))
24199 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24200 return(NULL);
24201}
24202
24203static xmlEntityPtr
24204getParameterEntitySplit(void *ctx, const xmlChar *name)
24205{
Daniel Veillard971771e2005-07-09 17:32:57 +000024206 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024207 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24208 (ctxt->user_sax->getParameterEntity != NULL))
24209 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24210 return(NULL);
24211}
24212
24213
24214static void
24215entityDeclSplit(void *ctx, const xmlChar *name, int type,
24216 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24217{
Daniel Veillard971771e2005-07-09 17:32:57 +000024218 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024219 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24220 (ctxt->user_sax->entityDecl != NULL))
24221 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24222 systemId, content);
24223}
24224
24225static void
24226attributeDeclSplit(void *ctx, const xmlChar * elem,
24227 const xmlChar * name, int type, int def,
24228 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24229{
Daniel Veillard971771e2005-07-09 17:32:57 +000024230 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024231 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24232 (ctxt->user_sax->attributeDecl != NULL)) {
24233 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24234 def, defaultValue, tree);
24235 } else {
24236 xmlFreeEnumeration(tree);
24237 }
24238}
24239
24240static void
24241elementDeclSplit(void *ctx, const xmlChar *name, int type,
24242 xmlElementContentPtr content)
24243{
Daniel Veillard971771e2005-07-09 17:32:57 +000024244 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024245 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24246 (ctxt->user_sax->elementDecl != NULL))
24247 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24248}
24249
24250static void
24251notationDeclSplit(void *ctx, const xmlChar *name,
24252 const xmlChar *publicId, const xmlChar *systemId)
24253{
Daniel Veillard971771e2005-07-09 17:32:57 +000024254 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024255 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24256 (ctxt->user_sax->notationDecl != NULL))
24257 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24258 systemId);
24259}
24260
24261static void
24262unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24263 const xmlChar *publicId, const xmlChar *systemId,
24264 const xmlChar *notationName)
24265{
Daniel Veillard971771e2005-07-09 17:32:57 +000024266 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024267 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24268 (ctxt->user_sax->unparsedEntityDecl != NULL))
24269 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24270 systemId, notationName);
24271}
24272
24273static void
24274setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24275{
Daniel Veillard971771e2005-07-09 17:32:57 +000024276 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024277 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24278 (ctxt->user_sax->setDocumentLocator != NULL))
24279 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24280}
24281
24282static void
24283startDocumentSplit(void *ctx)
24284{
Daniel Veillard971771e2005-07-09 17:32:57 +000024285 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024286 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24287 (ctxt->user_sax->startDocument != NULL))
24288 ctxt->user_sax->startDocument(ctxt->user_data);
24289}
24290
24291static void
24292endDocumentSplit(void *ctx)
24293{
Daniel Veillard971771e2005-07-09 17:32:57 +000024294 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024295 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24296 (ctxt->user_sax->endDocument != NULL))
24297 ctxt->user_sax->endDocument(ctxt->user_data);
24298}
24299
24300static void
24301processingInstructionSplit(void *ctx, const xmlChar *target,
24302 const xmlChar *data)
24303{
Daniel Veillard971771e2005-07-09 17:32:57 +000024304 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024305 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24306 (ctxt->user_sax->processingInstruction != NULL))
24307 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24308}
24309
24310static void
24311commentSplit(void *ctx, const xmlChar *value)
24312{
Daniel Veillard971771e2005-07-09 17:32:57 +000024313 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024314 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24315 (ctxt->user_sax->comment != NULL))
24316 ctxt->user_sax->comment(ctxt->user_data, value);
24317}
24318
24319/*
24320 * Varargs error callbacks to the user application, harder ...
24321 */
24322
Daniel Veillardffa3c742005-07-21 13:24:09 +000024323static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024324warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024325 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024326 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24327 (ctxt->user_sax->warning != NULL)) {
24328 TODO
24329 }
24330}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024331static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024332errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024333 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024334 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24335 (ctxt->user_sax->error != NULL)) {
24336 TODO
24337 }
24338}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024339static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024340fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024341 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024342 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24343 (ctxt->user_sax->fatalError != NULL)) {
24344 TODO
24345 }
24346}
24347
24348/*
24349 * Those are function where both the user handler and the schemas handler
24350 * need to be called.
24351 */
24352static void
24353charactersSplit(void *ctx, const xmlChar *ch, int len)
24354{
Daniel Veillard971771e2005-07-09 17:32:57 +000024355 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024356 if (ctxt == NULL)
24357 return;
24358 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24359 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24360 if (ctxt->ctxt != NULL)
24361 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24362}
24363
24364static void
24365ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24366{
Daniel Veillard971771e2005-07-09 17:32:57 +000024367 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024368 if (ctxt == NULL)
24369 return;
24370 if ((ctxt->user_sax != NULL) &&
24371 (ctxt->user_sax->ignorableWhitespace != NULL))
24372 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24373 if (ctxt->ctxt != NULL)
24374 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24375}
24376
24377static void
24378cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24379{
Daniel Veillard971771e2005-07-09 17:32:57 +000024380 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024381 if (ctxt == NULL)
24382 return;
24383 if ((ctxt->user_sax != NULL) &&
24384 (ctxt->user_sax->ignorableWhitespace != NULL))
24385 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24386 if (ctxt->ctxt != NULL)
24387 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24388}
24389
24390static void
24391referenceSplit(void *ctx, const xmlChar *name)
24392{
Daniel Veillard971771e2005-07-09 17:32:57 +000024393 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024394 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24395 (ctxt->user_sax->reference != NULL))
24396 ctxt->user_sax->reference(ctxt->user_data, name);
24397 if (ctxt->ctxt != NULL)
24398 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24399}
24400
24401static void
24402startElementNsSplit(void *ctx, const xmlChar * localname,
24403 const xmlChar * prefix, const xmlChar * URI,
24404 int nb_namespaces, const xmlChar ** namespaces,
24405 int nb_attributes, int nb_defaulted,
24406 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024407 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024408 if (ctxt == NULL)
24409 return;
24410 if ((ctxt->user_sax != NULL) &&
24411 (ctxt->user_sax->startElementNs != NULL))
24412 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24413 URI, nb_namespaces, namespaces,
24414 nb_attributes, nb_defaulted,
24415 attributes);
24416 if (ctxt->ctxt != NULL)
24417 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24418 URI, nb_namespaces, namespaces,
24419 nb_attributes, nb_defaulted,
24420 attributes);
24421}
24422
24423static void
24424endElementNsSplit(void *ctx, const xmlChar * localname,
24425 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024426 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024427 if (ctxt == NULL)
24428 return;
24429 if ((ctxt->user_sax != NULL) &&
24430 (ctxt->user_sax->endElementNs != NULL))
24431 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24432 if (ctxt->ctxt != NULL)
24433 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24434}
24435
Daniel Veillard4255d502002-04-16 15:50:10 +000024436/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024437 * xmlSchemaSAXPlug:
24438 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024439 * @sax: a pointer to the original xmlSAXHandlerPtr
24440 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024441 *
24442 * Plug a SAX based validation layer in a SAX parsing event flow.
24443 * The original @saxptr and @dataptr data are replaced by new pointers
24444 * but the calls to the original will be maintained.
24445 *
24446 * Returns a pointer to a data structure needed to unplug the validation layer
24447 * or NULL in case of errors.
24448 */
24449xmlSchemaSAXPlugPtr
24450xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24451 xmlSAXHandlerPtr *sax, void **user_data)
24452{
24453 xmlSchemaSAXPlugPtr ret;
24454 xmlSAXHandlerPtr old_sax;
24455
24456 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24457 return(NULL);
24458
24459 /*
24460 * We only allow to plug into SAX2 event streams
24461 */
24462 old_sax = *sax;
24463 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24464 return(NULL);
24465 if ((old_sax != NULL) &&
24466 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24467 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24468 return(NULL);
24469
24470 /*
24471 * everything seems right allocate the local data needed for that layer
24472 */
24473 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24474 if (ret == NULL) {
24475 return(NULL);
24476 }
24477 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24478 ret->magic = XML_SAX_PLUG_MAGIC;
24479 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24480 ret->ctxt = ctxt;
24481 ret->user_sax_ptr = sax;
24482 ret->user_sax = old_sax;
24483 if (old_sax == NULL) {
24484 /*
24485 * go direct, no need for the split block and functions.
24486 */
24487 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24488 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24489 /*
24490 * Note that we use the same text-function for both, to prevent
24491 * the parser from testing for ignorable whitespace.
24492 */
24493 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24494 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24495
24496 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24497 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24498
24499 ret->user_data = ctxt;
24500 *user_data = ctxt;
24501 } else {
24502 /*
24503 * for each callback unused by Schemas initialize it to the Split
24504 * routine only if non NULL in the user block, this can speed up
24505 * things at the SAX level.
24506 */
24507 if (old_sax->internalSubset != NULL)
24508 ret->schemas_sax.internalSubset = internalSubsetSplit;
24509 if (old_sax->isStandalone != NULL)
24510 ret->schemas_sax.isStandalone = isStandaloneSplit;
24511 if (old_sax->hasInternalSubset != NULL)
24512 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24513 if (old_sax->hasExternalSubset != NULL)
24514 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24515 if (old_sax->resolveEntity != NULL)
24516 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24517 if (old_sax->getEntity != NULL)
24518 ret->schemas_sax.getEntity = getEntitySplit;
24519 if (old_sax->entityDecl != NULL)
24520 ret->schemas_sax.entityDecl = entityDeclSplit;
24521 if (old_sax->notationDecl != NULL)
24522 ret->schemas_sax.notationDecl = notationDeclSplit;
24523 if (old_sax->attributeDecl != NULL)
24524 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24525 if (old_sax->elementDecl != NULL)
24526 ret->schemas_sax.elementDecl = elementDeclSplit;
24527 if (old_sax->unparsedEntityDecl != NULL)
24528 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24529 if (old_sax->setDocumentLocator != NULL)
24530 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24531 if (old_sax->startDocument != NULL)
24532 ret->schemas_sax.startDocument = startDocumentSplit;
24533 if (old_sax->endDocument != NULL)
24534 ret->schemas_sax.endDocument = endDocumentSplit;
24535 if (old_sax->processingInstruction != NULL)
24536 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24537 if (old_sax->comment != NULL)
24538 ret->schemas_sax.comment = commentSplit;
24539 if (old_sax->warning != NULL)
24540 ret->schemas_sax.warning = warningSplit;
24541 if (old_sax->error != NULL)
24542 ret->schemas_sax.error = errorSplit;
24543 if (old_sax->fatalError != NULL)
24544 ret->schemas_sax.fatalError = fatalErrorSplit;
24545 if (old_sax->getParameterEntity != NULL)
24546 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24547 if (old_sax->externalSubset != NULL)
24548 ret->schemas_sax.externalSubset = externalSubsetSplit;
24549
24550 /*
24551 * the 6 schemas callback have to go to the splitter functions
24552 * Note that we use the same text-function for ignorableWhitespace
24553 * if possible, to prevent the parser from testing for ignorable
24554 * whitespace.
24555 */
24556 ret->schemas_sax.characters = charactersSplit;
24557 if ((old_sax->ignorableWhitespace != NULL) &&
24558 (old_sax->ignorableWhitespace != old_sax->characters))
24559 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24560 else
24561 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24562 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24563 ret->schemas_sax.reference = referenceSplit;
24564 ret->schemas_sax.startElementNs = startElementNsSplit;
24565 ret->schemas_sax.endElementNs = endElementNsSplit;
24566
24567 ret->user_data_ptr = user_data;
24568 ret->user_data = *user_data;
24569 *user_data = ret;
24570 }
24571
24572 /*
24573 * plug the pointers back.
24574 */
24575 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024576 ctxt->sax = *sax;
24577 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24578 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024579 return(ret);
24580}
24581
24582/**
24583 * xmlSchemaSAXUnplug:
24584 * @plug: a data structure returned by xmlSchemaSAXPlug
24585 *
24586 * Unplug a SAX based validation layer in a SAX parsing event flow.
24587 * The original pointers used in the call are restored.
24588 *
24589 * Returns 0 in case of success and -1 in case of failure.
24590 */
24591int
24592xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24593{
24594 xmlSAXHandlerPtr *sax;
24595 void **user_data;
24596
24597 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24598 return(-1);
24599 plug->magic = 0;
24600
Daniel Veillardf10ae122005-07-10 19:03:16 +000024601 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024602 /* restore the data */
24603 sax = plug->user_sax_ptr;
24604 *sax = plug->user_sax;
24605 if (plug->user_sax != NULL) {
24606 user_data = plug->user_data_ptr;
24607 *user_data = plug->user_data;
24608 }
24609
24610 /* free and return */
24611 xmlFree(plug);
24612 return(0);
24613}
24614
24615/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024616 * xmlSchemaValidateStream:
24617 * @ctxt: a schema validation context
24618 * @input: the input to use for reading the data
24619 * @enc: an optional encoding information
24620 * @sax: a SAX handler for the resulting events
24621 * @user_data: the context to provide to the SAX handler.
24622 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024623 * Validate an input based on a flow of SAX event from the parser
24624 * and forward the events to the @sax handler with the provided @user_data
24625 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024626 *
24627 * Returns 0 if the document is schemas valid, a positive error code
24628 * number otherwise and -1 in case of internal or API error.
24629 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024630int
Daniel Veillard4255d502002-04-16 15:50:10 +000024631xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024632 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24633 xmlSAXHandlerPtr sax, void *user_data)
24634{
Daniel Veillard971771e2005-07-09 17:32:57 +000024635 xmlSchemaSAXPlugPtr plug = NULL;
24636 xmlSAXHandlerPtr old_sax = NULL;
24637 xmlParserCtxtPtr pctxt = NULL;
24638 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024639 int ret;
24640
Daniel Veillard4255d502002-04-16 15:50:10 +000024641 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024642 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024643
Daniel Veillardcdc82732005-07-08 15:04:06 +000024644 /*
24645 * prepare the parser
24646 */
24647 pctxt = xmlNewParserCtxt();
24648 if (pctxt == NULL)
24649 return (-1);
24650 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024651 pctxt->sax = sax;
24652 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024653#if 0
24654 if (options)
24655 xmlCtxtUseOptions(pctxt, options);
24656#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024657 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024658
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024659 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024660 if (inputStream == NULL) {
24661 ret = -1;
24662 goto done;
24663 }
24664 inputPush(pctxt, inputStream);
24665 ctxt->parserCtxt = pctxt;
24666 ctxt->input = input;
24667
24668 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024669 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024670 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024671 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24672 if (plug == NULL) {
24673 ret = -1;
24674 goto done;
24675 }
24676 ctxt->input = input;
24677 ctxt->enc = enc;
24678 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024679 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24680 ret = xmlSchemaVStart(ctxt);
24681
24682 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24683 ret = ctxt->parserCtxt->errNo;
24684 if (ret == 0)
24685 ret = 1;
24686 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024687
24688done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024689 ctxt->parserCtxt = NULL;
24690 ctxt->sax = NULL;
24691 ctxt->input = NULL;
24692 if (plug != NULL) {
24693 xmlSchemaSAXUnplug(plug);
24694 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024695 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024696 if (pctxt != NULL) {
24697 pctxt->sax = old_sax;
24698 xmlFreeParserCtxt(pctxt);
24699 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024700 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024701}
24702
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024703/**
24704 * xmlSchemaValidateFile:
24705 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024706 * @filename: the URI of the instance
24707 * @options: a future set of options, currently unused
24708 *
24709 * Do a schemas validation of the given resource, it will use the
24710 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024711 *
24712 * Returns 0 if the document is valid, a positive error code
24713 * number otherwise and -1 in case of an internal or API error.
24714 */
24715int
24716xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024717 const char * filename,
24718 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024719{
Daniel Veillard81562d22005-06-15 13:27:56 +000024720#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024721 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024722 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024723
24724 if ((ctxt == NULL) || (filename == NULL))
24725 return (-1);
24726
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024727 input = xmlParserInputBufferCreateFilename(filename,
24728 XML_CHAR_ENCODING_NONE);
24729 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024730 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024731 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24732 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024733 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024734#else
24735 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024736#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024737}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024738
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024739#define bottom_xmlschemas
24740#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024741#endif /* LIBXML_SCHEMAS_ENABLED */