blob: 0bd64239a2425910f3eda8a7a85090a6ec457181 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
1574
1575 vctxt->nberrors++;
1576 vctxt->err = error;
1577 channel = vctxt->error;
1578 schannel = vctxt->serror;
1579 data = vctxt->userData;
1580 if ((node == NULL) && (vctxt->depth >= 0) &&
1581 (vctxt->inode != NULL))
1582 node = vctxt->inode->node;
1583 __xmlRaiseError(schannel, channel, data, ctxt,
1584 node, XML_FROM_SCHEMASV,
1585 error, XML_ERR_ERROR, NULL, 0,
1586 (const char *) str1, (const char *) str2,
1587 (const char *) str3, 0, 0, msg, str1, str2, str3);
1588
1589 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1590 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1591
1592 pctxt->nberrors++;
1593 pctxt->err = error;
1594 channel = pctxt->error;
1595 schannel = pctxt->serror;
1596 data = pctxt->userData;
1597 __xmlRaiseError(schannel, channel, data, ctxt,
1598 node, XML_FROM_SCHEMASP,
1599 error, XML_ERR_ERROR, NULL, 0,
1600 (const char *) str1, (const char *) str2,
1601 (const char *) str3, 0, 0, msg, str1, str2, str3);
1602 } else {
1603 TODO
1604 }
1605 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001606}
1607
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001608static void
1609xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1610 int error, xmlNodePtr node, const char *msg,
1611 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001612{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001613 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static xmlChar *
1617xmlSchemaFormatNodeForError(xmlChar ** msg,
1618 xmlSchemaAbstractCtxtPtr actxt,
1619 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001620{
1621 xmlChar *str = NULL;
1622
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001623 if (node != NULL) {
1624 /*
1625 * Work on tree nodes.
1626 */
1627 if (node->type == XML_ATTRIBUTE_NODE) {
1628 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001629
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001630 *msg = xmlStrdup(BAD_CAST "Element '");
1631 if (elem->ns != NULL)
1632 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1633 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001634 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001635 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1636 NULL, elem->name));
1637 FREE_AND_NULL(str);
1638 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1639 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1640 } else {
1641 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 if (node->ns != NULL)
1644 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1645 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001646 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001647 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1648 NULL, node->name));
1649 FREE_AND_NULL(str);
1650 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1651 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1652 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1653 /*
1654 * Work on node infos.
1655 */
1656 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1657 xmlSchemaNodeInfoPtr ielem =
1658 vctxt->elemInfos[vctxt->depth];
1659
1660 *msg = xmlStrdup(BAD_CAST "Element '");
1661 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1662 ielem->nsName, ielem->localName));
1663 FREE_AND_NULL(str);
1664 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1665 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1666 } else {
1667 *msg = xmlStrdup(BAD_CAST "Element '");
1668 }
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 vctxt->inode->nsName, vctxt->inode->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1673 } else {
1674 TODO
1675 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001676 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001677 /*
1678 * VAL TODO: The output of the given schema component is currently
1679 * disabled.
1680 */
1681#if 0
1682 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1683 *msg = xmlStrcat(*msg, BAD_CAST " [");
1684 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1685 NULL, type, NULL, 0));
1686 FREE_AND_NULL(str)
1687 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001688 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001689#endif
1690 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001691}
1692
Daniel Veillardc0826a72004-08-10 14:17:33 +00001693static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001694xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1695 const char *funcName,
1696 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001697{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001698 xmlChar *msg = NULL;
1699
1700 msg = xmlStrdup(BAD_CAST "Internal error: ");
1701 msg = xmlStrcat(msg, BAD_CAST funcName);
1702 msg = xmlStrcat(msg, BAD_CAST ", ");
1703 msg = xmlStrcat(msg, BAD_CAST message);
1704 msg = xmlStrcat(msg, BAD_CAST ".\n");
1705
1706 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1707 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1708 (const char *) msg, NULL, NULL);
1709
1710 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1711 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1712 (const char *) msg, NULL, NULL);
1713
1714 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001715}
1716
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001717static void
1718xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1719 xmlParserErrors error,
1720 xmlNodePtr node,
1721 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1722 const char *message,
1723 const xmlChar *str1,
1724 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001725{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001726 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001727
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001728 xmlSchemaFormatNodeForError(&msg, actxt, node);
1729 msg = xmlStrcat(msg, (const xmlChar *) message);
1730 msg = xmlStrcat(msg, BAD_CAST ".\n");
1731 xmlSchemaErr(actxt, error, node,
1732 (const char *) msg, str1, str2);
1733 FREE_AND_NULL(msg)
1734}
1735
1736static int
1737xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1738 xmlNodePtr node)
1739{
1740 if (node != NULL)
1741 return (node->type);
1742 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1743 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1744 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1745 return (-1);
1746}
1747
1748static int
1749xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1750{
1751 switch (item->type) {
1752 case XML_SCHEMA_TYPE_COMPLEX:
1753 case XML_SCHEMA_TYPE_SIMPLE:
1754 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1755 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001756 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001757 case XML_SCHEMA_TYPE_GROUP:
1758 return (1);
1759 case XML_SCHEMA_TYPE_ELEMENT:
1760 if ( ((xmlSchemaElementPtr) item)->flags &
1761 XML_SCHEMAS_ELEM_GLOBAL)
1762 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001763 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001764 case XML_SCHEMA_TYPE_ATTRIBUTE:
1765 if ( ((xmlSchemaAttributePtr) item)->flags &
1766 XML_SCHEMAS_ATTR_GLOBAL)
1767 return(1);
1768 break;
1769 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001770 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001771 return(1);
1772 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001773 return (0);
1774}
1775
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001776static void
1777xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1778 xmlParserErrors error,
1779 xmlNodePtr node,
1780 const xmlChar *value,
1781 xmlSchemaTypePtr type,
1782 int displayValue)
1783{
1784 xmlChar *msg = NULL;
1785
1786 xmlSchemaFormatNodeForError(&msg, actxt, node);
1787
1788 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1789 XML_ATTRIBUTE_NODE))
1790 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1791 else
1792 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1793 "value of ");
1794
1795 if (! xmlSchemaIsGlobalItem(type))
1796 msg = xmlStrcat(msg, BAD_CAST "the local ");
1797 else
1798 msg = xmlStrcat(msg, BAD_CAST "the ");
1799
1800 if (VARIETY_ATOMIC(type))
1801 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1802 else if (VARIETY_LIST(type))
1803 msg = xmlStrcat(msg, BAD_CAST "list type");
1804 else if (VARIETY_UNION(type))
1805 msg = xmlStrcat(msg, BAD_CAST "union type");
1806
1807 if (xmlSchemaIsGlobalItem(type)) {
1808 xmlChar *str = NULL;
1809 msg = xmlStrcat(msg, BAD_CAST " '");
1810 if (type->builtInType != 0) {
1811 msg = xmlStrcat(msg, BAD_CAST "xs:");
1812 msg = xmlStrcat(msg, type->name);
1813 } else
1814 msg = xmlStrcat(msg,
1815 xmlSchemaFormatQName(&str,
1816 type->targetNamespace, type->name));
1817 msg = xmlStrcat(msg, BAD_CAST "'");
1818 FREE_AND_NULL(str);
1819 }
1820 msg = xmlStrcat(msg, BAD_CAST ".\n");
1821 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1822 XML_ATTRIBUTE_NODE))
1823 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1824 else
1825 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1826 FREE_AND_NULL(msg)
1827}
1828
Daniel Veillardc0826a72004-08-10 14:17:33 +00001829static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001830xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1831 xmlSchemaNodeInfoPtr ni,
1832 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001833{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001834 if (node != NULL) {
1835 if (node->ns != NULL)
1836 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1837 else
1838 return (xmlSchemaFormatQName(str, NULL, node->name));
1839 } else if (ni != NULL)
1840 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1841 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001842}
1843
Daniel Veillardc0826a72004-08-10 14:17:33 +00001844static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001845xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1846 xmlParserErrors error,
1847 xmlSchemaAttrInfoPtr ni,
1848 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001849{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001850 xmlChar *msg = NULL, *str = NULL;
1851
1852 xmlSchemaFormatNodeForError(&msg, actxt, node);
1853 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1854 xmlSchemaErr(actxt, error, node, (const char *) msg,
1855 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1856 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001859}
1860
Daniel Veillardc0826a72004-08-10 14:17:33 +00001861static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001862xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1863 xmlParserErrors error,
1864 xmlNodePtr node,
1865 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001866 const char *message,
1867 int nbval,
1868 int nbneg,
1869 xmlChar **values)
1870{
1871 xmlChar *str = NULL, *msg = NULL;
1872 xmlChar *localName, *nsName;
1873 const xmlChar *cur, *end;
1874 int i;
1875
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001876 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001877 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001878 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001879 /*
1880 * Note that is does not make sense to report that we have a
1881 * wildcard here, since the wildcard might be unfolded into
1882 * multiple transitions.
1883 */
1884 if (nbval + nbneg > 0) {
1885 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001888 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001889 nsName = NULL;
1890
1891 for (i = 0; i < nbval + nbneg; i++) {
1892 cur = values[i];
1893 /*
1894 * Get the local name.
1895 */
1896 localName = NULL;
1897
1898 end = cur;
1899 if (*end == '*') {
1900 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001901 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001902 } else {
1903 while ((*end != 0) && (*end != '|'))
1904 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001905 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001906 }
1907 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001908 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001909 /*
1910 * Skip "*|*" if they come with negated expressions, since
1911 * they represent the same negated wildcard.
1912 */
1913 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1914 /*
1915 * Get the namespace name.
1916 */
1917 cur = end;
1918 if (*end == '*') {
1919 nsName = xmlStrdup(BAD_CAST "{*}");
1920 } else {
1921 while (*end != 0)
1922 end++;
1923
1924 if (i >= nbval)
1925 nsName = xmlStrdup(BAD_CAST "{##other:");
1926 else
1927 nsName = xmlStrdup(BAD_CAST "{");
1928
1929 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1930 nsName = xmlStrcat(nsName, BAD_CAST "}");
1931 }
1932 str = xmlStrcat(str, BAD_CAST nsName);
1933 FREE_AND_NULL(nsName)
1934 } else {
1935 FREE_AND_NULL(localName);
1936 continue;
1937 }
1938 }
1939 str = xmlStrcat(str, BAD_CAST localName);
1940 FREE_AND_NULL(localName);
1941
1942 if (i < nbval + nbneg -1)
1943 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001944 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001945 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001946 msg = xmlStrcat(msg, BAD_CAST str);
1947 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001948 } else
1949 msg = xmlStrcat(msg, BAD_CAST "\n");
1950 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001951 xmlFree(msg);
1952}
1953
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001954static void
1955xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1956 xmlParserErrors error,
1957 xmlNodePtr node,
1958 const xmlChar *value,
1959 unsigned long length,
1960 xmlSchemaTypePtr type,
1961 xmlSchemaFacetPtr facet,
1962 const char *message,
1963 const xmlChar *str1,
1964 const xmlChar *str2)
1965{
1966 xmlChar *str = NULL, *msg = NULL;
1967 xmlSchemaTypeType facetType;
1968 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1969
1970 xmlSchemaFormatNodeForError(&msg, actxt, node);
1971 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1972 facetType = XML_SCHEMA_FACET_ENUMERATION;
1973 /*
1974 * If enumerations are validated, one must not expect the
1975 * facet to be given.
1976 */
1977 } else
1978 facetType = facet->type;
1979 msg = xmlStrcat(msg, BAD_CAST "[");
1980 msg = xmlStrcat(msg, BAD_CAST "facet '");
1981 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1982 msg = xmlStrcat(msg, BAD_CAST "'] ");
1983 if (message == NULL) {
1984 /*
1985 * Use a default message.
1986 */
1987 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1988 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1989 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1990
1991 char len[25], actLen[25];
1992
1993 /* FIXME, TODO: What is the max expected string length of the
1994 * this value?
1995 */
1996 if (nodeType == XML_ATTRIBUTE_NODE)
1997 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1998 else
1999 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2000
2001 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2002 snprintf(actLen, 24, "%lu", length);
2003
2004 if (facetType == XML_SCHEMA_FACET_LENGTH)
2005 msg = xmlStrcat(msg,
2006 BAD_CAST "this differs from the allowed length of '%s'.\n");
2007 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2008 msg = xmlStrcat(msg,
2009 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2010 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2011 msg = xmlStrcat(msg,
2012 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2013
2014 if (nodeType == XML_ATTRIBUTE_NODE)
2015 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2016 value, (const xmlChar *) actLen, (const xmlChar *) len);
2017 else
2018 xmlSchemaErr(actxt, error, node, (const char *) msg,
2019 (const xmlChar *) actLen, (const xmlChar *) len);
2020
2021 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2022 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2023 "of the set {%s}.\n");
2024 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2025 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2026 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2027 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2028 "by the pattern '%s'.\n");
2029 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2030 facet->value);
2031 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2032 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2033 "minimum value allowed ('%s').\n");
2034 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2035 facet->value);
2036 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2037 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2038 "maximum value allowed ('%s').\n");
2039 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2040 facet->value);
2041 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2042 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2043 "'%s'.\n");
2044 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2045 facet->value);
2046 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2047 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2048 "'%s'.\n");
2049 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2050 facet->value);
2051 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2052 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2053 "digits than are allowed ('%s').\n");
2054 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2055 facet->value);
2056 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2057 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2058 "digits than are allowed ('%s').\n");
2059 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2060 facet->value);
2061 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2062 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2063 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2064 } else {
2065 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2066 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2067 }
2068 } else {
2069 msg = xmlStrcat(msg, (const xmlChar *) message);
2070 msg = xmlStrcat(msg, BAD_CAST ".\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2072 }
2073 FREE_AND_NULL(str)
2074 xmlFree(msg);
2075}
2076
2077#define VERROR(err, type, msg) \
2078 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2079
2080#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2081
2082#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2083
2084#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2085
2086
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002087/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002088 * xmlSchemaPMissingAttrErr:
2089 * @ctxt: the schema validation context
2090 * @ownerDes: the designation of the owner
2091 * @ownerName: the name of the owner
2092 * @ownerItem: the owner as a schema object
2093 * @ownerElem: the owner as an element node
2094 * @node: the parent element node of the missing attribute node
2095 * @type: the corresponding type of the attribute node
2096 *
2097 * Reports an illegal attribute.
2098 */
2099static void
2100xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002101 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002102 xmlSchemaTypePtr ownerItem,
2103 xmlNodePtr ownerElem,
2104 const char *name,
2105 const char *message)
2106{
2107 xmlChar *des = NULL;
2108
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2110
Daniel Veillardc0826a72004-08-10 14:17:33 +00002111 if (message != NULL)
2112 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002113 else
2114 xmlSchemaPErr(ctxt, ownerElem, error,
2115 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002116 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002118}
2119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002120
Daniel Veillardc0826a72004-08-10 14:17:33 +00002121/**
2122 * xmlSchemaPResCompAttrErr:
2123 * @ctxt: the schema validation context
2124 * @error: the error code
2125 * @ownerDes: the designation of the owner
2126 * @ownerItem: the owner as a schema object
2127 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129 * @refName: the referenced local name
2130 * @refURI: the referenced namespace URI
2131 * @message: optional message
2132 *
2133 * Used to report QName attribute values that failed to resolve
2134 * to schema components.
2135 */
2136static void
2137xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002138 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002139 xmlSchemaTypePtr ownerItem,
2140 xmlNodePtr ownerElem,
2141 const char *name,
2142 const xmlChar *refName,
2143 const xmlChar *refURI,
2144 xmlSchemaTypeType refType,
2145 const char *refTypeStr)
2146{
2147 xmlChar *des = NULL, *strA = NULL;
2148
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002149 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002150 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002151 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2152 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002153 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002154 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2155 "%s.\n", BAD_CAST des, BAD_CAST name,
2156 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002158 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002159 FREE_AND_NULL(strA)
2160}
2161
William M. Brack2f2a6632004-08-20 23:09:47 +00002162/**
2163 * xmlSchemaPCustomAttrErr:
2164 * @ctxt: the schema parser context
2165 * @error: the error code
2166 * @ownerDes: the designation of the owner
2167 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002168 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002169 *
2170 * Reports an illegal attribute during the parse.
2171 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002172static void
2173xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002174 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002175 xmlChar **ownerDes,
2176 xmlSchemaTypePtr ownerItem,
2177 xmlAttrPtr attr,
2178 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002179{
2180 xmlChar *des = NULL;
2181
2182 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002183 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002184 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002185 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002186 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002187 } else
2188 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002189 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002190 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002191 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2192 if (ownerDes == NULL)
2193 FREE_AND_NULL(des);
2194}
2195
2196/**
2197 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002198 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002200 * @ownerDes: the designation of the attribute's owner
2201 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002202 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002203 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002204 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002205 */
2206static void
2207xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 xmlChar **ownerDes,
2210 xmlSchemaTypePtr ownerItem,
2211 xmlAttrPtr attr)
2212{
2213 xmlChar *des = NULL, *strA = NULL;
2214
2215 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002218 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002219 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002220 } else
2221 des = *ownerDes;
2222 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2223 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2224 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002225 if (ownerDes == NULL)
2226 FREE_AND_NULL(des);
2227 FREE_AND_NULL(strA);
2228}
2229
William M. Brack2f2a6632004-08-20 23:09:47 +00002230/**
2231 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002233 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002235 * @itemElem: the node of the schema item
2236 *
2237 * Creates a designation for an item.
2238 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002239static void
2240xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002241 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002242 xmlSchemaTypePtr item,
2243 xmlNodePtr itemElem)
2244{
2245 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002247 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002249 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250 } else
2251 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252}
2253
William M. Brack2f2a6632004-08-20 23:09:47 +00002254/**
2255 * xmlSchemaPCustomErr:
2256 * @ctxt: the schema parser context
2257 * @error: the error code
2258 * @itemDes: the designation of the schema item
2259 * @item: the schema item
2260 * @itemElem: the node of the schema item
2261 * @message: the error message
2262 * @str1: an optional param for the error message
2263 * @str2: an optional param for the error message
2264 * @str3: an optional param for the error message
2265 *
2266 * Reports an error during parsing.
2267 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002268static void
2269xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002270 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002271 xmlChar **itemDes,
2272 xmlSchemaTypePtr item,
2273 xmlNodePtr itemElem,
2274 const char *message,
2275 const xmlChar *str1,
2276 const xmlChar *str2,
2277 const xmlChar *str3)
2278{
2279 xmlChar *des = NULL, *msg = NULL;
2280
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002281 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002282 msg = xmlStrdup(BAD_CAST "%s: ");
2283 msg = xmlStrcat(msg, (const xmlChar *) message);
2284 msg = xmlStrcat(msg, BAD_CAST ".\n");
2285 if ((itemElem == NULL) && (item != NULL))
2286 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002287 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2289 if (itemDes == NULL)
2290 FREE_AND_NULL(des);
2291 FREE_AND_NULL(msg);
2292}
2293
William M. Brack2f2a6632004-08-20 23:09:47 +00002294/**
2295 * xmlSchemaPCustomErr:
2296 * @ctxt: the schema parser context
2297 * @error: the error code
2298 * @itemDes: the designation of the schema item
2299 * @item: the schema item
2300 * @itemElem: the node of the schema item
2301 * @message: the error message
2302 * @str1: the optional param for the error message
2303 *
2304 * Reports an error during parsing.
2305 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306static void
2307xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002308 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002309 xmlChar **itemDes,
2310 xmlSchemaTypePtr item,
2311 xmlNodePtr itemElem,
2312 const char *message,
2313 const xmlChar *str1)
2314{
2315 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2316 str1, NULL, NULL);
2317}
2318
William M. Brack2f2a6632004-08-20 23:09:47 +00002319/**
2320 * xmlSchemaPAttrUseErr:
2321 * @ctxt: the schema parser context
2322 * @error: the error code
2323 * @itemDes: the designation of the schema type
2324 * @item: the schema type
2325 * @itemElem: the node of the schema type
2326 * @attr: the invalid schema attribute
2327 * @message: the error message
2328 * @str1: the optional param for the error message
2329 *
2330 * Reports an attribute use error during parsing.
2331 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002332static void
2333xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002334 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002335 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002336 const xmlSchemaAttributePtr attr,
2337 const char *message,
2338 const xmlChar *str1)
2339{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002340 xmlChar *str = NULL, *msg = NULL;
2341 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2342 msg = xmlStrcat(msg, BAD_CAST ", ");
2343 msg = xmlStrcat(msg,
2344 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2345 (xmlSchemaTypePtr) attr, NULL));
2346 FREE_AND_NULL(str);
2347 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002348 msg = xmlStrcat(msg, (const xmlChar *) message);
2349 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002350 xmlSchemaPErr(ctxt, attr->node, error,
2351 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002352 xmlFree(msg);
2353}
2354
William M. Brack2f2a6632004-08-20 23:09:47 +00002355/**
2356 * xmlSchemaPIllegalFacetAtomicErr:
2357 * @ctxt: the schema parser context
2358 * @error: the error code
2359 * @itemDes: the designation of the type
2360 * @item: the schema type
2361 * @baseItem: the base type of type
2362 * @facet: the illegal facet
2363 *
2364 * Reports an illegal facet for atomic simple types.
2365 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002366static void
2367xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002368 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002369 xmlChar **itemDes,
2370 xmlSchemaTypePtr item,
2371 xmlSchemaTypePtr baseItem,
2372 xmlSchemaFacetPtr facet)
2373{
2374 xmlChar *des = NULL, *strT = NULL;
2375
2376 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2377 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2378 "%s: The facet '%s' is not allowed on types derived from the "
2379 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002380 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002381 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002382 NULL, NULL);
2383 if (itemDes == NULL)
2384 FREE_AND_NULL(des);
2385 FREE_AND_NULL(strT);
2386}
2387
William M. Brack2f2a6632004-08-20 23:09:47 +00002388/**
2389 * xmlSchemaPIllegalFacetListUnionErr:
2390 * @ctxt: the schema parser context
2391 * @error: the error code
2392 * @itemDes: the designation of the schema item involved
2393 * @item: the schema item involved
2394 * @facet: the illegal facet
2395 *
2396 * Reports an illegal facet for <list> and <union>.
2397 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002398static void
2399xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002400 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002401 xmlChar **itemDes,
2402 xmlSchemaTypePtr item,
2403 xmlSchemaFacetPtr facet)
2404{
2405 xmlChar *des = NULL, *strT = NULL;
2406
2407 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408 xmlSchemaPErr(ctxt, item->node, error,
2409 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002410 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002411 if (itemDes == NULL)
2412 FREE_AND_NULL(des);
2413 FREE_AND_NULL(strT);
2414}
2415
2416/**
2417 * xmlSchemaPMutualExclAttrErr:
2418 * @ctxt: the schema validation context
2419 * @error: the error code
2420 * @elemDes: the designation of the parent element node
2421 * @attr: the bad attribute node
2422 * @type: the corresponding type of the attribute node
2423 *
2424 * Reports an illegal attribute.
2425 */
2426static void
2427xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2428 xmlParserErrors error,
2429 xmlChar **ownerDes,
2430 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002432 const char *name1,
2433 const char *name2)
2434{
2435 xmlChar *des = NULL;
2436
2437 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002438 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002439 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002440 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002441 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002442 } else
2443 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002444 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002445 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002446 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2447 if (ownerDes == NULL)
2448 FREE_AND_NULL(des)
2449}
2450
2451/**
2452 * xmlSchemaPSimpleTypeErr:
2453 * @ctxt: the schema validation context
2454 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002455 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002456 * @ownerDes: the designation of the owner
2457 * @ownerItem: the schema object if existent
2458 * @node: the validated node
2459 * @value: the validated value
2460 *
2461 * Reports a simple type validation error.
2462 * TODO: Should this report the value of an element as well?
2463 */
2464static void
2465xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2466 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002467 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002469 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002470 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002471 const xmlChar *value,
2472 const char *message,
2473 const xmlChar *str1,
2474 const xmlChar *str2)
2475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002476 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002477
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 if (message == NULL) {
2480 /*
2481 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002482 */
2483 if (type != NULL) {
2484 if (node->type == XML_ATTRIBUTE_NODE)
2485 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2486 else
2487 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2488 "valid value of ");
2489 if (! xmlSchemaIsGlobalItem(type))
2490 msg = xmlStrcat(msg, BAD_CAST "the local ");
2491 else
2492 msg = xmlStrcat(msg, BAD_CAST "the ");
2493
2494 if (VARIETY_ATOMIC(type))
2495 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2496 else if (VARIETY_LIST(type))
2497 msg = xmlStrcat(msg, BAD_CAST "list type");
2498 else if (VARIETY_UNION(type))
2499 msg = xmlStrcat(msg, BAD_CAST "union type");
2500
2501 if (xmlSchemaIsGlobalItem(type)) {
2502 xmlChar *str = NULL;
2503 msg = xmlStrcat(msg, BAD_CAST " '");
2504 if (type->builtInType != 0) {
2505 msg = xmlStrcat(msg, BAD_CAST "xs:");
2506 msg = xmlStrcat(msg, type->name);
2507 } else
2508 msg = xmlStrcat(msg,
2509 xmlSchemaFormatQName(&str,
2510 type->targetNamespace, type->name));
2511 msg = xmlStrcat(msg, BAD_CAST "'.");
2512 FREE_AND_NULL(str);
2513 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002514 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002515 if (node->type == XML_ATTRIBUTE_NODE)
2516 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2517 else
2518 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2519 "valid.");
2520 }
2521 if (expected) {
2522 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2523 msg = xmlStrcat(msg, BAD_CAST expected);
2524 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2525 } else
2526 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002527 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002528 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2529 else
2530 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2531 } else {
2532 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2533 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002534 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002535 /* Cleanup. */
2536 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002537}
2538
William M. Brack2f2a6632004-08-20 23:09:47 +00002539/**
2540 * xmlSchemaPContentErr:
2541 * @ctxt: the schema parser context
2542 * @error: the error code
2543 * @onwerDes: the designation of the holder of the content
2544 * @ownerItem: the owner item of the holder of the content
2545 * @ownerElem: the node of the holder of the content
2546 * @child: the invalid child node
2547 * @message: the optional error message
2548 * @content: the optional string describing the correct content
2549 *
2550 * Reports an error concerning the content of a schema element.
2551 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002552static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002553xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002554 xmlParserErrors error,
2555 xmlChar **ownerDes,
2556 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002557 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002558 xmlNodePtr child,
2559 const char *message,
2560 const char *content)
2561{
2562 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002563
Daniel Veillardc0826a72004-08-10 14:17:33 +00002564 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002567 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002568 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002569 } else
2570 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002571 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002572 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2573 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 BAD_CAST des, BAD_CAST message);
2575 else {
2576 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2578 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 BAD_CAST des, BAD_CAST content);
2580 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2582 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002583 BAD_CAST des, NULL);
2584 }
2585 }
2586 if (ownerDes == NULL)
2587 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002588}
2589
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002590/************************************************************************
2591 * *
2592 * Streamable error functions *
2593 * *
2594 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002595
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002596
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002597
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002598
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002599/************************************************************************
2600 * *
2601 * Validation helper functions *
2602 * *
2603 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002604
Daniel Veillardc0826a72004-08-10 14:17:33 +00002605
Daniel Veillard4255d502002-04-16 15:50:10 +00002606/************************************************************************
2607 * *
2608 * Allocation functions *
2609 * *
2610 ************************************************************************/
2611
2612/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002613 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002614 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002615 *
2616 * Allocate a new Schema structure.
2617 *
2618 * Returns the newly allocated structure or NULL in case or error
2619 */
2620static xmlSchemaPtr
2621xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2622{
2623 xmlSchemaPtr ret;
2624
2625 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2626 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002627 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002628 return (NULL);
2629 }
2630 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002631 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002632 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002633
2634 return (ret);
2635}
2636
2637/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002638 * xmlSchemaNewSchema:
2639 * @ctxt: a schema validation context
2640 *
2641 * Allocate a new Schema structure.
2642 *
2643 * Returns the newly allocated structure or NULL in case or error
2644 */
2645static xmlSchemaAssemblePtr
2646xmlSchemaNewAssemble(void)
2647{
2648 xmlSchemaAssemblePtr ret;
2649
2650 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2651 if (ret == NULL) {
2652 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2653 return (NULL);
2654 }
2655 memset(ret, 0, sizeof(xmlSchemaAssemble));
2656 ret->items = NULL;
2657 return (ret);
2658}
2659
2660/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002661 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002662 *
2663 * Allocate a new Facet structure.
2664 *
2665 * Returns the newly allocated structure or NULL in case or error
2666 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002667xmlSchemaFacetPtr
2668xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002669{
2670 xmlSchemaFacetPtr ret;
2671
2672 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2673 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002674 return (NULL);
2675 }
2676 memset(ret, 0, sizeof(xmlSchemaFacet));
2677
2678 return (ret);
2679}
2680
2681/**
2682 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002683 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002684 * @node: a node
2685 *
2686 * Allocate a new annotation structure.
2687 *
2688 * Returns the newly allocated structure or NULL in case or error
2689 */
2690static xmlSchemaAnnotPtr
2691xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2692{
2693 xmlSchemaAnnotPtr ret;
2694
2695 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2696 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002697 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002698 return (NULL);
2699 }
2700 memset(ret, 0, sizeof(xmlSchemaAnnot));
2701 ret->content = node;
2702 return (ret);
2703}
2704
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002705static xmlSchemaItemListPtr
2706xmlSchemaNewItemList(void)
2707{
2708 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002709
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002710 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2711 if (ret == NULL) {
2712 xmlSchemaPErrMemory(NULL,
2713 "allocating an item list structure", NULL);
2714 return (NULL);
2715 }
2716 memset(ret, 0, sizeof(xmlSchemaItemList));
2717 return (ret);
2718}
2719
2720/**
2721 * xmlSchemaAddElementSubstitutionMember:
2722 * @pctxt: a schema parser context
2723 * @head: the head of the substitution group
2724 * @member: the new member of the substitution group
2725 *
2726 * Allocate a new annotation structure.
2727 *
2728 * Returns the newly allocated structure or NULL in case or error
2729 */
2730static int
2731xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2732 xmlSchemaElementPtr head,
2733 xmlSchemaElementPtr member)
2734{
2735 xmlSchemaSubstGroupPtr substGroup;
2736
2737 if (pctxt == NULL)
2738 return (-1);
2739
2740 if (pctxt->substGroups == NULL) {
2741 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2742 if (pctxt->substGroups == NULL)
2743 return (-1);
2744 }
2745 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2746 head->targetNamespace);
2747 if (substGroup == NULL) {
2748 int res;
2749
2750 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2751 if (substGroup == NULL) {
2752 xmlSchemaPErrMemory(NULL,
2753 "xmlSchemaAddElementSubstitution, allocating a substitution "
2754 "group container",
2755 NULL);
2756 return (-1);
2757 }
2758 substGroup->members = xmlSchemaNewItemList();
2759 if (substGroup->members == NULL) {
2760 xmlFree(substGroup);
2761 return (-1);
2762 }
2763 substGroup->head = head;
2764
2765 res = xmlHashAddEntry2(pctxt->substGroups,
2766 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002767 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002768 xmlFree(substGroup->members);
2769 xmlFree(substGroup);
2770 xmlSchemaPErr(pctxt, member->node,
2771 XML_SCHEMAP_INTERNAL,
2772 "Internal error: xmlSchemaAddElementSubstitution, "
2773 "failed to add a new substitution group container for "
2774 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775 return (-1);
2776 }
2777 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002778 if (substGroup->members->items == NULL) {
2779 substGroup->members->items = (void **) xmlMalloc(
2780 5 * sizeof(xmlSchemaElementPtr));
2781 if (substGroup->members->items == NULL) {
2782 xmlSchemaPErrMemory(NULL,
2783 "allocating list of substitution group members", NULL);
2784 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002785 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002787 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002788 substGroup->members->nbItems) {
2789 substGroup->members->sizeItems *= 2;
2790 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002791 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002792 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2793 if (substGroup->members->items == NULL) {
2794 xmlSchemaPErrMemory(NULL,
2795 "re-allocating list of substitution group members", NULL);
2796 substGroup->members->sizeItems = 0;
2797 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002798 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002799 }
2800 ((xmlSchemaElementPtr *) substGroup->members->items)
2801 [substGroup->members->nbItems++] = (void *) member;
2802 return (0);
2803}
2804
2805/**
2806 * xmlSchemaGetElementSubstitutionGroup:
2807 * @pctxt: a schema parser context
2808 * @head: the head of the substitution group
2809 * @member: the new member of the substitution group
2810 *
2811 * Allocate a new annotation structure.
2812 *
2813 * Returns the newly allocated structure or NULL in case or error
2814 */
2815static xmlSchemaSubstGroupPtr
2816xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2817 xmlSchemaElementPtr head)
2818{
2819 if (pctxt == NULL)
2820 return (NULL);
2821
2822 if (pctxt->substGroups == NULL)
2823 return (NULL);
2824
2825 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2826 head->name, head->targetNamespace));
2827}
2828
2829/**
2830 * xmlSchemaFreeItemList:
2831 * @annot: a schema type structure
2832 *
2833 * Deallocate a annotation structure
2834 */
2835static void
2836xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2837{
2838 if (list == NULL)
2839 return;
2840 if (list->items != NULL)
2841 xmlFree(list->items);
2842 xmlFree(list);
2843}
2844
Daniel Veillard4255d502002-04-16 15:50:10 +00002845/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002846 * xmlSchemaFreeAnnot:
2847 * @annot: a schema type structure
2848 *
2849 * Deallocate a annotation structure
2850 */
2851static void
2852xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2853{
2854 if (annot == NULL)
2855 return;
2856 xmlFree(annot);
2857}
2858
2859/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002860 * xmlSchemaFreeImport:
2861 * @import: a schema import structure
2862 *
2863 * Deallocate an import structure
2864 */
2865static void
2866xmlSchemaFreeImport(xmlSchemaImportPtr import)
2867{
2868 if (import == NULL)
2869 return;
2870
2871 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002872 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002873 xmlFree(import);
2874}
2875
2876/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002877 * xmlSchemaFreeInclude:
2878 * @include: a schema include structure
2879 *
2880 * Deallocate an include structure
2881 */
2882static void
2883xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2884{
2885 if (include == NULL)
2886 return;
2887
2888 xmlFreeDoc(include->doc);
2889 xmlFree(include);
2890}
2891
2892/**
2893 * xmlSchemaFreeIncludeList:
2894 * @includes: a schema include list
2895 *
2896 * Deallocate an include structure
2897 */
2898static void
2899xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2900{
2901 xmlSchemaIncludePtr next;
2902
2903 while (includes != NULL) {
2904 next = includes->next;
2905 xmlSchemaFreeInclude(includes);
2906 includes = next;
2907 }
2908}
2909
2910/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002911 * xmlSchemaFreeNotation:
2912 * @schema: a schema notation structure
2913 *
2914 * Deallocate a Schema Notation structure.
2915 */
2916static void
2917xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2918{
2919 if (nota == NULL)
2920 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002921 xmlFree(nota);
2922}
2923
2924/**
2925 * xmlSchemaFreeAttribute:
2926 * @schema: a schema attribute structure
2927 *
2928 * Deallocate a Schema Attribute structure.
2929 */
2930static void
2931xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2932{
2933 if (attr == NULL)
2934 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002935 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002936 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002937 if (attr->defVal != NULL)
2938 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002939 xmlFree(attr);
2940}
2941
2942/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002943 * xmlSchemaFreeWildcardNsSet:
2944 * set: a schema wildcard namespace
2945 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002946 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002947 */
2948static void
2949xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2950{
2951 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002952
Daniel Veillard3646d642004-06-02 19:19:14 +00002953 while (set != NULL) {
2954 next = set->next;
2955 xmlFree(set);
2956 set = next;
2957 }
2958}
2959
2960/**
2961 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002962 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002963 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002964 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002965 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002966void
Daniel Veillard3646d642004-06-02 19:19:14 +00002967xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2968{
2969 if (wildcard == NULL)
2970 return;
2971 if (wildcard->annot != NULL)
2972 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002973 if (wildcard->nsSet != NULL)
2974 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2975 if (wildcard->negNsSet != NULL)
2976 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002977 xmlFree(wildcard);
2978}
2979
2980/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002981 * xmlSchemaFreeAttributeGroup:
2982 * @schema: a schema attribute group structure
2983 *
2984 * Deallocate a Schema Attribute Group structure.
2985 */
2986static void
2987xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2988{
2989 if (attr == NULL)
2990 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002991 if (attr->annot != NULL)
2992 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002993 xmlFree(attr);
2994}
2995
2996/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002997 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002998 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002999 *
3000 * Deallocate a list of schema attribute uses.
3001 */
3002static void
3003xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3004{
3005 xmlSchemaAttributeLinkPtr next;
3006
3007 while (attrUse != NULL) {
3008 next = attrUse->next;
3009 xmlFree(attrUse);
3010 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003011 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003012}
3013
3014/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003015 * xmlSchemaFreeQNameRef:
3016 * @item: a QName reference structure
3017 *
3018 * Deallocatea a QName reference structure.
3019 */
3020static void
3021xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3022{
3023 xmlFree(item);
3024}
3025
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003026/**
3027 * xmlSchemaFreeQNameRef:
3028 * @item: a QName reference structure
3029 *
3030 * Deallocatea a QName reference structure.
3031 */
3032static void
3033xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3034{
3035 if (item == NULL)
3036 return;
3037 if (item->members != NULL)
3038 xmlSchemaFreeItemList(item->members);
3039 xmlFree(item);
3040}
3041
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003042static int
3043xmlSchemaAddVolatile(xmlSchemaPtr schema,
3044 xmlSchemaBasicItemPtr item)
3045{
3046 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003047
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003048 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003049 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003050 if (schema->volatiles == NULL) {
3051 xmlSchemaPErrMemory(NULL,
3052 "allocating list of volatiles", NULL);
3053 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003054 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003055 }
3056 list = (xmlSchemaItemListPtr) schema->volatiles;
3057 if (list->items == NULL) {
3058 list->items = (void **) xmlMalloc(
3059 20 * sizeof(xmlSchemaBasicItemPtr));
3060 if (list->items == NULL) {
3061 xmlSchemaPErrMemory(NULL,
3062 "allocating new volatile item buffer", NULL);
3063 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003064 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003065 list->sizeItems = 20;
3066 } else if (list->sizeItems <= list->nbItems) {
3067 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003068 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003069 list->sizeItems * sizeof(xmlSchemaTypePtr));
3070 if (list->items == NULL) {
3071 xmlSchemaPErrMemory(NULL,
3072 "growing volatile item buffer", NULL);
3073 list->sizeItems = 0;
3074 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003075 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003076 }
3077 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3078 return (0);
3079}
3080
3081/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003082 * xmlSchemaFreeTypeLinkList:
3083 * @alink: a type link
3084 *
3085 * Deallocate a list of types.
3086 */
3087static void
3088xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3089{
3090 xmlSchemaTypeLinkPtr next;
3091
3092 while (link != NULL) {
3093 next = link->next;
3094 xmlFree(link);
3095 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003096 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003097}
3098
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003099static void
3100xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3101{
3102 xmlSchemaIDCStateObjPtr next;
3103 while (sto != NULL) {
3104 next = sto->next;
3105 if (sto->history != NULL)
3106 xmlFree(sto->history);
3107 if (sto->xpathCtxt != NULL)
3108 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3109 xmlFree(sto);
3110 sto = next;
3111 }
3112}
3113
3114/**
3115 * xmlSchemaFreeIDC:
3116 * @idc: a identity-constraint definition
3117 *
3118 * Deallocates an identity-constraint definition.
3119 */
3120static void
3121xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3122{
3123 xmlSchemaIDCSelectPtr cur, prev;
3124
3125 if (idcDef == NULL)
3126 return;
3127 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003128 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003129 /* Selector */
3130 if (idcDef->selector != NULL) {
3131 if (idcDef->selector->xpathComp != NULL)
3132 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3133 xmlFree(idcDef->selector);
3134 }
3135 /* Fields */
3136 if (idcDef->fields != NULL) {
3137 cur = idcDef->fields;
3138 do {
3139 prev = cur;
3140 cur = cur->next;
3141 if (prev->xpathComp != NULL)
3142 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003143 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003144 } while (cur != NULL);
3145 }
3146 xmlFree(idcDef);
3147}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003148
Daniel Veillard01fa6152004-06-29 17:04:39 +00003149/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003150 * xmlSchemaFreeElement:
3151 * @schema: a schema element structure
3152 *
3153 * Deallocate a Schema Element structure.
3154 */
3155static void
3156xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3157{
3158 if (elem == NULL)
3159 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003160 if (elem->annot != NULL)
3161 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003163 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003164 if (elem->defVal != NULL)
3165 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003166 xmlFree(elem);
3167}
3168
3169/**
3170 * xmlSchemaFreeFacet:
3171 * @facet: a schema facet structure
3172 *
3173 * Deallocate a Schema Facet structure.
3174 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003175void
Daniel Veillard4255d502002-04-16 15:50:10 +00003176xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3177{
3178 if (facet == NULL)
3179 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003180 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003181 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003182 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003183 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003184 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003185 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003186 xmlFree(facet);
3187}
3188
3189/**
3190 * xmlSchemaFreeType:
3191 * @type: a schema type structure
3192 *
3193 * Deallocate a Schema Type structure.
3194 */
3195void
3196xmlSchemaFreeType(xmlSchemaTypePtr type)
3197{
3198 if (type == NULL)
3199 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003201 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003202 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003204
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003205 facet = type->facets;
3206 while (facet != NULL) {
3207 next = facet->next;
3208 xmlSchemaFreeFacet(facet);
3209 facet = next;
3210 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003212 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3213 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003214 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003215 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003216 if (type->memberTypes != NULL)
3217 xmlSchemaFreeTypeLinkList(type->memberTypes);
3218 if (type->facetSet != NULL) {
3219 xmlSchemaFacetLinkPtr next, link;
3220
3221 link = type->facetSet;
3222 do {
3223 next = link->next;
3224 xmlFree(link);
3225 link = next;
3226 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003227 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003228 if (type->contModel != NULL)
3229 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003230 xmlFree(type);
3231}
3232
3233/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003234 * xmlSchemaFreeModelGroupDef:
3235 * @item: a schema model group definition
3236 *
3237 * Deallocates a schema model group definition.
3238 */
3239static void
3240xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3241{
3242 if (item->annot != NULL)
3243 xmlSchemaFreeAnnot(item->annot);
3244 xmlFree(item);
3245}
3246
3247/**
3248 * xmlSchemaFreeModelGroup:
3249 * @item: a schema model group
3250 *
3251 * Deallocates a schema model group structure.
3252 */
3253static void
3254xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3255{
3256 if (item->annot != NULL)
3257 xmlSchemaFreeAnnot(item->annot);
3258 xmlFree(item);
3259}
3260
3261/**
3262 * xmlSchemaFreeParticle:
3263 * @type: a schema type structure
3264 *
3265 * Deallocate a Schema Type structure.
3266 */
3267static void
3268xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3269{
3270 if (item->annot != NULL)
3271 xmlSchemaFreeAnnot(item->annot);
3272 xmlFree(item);
3273}
3274
3275/**
3276 * xmlSchemaFreeMiscComponents:
3277 * @item: a schema component
3278 *
3279 * Deallocates misc. schema component structures.
3280 */
3281static void
3282xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3283{
3284 if (item == NULL)
3285 return;
3286 switch (item->type) {
3287 case XML_SCHEMA_TYPE_PARTICLE:
3288 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3289 return;
3290 case XML_SCHEMA_TYPE_SEQUENCE:
3291 case XML_SCHEMA_TYPE_CHOICE:
3292 case XML_SCHEMA_TYPE_ALL:
3293 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3294 return;
3295 case XML_SCHEMA_TYPE_ANY:
3296 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3297 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3298 break;
3299 default:
3300 /* TODO: This should never be hit. */
3301 TODO
3302 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003303 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003304}
3305
3306static void
3307xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3308{
3309 if (schema->volatiles == NULL)
3310 return;
3311 {
3312 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3313 xmlSchemaTreeItemPtr item;
3314 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003315
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003316 for (i = 0; i < list->nbItems; i++) {
3317 if (list->items[i] != NULL) {
3318 item = (xmlSchemaTreeItemPtr) list->items[i];
3319 switch (item->type) {
3320 case XML_SCHEMA_EXTRA_QNAMEREF:
3321 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3322 break;
3323 default:
3324 xmlSchemaFreeMiscComponents(item);
3325 }
3326 }
3327 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003328 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003329 }
3330}
3331/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003332 * xmlSchemaFreeTypeList:
3333 * @type: a schema type structure
3334 *
3335 * Deallocate a Schema Type structure.
3336 */
3337static void
3338xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3339{
3340 xmlSchemaTypePtr next;
3341
3342 while (type != NULL) {
3343 next = type->redef;
3344 xmlSchemaFreeType(type);
3345 type = next;
3346 }
3347}
3348
3349/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003350 * xmlSchemaFree:
3351 * @schema: a schema structure
3352 *
3353 * Deallocate a Schema structure.
3354 */
3355void
3356xmlSchemaFree(xmlSchemaPtr schema)
3357{
3358 if (schema == NULL)
3359 return;
3360
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003361 if (schema->volatiles != NULL)
3362 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003363 if (schema->notaDecl != NULL)
3364 xmlHashFree(schema->notaDecl,
3365 (xmlHashDeallocator) xmlSchemaFreeNotation);
3366 if (schema->attrDecl != NULL)
3367 xmlHashFree(schema->attrDecl,
3368 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3369 if (schema->attrgrpDecl != NULL)
3370 xmlHashFree(schema->attrgrpDecl,
3371 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3372 if (schema->elemDecl != NULL)
3373 xmlHashFree(schema->elemDecl,
3374 (xmlHashDeallocator) xmlSchemaFreeElement);
3375 if (schema->typeDecl != NULL)
3376 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003377 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003378 if (schema->groupDecl != NULL)
3379 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003380 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003381 if (schema->idcDef != NULL)
3382 xmlHashFree(schema->idcDef,
3383 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003384 if (schema->schemasImports != NULL)
3385 xmlHashFree(schema->schemasImports,
3386 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003387 if (schema->includes != NULL) {
3388 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3389 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003390 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003391 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003392 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003393 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003394 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003395 xmlFree(schema);
3396}
3397
3398/************************************************************************
3399 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 * Debug functions *
3401 * *
3402 ************************************************************************/
3403
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003404#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003405
Daniel Veillard4255d502002-04-16 15:50:10 +00003406/**
3407 * xmlSchemaElementDump:
3408 * @elem: an element
3409 * @output: the file output
3410 *
3411 * Dump the element
3412 */
3413static void
3414xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003415 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003416 const xmlChar * namespace ATTRIBUTE_UNUSED,
3417 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003418{
3419 if (elem == NULL)
3420 return;
3421
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003422 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3423 fprintf(output, "Particle: %s", name);
3424 fprintf(output, ", term element: %s", elem->ref);
3425 if (elem->refNs != NULL)
3426 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003427 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003428 fprintf(output, "Element");
3429 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3430 fprintf(output, " (global)");
3431 fprintf(output, ": %s ", elem->name);
3432 if (namespace != NULL)
3433 fprintf(output, "ns %s", namespace);
3434 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003435 fprintf(output, "\n");
3436 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003437 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003438 if (elem->maxOccurs >= UNBOUNDED)
3439 fprintf(output, "max: unbounded\n");
3440 else if (elem->maxOccurs != 1)
3441 fprintf(output, "max: %d\n", elem->maxOccurs);
3442 else
3443 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003444 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003445 /*
3446 * Misc other properties.
3447 */
3448 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3449 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3450 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3451 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3452 (elem->id != NULL)) {
3453 fprintf(output, " props: ");
3454 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3455 fprintf(output, "[fixed] ");
3456 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3457 fprintf(output, "[default] ");
3458 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3459 fprintf(output, "[abstract] ");
3460 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3461 fprintf(output, "[nillable] ");
3462 if (elem->id != NULL)
3463 fprintf(output, "[id: '%s'] ", elem->id);
3464 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003465 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003466 /*
3467 * Default/fixed value.
3468 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003469 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003470 fprintf(output, " value: '%s'\n", elem->value);
3471 /*
3472 * Type.
3473 */
3474 if (elem->namedType != NULL) {
3475 fprintf(output, " type: %s ", elem->namedType);
3476 if (elem->namedTypeNs != NULL)
3477 fprintf(output, "ns %s\n", elem->namedTypeNs);
3478 else
3479 fprintf(output, "\n");
3480 }
3481 /*
3482 * Substitution group.
3483 */
3484 if (elem->substGroup != NULL) {
3485 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3486 if (elem->substGroupNs != NULL)
3487 fprintf(output, "ns %s\n", elem->substGroupNs);
3488 else
3489 fprintf(output, "\n");
3490 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003491}
3492
3493/**
3494 * xmlSchemaAnnotDump:
3495 * @output: the file output
3496 * @annot: a annotation
3497 *
3498 * Dump the annotation
3499 */
3500static void
3501xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3502{
3503 xmlChar *content;
3504
3505 if (annot == NULL)
3506 return;
3507
3508 content = xmlNodeGetContent(annot->content);
3509 if (content != NULL) {
3510 fprintf(output, " Annot: %s\n", content);
3511 xmlFree(content);
3512 } else
3513 fprintf(output, " Annot: empty\n");
3514}
3515
3516/**
3517 * xmlSchemaTypeDump:
3518 * @output: the file output
3519 * @type: a type structure
3520 *
3521 * Dump a SchemaType structure
3522 */
3523static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003524xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3525{
3526 xmlChar *str = NULL;
3527 xmlSchemaTreeItemPtr term;
3528 char shift[100];
3529 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003530
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003531 if (particle == NULL)
3532 return;
3533 for (i = 0;((i < depth) && (i < 25));i++)
3534 shift[2 * i] = shift[2 * i + 1] = ' ';
3535 shift[2 * i] = shift[2 * i + 1] = 0;
3536 fprintf(output, shift);
3537 if (particle->children == NULL) {
3538 fprintf(output, "MISSING particle term\n");
3539 return;
3540 }
3541 term = particle->children;
3542 switch (term->type) {
3543 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003544 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003545 ((xmlSchemaElementPtr)term)->targetNamespace,
3546 ((xmlSchemaElementPtr)term)->name));
3547 break;
3548 case XML_SCHEMA_TYPE_SEQUENCE:
3549 fprintf(output, "SEQUENCE");
3550 break;
3551 case XML_SCHEMA_TYPE_CHOICE:
3552 fprintf(output, "CHOICE");
3553 break;
3554 case XML_SCHEMA_TYPE_ALL:
3555 fprintf(output, "ALL");
3556 break;
3557 case XML_SCHEMA_TYPE_ANY:
3558 fprintf(output, "ANY");
3559 break;
3560 default:
3561 fprintf(output, "UNKNOWN\n");
3562 return;
3563 }
3564 if (particle->minOccurs != 1)
3565 fprintf(output, " min: %d", particle->minOccurs);
3566 if (particle->maxOccurs >= UNBOUNDED)
3567 fprintf(output, " max: unbounded");
3568 else if (particle->maxOccurs != 1)
3569 fprintf(output, " max: %d", particle->maxOccurs);
3570 fprintf(output, "\n");
3571 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3572 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3573 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3574 (term->children != NULL)) {
3575 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3576 output, depth +1);
3577 }
3578 if (particle->next != NULL)
3579 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3580 output, depth);
3581}
3582/**
3583 * xmlSchemaTypeDump:
3584 * @output: the file output
3585 * @type: a type structure
3586 *
3587 * Dump a SchemaType structure
3588 */
3589static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003590xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3591{
3592 if (type == NULL) {
3593 fprintf(output, "Type: NULL\n");
3594 return;
3595 }
3596 fprintf(output, "Type: ");
3597 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003598 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003600 fprintf(output, "no name ");
3601 if (type->targetNamespace != NULL)
3602 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 switch (type->type) {
3604 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003605 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003606 break;
3607 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 break;
3610 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003611 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 break;
3613 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003614 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 break;
3616 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003617 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 break;
3619 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003620 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 break;
3622 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003623 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 break;
3625 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003626 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 break;
3628 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003629 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 break;
3631 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003632 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003634 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003635 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003637 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003638 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003639 break;
3640 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003641 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003642 break;
3643 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003644 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 break;
3646 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003647 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 break;
3649 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003650 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 break;
3652 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003653 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003654 break;
3655 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003656 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 break;
3658 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003659 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003660 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 }
3662 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003663 if (type->base != NULL) {
3664 fprintf(output, " base type: %s", type->base);
3665 if (type->baseNs != NULL)
3666 fprintf(output, " ns %s\n", type->baseNs);
3667 else
3668 fprintf(output, "\n");
3669 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 if (type->annot != NULL)
3671 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003672#ifdef DUMP_CONTENT_MODEL
3673 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3674 (type->subtypes != NULL)) {
3675 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3676 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003678#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003679}
3680
3681/**
3682 * xmlSchemaDump:
3683 * @output: the file output
3684 * @schema: a schema structure
3685 *
3686 * Dump a Schema structure.
3687 */
3688void
3689xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3690{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003691 if (output == NULL)
3692 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003693 if (schema == NULL) {
3694 fprintf(output, "Schemas: NULL\n");
3695 return;
3696 }
3697 fprintf(output, "Schemas: ");
3698 if (schema->name != NULL)
3699 fprintf(output, "%s, ", schema->name);
3700 else
3701 fprintf(output, "no name, ");
3702 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003703 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 else
3705 fprintf(output, "no target namespace");
3706 fprintf(output, "\n");
3707 if (schema->annot != NULL)
3708 xmlSchemaAnnotDump(output, schema->annot);
3709
3710 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3711 output);
3712 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003713 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003714}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003715
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003716#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003717/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003718 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003719 * @vctxt: the WXS validation context
3720 *
3721 * Displays the current IDC table for debug purposes.
3722 */
3723static void
3724xmlSchemaDebugDumpIDCTable(FILE * output,
3725 const xmlChar *namespaceName,
3726 const xmlChar *localName,
3727 xmlSchemaPSVIIDCBindingPtr bind)
3728{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003729 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003730 xmlSchemaPSVIIDCNodePtr tab;
3731 xmlSchemaPSVIIDCKeyPtr key;
3732 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003733
3734 fprintf(output, "IDC: TABLES on %s\n",
3735 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003736 FREE_AND_NULL(str)
3737
3738 if (bind == NULL)
3739 return;
3740 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741 fprintf(output, "IDC: BINDING %s\n",
3742 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003743 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003744 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003745 for (i = 0; i < bind->nbNodes; i++) {
3746 tab = bind->nodeTable[i];
3747 fprintf(output, " ( ");
3748 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 key = tab->keys[j];
3750 if ((key != NULL) && (key->val != NULL)) {
3751 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003752 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003753 fprintf(output, "\"%s\" ", value);
3754 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003755 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003756 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003757 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003758 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003759 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003760 else
3761 fprintf(output, "(key missing), ");
3762 }
3763 fprintf(output, ")\n");
3764 }
3765 bind = bind->next;
3766 } while (bind != NULL);
3767}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003768#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003769#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003770
3771/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003772 * *
3773 * Utilities *
3774 * *
3775 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003776
Daniel Veillardc0826a72004-08-10 14:17:33 +00003777/**
3778 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003779 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003780 * @name: the name of the attribute
3781 *
3782 * Seeks an attribute with a name of @name in
3783 * no namespace.
3784 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003785 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003786 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003787static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003788xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003789{
3790 xmlAttrPtr prop;
3791
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003792 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003793 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003794 prop = node->properties;
3795 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003796 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003797 return(prop);
3798 prop = prop->next;
3799 }
3800 return (NULL);
3801}
3802
3803/**
3804 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003805 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003806 * @uri: the uri
3807 * @name: the name of the attribute
3808 *
3809 * Seeks an attribute with a local name of @name and
3810 * a namespace URI of @uri.
3811 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003812 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003813 */
3814static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003815xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003816{
3817 xmlAttrPtr prop;
3818
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003819 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003820 return(NULL);
3821 prop = node->properties;
3822 while (prop != NULL) {
3823 if ((prop->ns != NULL) &&
3824 xmlStrEqual(prop->name, BAD_CAST name) &&
3825 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003826 return(prop);
3827 prop = prop->next;
3828 }
3829 return (NULL);
3830}
3831
3832static const xmlChar *
3833xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3834{
3835 xmlChar *val;
3836 const xmlChar *ret;
3837
3838 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003839 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003840 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003841 ret = xmlDictLookup(ctxt->dict, val, -1);
3842 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003843 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003844}
3845
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003846/**
3847 * xmlSchemaGetProp:
3848 * @ctxt: the parser context
3849 * @node: the node
3850 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003852 * Read a attribute value and internalize the string
3853 *
3854 * Returns the string or NULL if not present.
3855 */
3856static const xmlChar *
3857xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3858 const char *name)
3859{
3860 xmlChar *val;
3861 const xmlChar *ret;
3862
3863 val = xmlGetProp(node, BAD_CAST name);
3864 if (val == NULL)
3865 return(NULL);
3866 ret = xmlDictLookup(ctxt->dict, val, -1);
3867 xmlFree(val);
3868 return(ret);
3869}
3870
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003871/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003872 * *
3873 * Parsing functions *
3874 * *
3875 ************************************************************************/
3876
3877/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003878 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003879 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003880 * @name: the element name
3881 * @ns: the element namespace
3882 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003883 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003884 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003885 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 */
3887static xmlSchemaElementPtr
3888xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003889 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003890{
3891 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892
3893 if ((name == NULL) || (schema == NULL))
3894 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003895
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003896 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003897 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003898 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003899 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003900 } else
3901 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003902 /*
3903 * This one was removed, since top level element declarations have
3904 * the target namespace specified in targetNamespace of the <schema>
3905 * information element, even if elementFormDefault is "unqualified".
3906 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003907
William M. Bracke7091952004-05-11 15:09:58 +00003908 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003909 if (xmlStrEqual(namespace, schema->targetNamespace))
3910 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3911 else
3912 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003913 if ((ret != NULL) &&
3914 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003915 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003916 }
William M. Bracke7091952004-05-11 15:09:58 +00003917 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003918
William M. Brack2f2a6632004-08-20 23:09:47 +00003919 /*
3920 * Removed since imported components will be hold by the main schema only.
3921 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003922 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003923 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003924 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003925 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003926 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003927 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003928 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3929 return (ret);
3930 } else
3931 ret = NULL;
3932 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003933 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003934#ifdef DEBUG
3935 if (ret == NULL) {
3936 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003937 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003938 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003939 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003940 namespace);
3941 }
3942#endif
3943 return (ret);
3944}
3945
3946/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003947 * xmlSchemaGetType:
3948 * @schema: the schemas context
3949 * @name: the type name
3950 * @ns: the type namespace
3951 *
3952 * Lookup a type in the schemas or the predefined types
3953 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003954 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 */
3956static xmlSchemaTypePtr
3957xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003958 const xmlChar * namespace)
3959{
Daniel Veillard4255d502002-04-16 15:50:10 +00003960 xmlSchemaTypePtr ret;
3961
3962 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003963 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003965 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003966 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003967 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 }
3969 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003970 if (ret != NULL)
3971 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003972 /*
3973 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003974 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003975 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003976 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003977 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003978 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003979 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003980 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003981 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3982 return (ret);
3983 } else
3984 ret = NULL;
3985 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003986 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003987#ifdef DEBUG
3988 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003989 if (namespace == NULL)
3990 fprintf(stderr, "Unable to lookup type %s", name);
3991 else
3992 fprintf(stderr, "Unable to lookup type %s:%s", name,
3993 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003994 }
3995#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003996 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003997}
3998
Daniel Veillard3646d642004-06-02 19:19:14 +00003999/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004000 * xmlSchemaGetAttributeDecl:
4001 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004002 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004003 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004004 *
4005 * Lookup a an attribute in the schema or imported schemas
4006 *
4007 * Returns the attribute declaration or NULL if not found.
4008 */
4009static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004010xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004011 const xmlChar * namespace)
4012{
4013 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004014
4015 if ((name == NULL) || (schema == NULL))
4016 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004017
4018
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4020 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004021 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004022 else
4023 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004024 /*
4025 * Removed, since imported components will be hold by the main schema only.
4026 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004028 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004029 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004030 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004031 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004032 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004033 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4034 return (ret);
4035 } else
4036 ret = NULL;
4037 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004038 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004039#ifdef DEBUG
4040 if (ret == NULL) {
4041 if (namespace == NULL)
4042 fprintf(stderr, "Unable to lookup attribute %s", name);
4043 else
4044 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4045 namespace);
4046 }
4047#endif
4048 return (ret);
4049}
4050
4051/**
4052 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004053 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004054 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004055 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004056 *
4057 * Lookup a an attribute group in the schema or imported schemas
4058 *
4059 * Returns the attribute group definition or NULL if not found.
4060 */
4061static xmlSchemaAttributeGroupPtr
4062xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4063 const xmlChar * namespace)
4064{
4065 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004066
4067 if ((name == NULL) || (schema == NULL))
4068 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004069
4070
Daniel Veillard3646d642004-06-02 19:19:14 +00004071 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4072 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004073 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004074 else
4075 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004076 /*
4077 * Removed since imported components will be hold by the main schema only.
4078 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004080 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004081 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004082 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 if (import != NULL) {
4084 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4085 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4086 return (ret);
4087 else
4088 ret = NULL;
4089 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004090 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004091#ifdef DEBUG
4092 if (ret == NULL) {
4093 if (namespace == NULL)
4094 fprintf(stderr, "Unable to lookup attribute group %s", name);
4095 else
4096 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4097 namespace);
4098 }
4099#endif
4100 return (ret);
4101}
4102
4103/**
4104 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004105 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004106 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004107 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004108 *
4109 * Lookup a group in the schema or imported schemas
4110 *
4111 * Returns the group definition or NULL if not found.
4112 */
4113static xmlSchemaTypePtr
4114xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4115 const xmlChar * namespace)
4116{
4117 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004118
4119 if ((name == NULL) || (schema == NULL))
4120 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004121
Daniel Veillard3646d642004-06-02 19:19:14 +00004122 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004123 /*
4124 * Removed since imported components will be hold by the main schema only.
4125 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004126 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004127 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004128 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004129 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 if (import != NULL) {
4131 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4132 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4133 return (ret);
4134 else
4135 ret = NULL;
4136 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004137 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004138#ifdef DEBUG
4139 if (ret == NULL) {
4140 if (namespace == NULL)
4141 fprintf(stderr, "Unable to lookup group %s", name);
4142 else
4143 fprintf(stderr, "Unable to lookup group %s:%s", name,
4144 namespace);
4145 }
4146#endif
4147 return (ret);
4148}
4149
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004150/**
4151 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004152 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004153 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004154 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004155 *
4156 * Lookup a group in the schema or imported schemas
4157 *
4158 * Returns the group definition or NULL if not found.
4159 */
4160static xmlSchemaTreeItemPtr
4161xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4162 xmlSchemaTypeType itemType,
4163 const xmlChar *name,
4164 const xmlChar *targetNs)
4165{
4166 switch (itemType) {
4167 case XML_SCHEMA_TYPE_GROUP:
4168 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4169 name, targetNs));
4170 case XML_SCHEMA_TYPE_ELEMENT:
4171 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4172 name, targetNs));
4173 default:
4174 return (NULL);
4175 }
4176}
4177
Daniel Veillard4255d502002-04-16 15:50:10 +00004178/************************************************************************
4179 * *
4180 * Parsing functions *
4181 * *
4182 ************************************************************************/
4183
4184#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004185 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004186
4187/**
4188 * xmlSchemaIsBlank:
4189 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004190 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004191 *
4192 * Check if a string is ignorable
4193 *
4194 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4195 */
4196static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004197xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004198{
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004200 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004201 if (len < 0) {
4202 while (*str != 0) {
4203 if (!(IS_BLANK_CH(*str)))
4204 return (0);
4205 str++;
4206 }
4207 } else while ((*str != 0) && (len != 0)) {
4208 if (!(IS_BLANK_CH(*str)))
4209 return (0);
4210 str++;
4211 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004212 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004213
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004214 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004215}
4216
4217/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004218 * xmlSchemaAddAssembledItem:
4219 * @ctxt: a schema parser context
4220 * @schema: the schema being built
4221 * @item: the item
4222 *
4223 * Add a item to the schema's list of current items.
4224 * This is used if the schema was already constructed and
4225 * new schemata need to be added to it.
4226 * *WARNING* this interface is highly subject to change.
4227 *
4228 * Returns 0 if suceeds and -1 if an internal error occurs.
4229 */
4230static int
4231xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4232 xmlSchemaTypePtr item)
4233{
4234 static int growSize = 100;
4235 xmlSchemaAssemblePtr ass;
4236
4237 ass = ctxt->assemble;
4238 if (ass->sizeItems < 0) {
4239 /* If disabled. */
4240 return (0);
4241 }
4242 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004243 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004244 if (ass->items == NULL) {
4245 xmlSchemaPErrMemory(ctxt,
4246 "allocating new item buffer", NULL);
4247 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004248 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004249 ass->sizeItems = growSize;
4250 } else if (ass->sizeItems <= ass->nbItems) {
4251 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004252 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004253 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4254 if (ass->items == NULL) {
4255 xmlSchemaPErrMemory(ctxt,
4256 "growing item buffer", NULL);
4257 ass->sizeItems = 0;
4258 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004259 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004260 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004261 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004262 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4263 return (0);
4264}
4265
4266/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004267 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004268 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 * @schema: the schema being built
4270 * @name: the item name
4271 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004272 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004273 * *WARNING* this interface is highly subject to change
4274 *
4275 * Returns the new struture or NULL in case of error
4276 */
4277static xmlSchemaNotationPtr
4278xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004279 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004280{
4281 xmlSchemaNotationPtr ret = NULL;
4282 int val;
4283
4284 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4285 return (NULL);
4286
4287 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004288 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 if (schema->notaDecl == NULL)
4290 return (NULL);
4291
4292 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4293 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 return (NULL);
4296 }
4297 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004298 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4300 ret);
4301 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004302 /*
4303 * TODO: This should never happen, since a unique name will be computed.
4304 * If it fails, then an other internal error must have occured.
4305 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4307 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004308 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004310 xmlFree(ret);
4311 return (NULL);
4312 }
4313 return (ret);
4314}
4315
4316
4317/**
4318 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004319 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004320 * @schema: the schema being built
4321 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004322 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 *
4324 * Add an XML schema Attrribute declaration
4325 * *WARNING* this interface is highly subject to change
4326 *
4327 * Returns the new struture or NULL in case of error
4328 */
4329static xmlSchemaAttributePtr
4330xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004331 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004333{
4334 xmlSchemaAttributePtr ret = NULL;
4335 int val;
4336
4337 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4338 return (NULL);
4339
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004340#ifdef DEBUG
4341 fprintf(stderr, "Adding attribute %s\n", name);
4342 if (namespace != NULL)
4343 fprintf(stderr, " target namespace %s\n", namespace);
4344#endif
4345
Daniel Veillard4255d502002-04-16 15:50:10 +00004346 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004347 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 if (schema->attrDecl == NULL)
4349 return (NULL);
4350
4351 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4352 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004353 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 return (NULL);
4355 }
4356 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004357 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004358 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004360 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004361 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004362 if (topLevel) {
4363 xmlSchemaPCustomErr(ctxt,
4364 XML_SCHEMAP_REDEFINED_ATTR,
4365 NULL, NULL, node,
4366 "A global attribute declaration with the name '%s' does "
4367 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004368 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004369 return (NULL);
4370 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004371 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004372 /*
4373 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4374 * in the scenario:
4375 * 1. multiple top-level complex types have different target
4376 * namespaces but have the SAME NAME; this can happen if
4377 * schemata are imported
4378 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004379 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004381 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004382 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004383 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004384 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004385
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004386 if (val != 0) {
4387 xmlSchemaPCustomErr(ctxt,
4388 XML_SCHEMAP_INTERNAL,
4389 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004390 "Internal error: xmlSchemaAddAttribute, "
4391 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004392 "could not be added to the hash.", name);
4393 xmlFree(ret);
4394 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004395 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004396 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004398 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004399 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004400 return (ret);
4401}
4402
4403/**
4404 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004405 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 * @schema: the schema being built
4407 * @name: the item name
4408 *
4409 * Add an XML schema Attrribute Group declaration
4410 *
4411 * Returns the new struture or NULL in case of error
4412 */
4413static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004415 xmlSchemaPtr schema, const xmlChar * name,
4416 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004417{
4418 xmlSchemaAttributeGroupPtr ret = NULL;
4419 int val;
4420
4421 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4422 return (NULL);
4423
4424 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004425 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 if (schema->attrgrpDecl == NULL)
4427 return (NULL);
4428
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 ret =
4430 (xmlSchemaAttributeGroupPtr)
4431 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004433 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 return (NULL);
4435 }
4436 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004437 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004439 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004441 xmlSchemaPCustomErr(ctxt,
4442 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4443 NULL, NULL, node,
4444 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004445 xmlFree(ret);
4446 return (NULL);
4447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004448 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004449 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004450 return (ret);
4451}
4452
4453/**
4454 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004455 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 * @schema: the schema being built
4457 * @name: the type name
4458 * @namespace: the type namespace
4459 *
4460 * Add an XML schema Element declaration
4461 * *WARNING* this interface is highly subject to change
4462 *
4463 * Returns the new struture or NULL in case of error
4464 */
4465static xmlSchemaElementPtr
4466xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004467 const xmlChar * name, const xmlChar * namespace,
4468 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004469{
4470 xmlSchemaElementPtr ret = NULL;
4471 int val;
4472
4473 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4474 return (NULL);
4475
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004476#ifdef DEBUG
4477 fprintf(stderr, "Adding element %s\n", name);
4478 if (namespace != NULL)
4479 fprintf(stderr, " target namespace %s\n", namespace);
4480#endif
4481
Daniel Veillard4255d502002-04-16 15:50:10 +00004482 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004483 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 if (schema->elemDecl == NULL)
4485 return (NULL);
4486
4487 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4488 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004489 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 return (NULL);
4491 }
4492 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004493 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004494 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004495 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004496 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004497 if (topLevel) {
4498 xmlSchemaPCustomErr(ctxt,
4499 XML_SCHEMAP_REDEFINED_ELEMENT,
4500 NULL, NULL, node,
4501 "A global element declaration with the name '%s' does "
4502 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 xmlFree(ret);
4504 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004506 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004507
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004508 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004509 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004510 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004511 if (val != 0) {
4512 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004513 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004514 NULL, NULL, node,
4515 "Internal error: xmlSchemaAddElement, "
4516 "a dublicate element declaration with the name '%s' "
4517 "could not be added to the hash.", name);
4518 xmlFree(ret);
4519 return (NULL);
4520 }
4521 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004522
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004524 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004525 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004526 return (ret);
4527}
4528
4529/**
4530 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004531 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004532 * @schema: the schema being built
4533 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004534 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004535 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004536 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 * *WARNING* this interface is highly subject to change
4538 *
4539 * Returns the new struture or NULL in case of error
4540 */
4541static xmlSchemaTypePtr
4542xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004543 const xmlChar * name, const xmlChar * namespace,
4544 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004545{
4546 xmlSchemaTypePtr ret = NULL;
4547 int val;
4548
4549 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4550 return (NULL);
4551
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004552#ifdef DEBUG
4553 fprintf(stderr, "Adding type %s\n", name);
4554 if (namespace != NULL)
4555 fprintf(stderr, " target namespace %s\n", namespace);
4556#endif
4557
Daniel Veillard4255d502002-04-16 15:50:10 +00004558 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004559 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 if (schema->typeDecl == NULL)
4561 return (NULL);
4562
4563 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4564 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004565 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 return (NULL);
4567 }
4568 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004569 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004570 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004571 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004572 if (val != 0) {
4573 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004574 xmlSchemaPCustomErr(ctxt,
4575 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004576 NULL, NULL, node,
4577 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004578 xmlFree(ret);
4579 return (NULL);
4580 } else {
4581 xmlSchemaTypePtr prev;
4582
4583 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4584 if (prev == NULL) {
4585 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004586 XML_ERR_INTERNAL_ERROR,
4587 "Internal error: xmlSchemaAddType, on type "
4588 "'%s'.\n",
4589 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004590 xmlFree(ret);
4591 return (NULL);
4592 }
4593 ret->redef = prev->redef;
4594 prev->redef = ret;
4595 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004596 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004597 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004598 ret->minOccurs = 1;
4599 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004600 ret->attributeUses = NULL;
4601 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004602 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004603 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004604 return (ret);
4605}
4606
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004607static xmlSchemaQNameRefPtr
4608xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4609 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004611 const xmlChar *refNs)
4612{
4613 xmlSchemaQNameRefPtr ret;
4614
4615 ret = (xmlSchemaQNameRefPtr)
4616 xmlMalloc(sizeof(xmlSchemaQNameRef));
4617 if (ret == NULL) {
4618 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4619 NULL);
4620 return (NULL);
4621 }
4622 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4623 ret->name = refName;
4624 ret->targetNamespace = refNs;
4625 ret->item = NULL;
4626 ret->itemType = refType;
4627 /*
4628 * Store the reference item in the schema.
4629 */
4630 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4631 return (ret);
4632}
4633
4634/**
4635 * xmlSchemaAddModelGroup:
4636 * @ctxt: a schema parser context
4637 * @schema: the schema being built
4638 * @type: the "compositor" type of the model group
4639 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004640 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004641 *
4642 * Adds a schema model group
4643 * *WARNING* this interface is highly subject to change
4644 *
4645 * Returns the new struture or NULL in case of error
4646 */
4647static xmlSchemaModelGroupPtr
4648xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4649 xmlSchemaTypeType type, const xmlChar **container,
4650 xmlNodePtr node)
4651{
4652 xmlSchemaModelGroupPtr ret = NULL;
4653 xmlChar buf[30];
4654
4655 if ((ctxt == NULL) || (schema == NULL))
4656 return (NULL);
4657
4658#ifdef DEBUG
4659 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004660#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004661 ret = (xmlSchemaModelGroupPtr)
4662 xmlMalloc(sizeof(xmlSchemaModelGroup));
4663 if (ret == NULL) {
4664 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4665 NULL);
4666 return (NULL);
4667 }
4668 ret->type = type;
4669 ret->annot = NULL;
4670 ret->node = node;
4671 ret->children = NULL;
4672 ret->next = NULL;
4673 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4674 if (container != NULL)
4675 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4676 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004677 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004678 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4679 } else {
4680 if (container != NULL)
4681 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4682 }
4683 if (container != NULL)
4684 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4685 /*
4686 * Add to volatile items.
4687 * TODO: this should be changed someday.
4688 */
4689 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4690 xmlFree(ret);
4691 return (NULL);
4692 }
4693 return (ret);
4694}
4695
4696
4697/**
4698 * xmlSchemaAddParticle:
4699 * @ctxt: a schema parser context
4700 * @schema: the schema being built
4701 * @node: the corresponding node in the schema doc
4702 * @min: the minOccurs
4703 * @max: the maxOccurs
4704 *
4705 * Adds an XML schema particle component.
4706 * *WARNING* this interface is highly subject to change
4707 *
4708 * Returns the new struture or NULL in case of error
4709 */
4710static xmlSchemaParticlePtr
4711xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4712 xmlNodePtr node, int min, int max)
4713{
4714 xmlSchemaParticlePtr ret = NULL;
4715 if ((ctxt == NULL) || (schema == NULL))
4716 return (NULL);
4717
4718#ifdef DEBUG
4719 fprintf(stderr, "Adding particle component\n");
4720#endif
4721 ret = (xmlSchemaParticlePtr)
4722 xmlMalloc(sizeof(xmlSchemaParticle));
4723 if (ret == NULL) {
4724 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4725 NULL);
4726 return (NULL);
4727 }
4728 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4729 ret->annot = NULL;
4730 ret->node = node;
4731 ret->minOccurs = min;
4732 ret->maxOccurs = max;
4733 ret->next = NULL;
4734 ret->children = NULL;
4735
4736 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4737 xmlFree(ret);
4738 return (NULL);
4739 }
4740 return (ret);
4741}
4742
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004743/**
4744 * xmlSchemaAddGroup:
4745 * @ctxt: a schema validation context
4746 * @schema: the schema being built
4747 * @name: the group name
4748 *
4749 * Add an XML schema Group definition
4750 *
4751 * Returns the new struture or NULL in case of error
4752 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004753static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004754xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004755 const xmlChar *name, const xmlChar *namespaceName,
4756 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004757{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004758 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004759 int val;
4760
4761 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4762 return (NULL);
4763
4764 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004765 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004766 if (schema->groupDecl == NULL)
4767 return (NULL);
4768
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004769 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004770 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004771 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004772 return (NULL);
4773 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004774 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004775 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004776 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 ret->node = node;
4778 ret->targetNamespace = namespaceName;
4779 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004781 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004782 XML_SCHEMAP_REDEFINED_GROUP,
4783 NULL, NULL, node,
4784 "A global model group definition with the name '%s' does already "
4785 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004786 xmlFree(ret);
4787 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004788 }
4789 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004790 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004791 return (ret);
4792}
4793
Daniel Veillard3646d642004-06-02 19:19:14 +00004794/**
4795 * xmlSchemaNewWildcardNs:
4796 * @ctxt: a schema validation context
4797 *
4798 * Creates a new wildcard namespace constraint.
4799 *
4800 * Returns the new struture or NULL in case of error
4801 */
4802static xmlSchemaWildcardNsPtr
4803xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4804{
4805 xmlSchemaWildcardNsPtr ret;
4806
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004807 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004808 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4809 if (ret == NULL) {
4810 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004811 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004812 }
4813 ret->value = NULL;
4814 ret->next = NULL;
4815 return (ret);
4816}
4817
4818/**
4819 * xmlSchemaAddWildcard:
4820 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004821 * @schema: a schema
4822 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004823 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004824 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004825 *
4826 * Returns the new struture or NULL in case of error
4827 */
4828static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004829xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4830 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004831{
4832 xmlSchemaWildcardPtr ret = NULL;
4833
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004834 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004835 return (NULL);
4836
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004837#ifdef DEBUG
4838 fprintf(stderr, "Adding wildcard component\n");
4839#endif
4840
Daniel Veillard3646d642004-06-02 19:19:14 +00004841 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4842 if (ret == NULL) {
4843 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4844 return (NULL);
4845 }
4846 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004848 ret->minOccurs = 1;
4849 ret->maxOccurs = 1;
4850
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004851 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4852 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4853 "Failed to add a wildcard component to the list", NULL);
4854 xmlFree(ret);
4855 return (NULL);
4856 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004857 return (ret);
4858}
4859
Daniel Veillard4255d502002-04-16 15:50:10 +00004860/************************************************************************
4861 * *
4862 * Utilities for parsing *
4863 * *
4864 ************************************************************************/
4865
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004866#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004867/**
4868 * xmlGetQNameProp:
4869 * @ctxt: a schema validation context
4870 * @node: a subtree containing XML Schema informations
4871 * @name: the attribute name
4872 * @namespace: the result namespace if any
4873 *
4874 * Extract a QName Attribute value
4875 *
4876 * Returns the NCName or NULL if not found, and also update @namespace
4877 * with the namespace URI
4878 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004879static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004880xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004881 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004882{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004883 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004884 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004885 const xmlChar *ret, *prefix;
4886 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004887 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004888
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004890 attr = xmlSchemaGetPropNode(node, name);
4891 if (attr == NULL)
4892 return (NULL);
4893 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004894
Daniel Veillard4255d502002-04-16 15:50:10 +00004895 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004897
Daniel Veillardba0153a2004-04-01 10:42:31 +00004898 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004899 ns = xmlSearchNs(node->doc, node, 0);
4900 if (ns) {
4901 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4902 return (val);
4903 }
4904 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004905 ret = xmlSplitQName3(val, &len);
4906 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004907 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004908 }
4909 ret = xmlDictLookup(ctxt->dict, ret, -1);
4910 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004911
4912 ns = xmlSearchNs(node->doc, node, prefix);
4913 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004914 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4915 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004916 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004917 "The QName value '%s' has no corresponding namespace "
4918 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004920 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004921 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004923}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004924#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004925
4926/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004927 * xmlSchemaPValAttrNodeQNameValue:
4928 * @ctxt: a schema parser context
4929 * @schema: the schema context
4930 * @ownerDes: the designation of the parent element
4931 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004932 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004933 * @local: the resulting local part if found, the attribute value otherwise
4934 * @uri: the resulting namespace URI if found
4935 *
4936 * Extracts the local name and the URI of a QName value and validates it.
4937 * This one is intended to be used on attribute values that
4938 * should resolve to schema components.
4939 *
4940 * Returns 0, in case the QName is valid, a positive error code
4941 * if not valid and -1 if an internal error occurs.
4942 */
4943static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004944xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004945 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004946 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004947 xmlSchemaTypePtr ownerItem,
4948 xmlAttrPtr attr,
4949 const xmlChar *value,
4950 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004951 const xmlChar **local)
4952{
4953 const xmlChar *pref;
4954 xmlNsPtr ns;
4955 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004956
Daniel Veillardc0826a72004-08-10 14:17:33 +00004957 *uri = NULL;
4958 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004959 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004960 if (ret > 0) {
4961 xmlSchemaPSimpleTypeErr(ctxt,
4962 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4963 ownerItem, (xmlNodePtr) attr,
4964 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4965 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004966 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004967 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004968 } else if (ret < 0)
4969 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004970
4971 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004972 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4973 if (ns)
4974 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4975 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4976 /*
4977 * This one takes care of included schemas with no
4978 * target namespace.
4979 */
4980 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004982 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004983 return (0);
4984 }
4985 /*
4986 * At this point xmlSplitQName3 has to return a local name.
4987 */
4988 *local = xmlSplitQName3(value, &len);
4989 *local = xmlDictLookup(ctxt->dict, *local, -1);
4990 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4992 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004993 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004994 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004995 ownerItem, (xmlNodePtr) attr,
4996 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
4997 "The value '%s' of simple type 'xs:QName' has no "
4998 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 return (ctxt->err);
5000 } else {
5001 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005002 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005003 return (0);
5004}
5005
5006/**
5007 * xmlSchemaPValAttrNodeQName:
5008 * @ctxt: a schema parser context
5009 * @schema: the schema context
5010 * @ownerDes: the designation of the owner element
5011 * @ownerItem: the owner as a schema object
5012 * @attr: the attribute node
5013 * @local: the resulting local part if found, the attribute value otherwise
5014 * @uri: the resulting namespace URI if found
5015 *
5016 * Extracts and validates the QName of an attribute value.
5017 * This one is intended to be used on attribute values that
5018 * should resolve to schema components.
5019 *
5020 * Returns 0, in case the QName is valid, a positive error code
5021 * if not valid and -1 if an internal error occurs.
5022 */
5023static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005024xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005025 xmlSchemaPtr schema,
5026 xmlChar **ownerDes,
5027 xmlSchemaTypePtr ownerItem,
5028 xmlAttrPtr attr,
5029 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005030 const xmlChar **local)
5031{
5032 const xmlChar *value;
5033
5034 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005035 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5036 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005037}
5038
5039/**
5040 * xmlSchemaPValAttrQName:
5041 * @ctxt: a schema parser context
5042 * @schema: the schema context
5043 * @ownerDes: the designation of the parent element
5044 * @ownerItem: the owner as a schema object
5045 * @ownerElem: the parent node of the attribute
5046 * @name: the name of the attribute
5047 * @local: the resulting local part if found, the attribute value otherwise
5048 * @uri: the resulting namespace URI if found
5049 *
5050 * Extracts and validates the QName of an attribute value.
5051 *
5052 * Returns 0, in case the QName is valid, a positive error code
5053 * if not valid and -1 if an internal error occurs.
5054 */
5055static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005056xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5057 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005058 xmlChar **ownerDes,
5059 xmlSchemaTypePtr ownerItem,
5060 xmlNodePtr ownerElem,
5061 const char *name,
5062 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005063 const xmlChar **local)
5064{
5065 xmlAttrPtr attr;
5066
5067 attr = xmlSchemaGetPropNode(ownerElem, name);
5068 if (attr == NULL) {
5069 *local = NULL;
5070 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005071 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005072 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005073 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5074 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005075}
5076
5077/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005078 * xmlSchemaPValAttrID:
5079 * @ctxt: a schema parser context
5080 * @schema: the schema context
5081 * @ownerDes: the designation of the parent element
5082 * @ownerItem: the owner as a schema object
5083 * @ownerElem: the parent node of the attribute
5084 * @name: the name of the attribute
5085 *
5086 * Extracts and validates the ID of an attribute value.
5087 *
5088 * Returns 0, in case the ID is valid, a positive error code
5089 * if not valid and -1 if an internal error occurs.
5090 */
5091static int
5092xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005093 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005094 xmlSchemaTypePtr ownerItem,
5095 xmlNodePtr ownerElem,
5096 const xmlChar *name)
5097{
5098 int ret;
5099 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005100 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005101
5102 value = xmlGetNoNsProp(ownerElem, name);
5103 if (value == NULL)
5104 return (0);
5105
5106 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5107 if (attr == NULL)
5108 return (-1);
5109
5110 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005111 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005112 /*
5113 * NOTE: the IDness might have already be declared in the DTD
5114 */
5115 if (attr->atype != XML_ATTRIBUTE_ID) {
5116 xmlIDPtr res;
5117 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005118
5119 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 * TODO: Use xmlSchemaStrip here; it's not exported at this
5121 * moment.
5122 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005123 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005124 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005125 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005126 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5127 if (res == NULL) {
5128 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005129 xmlSchemaPSimpleTypeErr(ctxt,
5130 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5131 ownerItem, (xmlNodePtr) attr,
5132 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5133 NULL, NULL, "Duplicate value '%s' of simple "
5134 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005135 } else
5136 attr->atype = XML_ATTRIBUTE_ID;
5137 if (strip != NULL)
5138 xmlFree(strip);
5139 }
5140 } else if (ret > 0) {
5141 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005142 xmlSchemaPSimpleTypeErr(ctxt,
5143 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5144 ownerItem, (xmlNodePtr) attr,
5145 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5146 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5147 "not a valid 'xs:NCName'",
5148 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005149 }
5150 xmlFree(value);
5151
5152 return (ret);
5153}
5154
5155/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 * xmlGetMaxOccurs:
5157 * @ctxt: a schema validation context
5158 * @node: a subtree containing XML Schema informations
5159 *
5160 * Get the maxOccurs property
5161 *
5162 * Returns the default if not found, or the value
5163 */
5164static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005165xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5166 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005168 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005169 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005170 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005171
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005172 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5173 if (attr == NULL)
5174 return (def);
5175 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005176
5177 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005179 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5181 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005182 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005183 val, NULL, NULL, NULL);
5184 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005185 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005186 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005187 }
5188
5189 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005190 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005192 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5195 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005196 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005197 val, NULL, NULL, NULL);
5198 return (def);
5199 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005200 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005201 ret = ret * 10 + (*cur - '0');
5202 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005203 }
William M. Brack76e95df2003-10-18 16:20:14 +00005204 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005206 /*
5207 * TODO: Restrict the maximal value to Integer.
5208 */
5209 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005210 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005211 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5212 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005213 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 val, NULL, NULL, NULL);
5215 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005216 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005217 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005218}
5219
5220/**
5221 * xmlGetMinOccurs:
5222 * @ctxt: a schema validation context
5223 * @node: a subtree containing XML Schema informations
5224 *
5225 * Get the minOccurs property
5226 *
5227 * Returns the default if not found, or the value
5228 */
5229static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005230xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005231 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005232{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005233 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005234 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005235 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005236
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005237 attr = xmlSchemaGetPropNode(node, "minOccurs");
5238 if (attr == NULL)
5239 return (def);
5240 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005242 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005243 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005244 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005245 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005246 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5247 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005248 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005249 val, NULL, NULL, NULL);
5250 return (def);
5251 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005253 ret = ret * 10 + (*cur - '0');
5254 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005255 }
William M. Brack76e95df2003-10-18 16:20:14 +00005256 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005257 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005258 /*
5259 * TODO: Restrict the maximal value to Integer.
5260 */
5261 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005262 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005263 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5264 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005265 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 val, NULL, NULL, NULL);
5267 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005268 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005270}
5271
5272/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005273 * xmlSchemaPGetBoolNodeValue:
5274 * @ctxt: a schema validation context
5275 * @ownerDes: owner designation
5276 * @ownerItem: the owner as a schema item
5277 * @node: the node holding the value
5278 *
5279 * Converts a boolean string value into 1 or 0.
5280 *
5281 * Returns 0 or 1.
5282 */
5283static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005284xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5285 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005286 xmlSchemaTypePtr ownerItem,
5287 xmlNodePtr node)
5288{
5289 xmlChar *value = NULL;
5290 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005291
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005292 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005293 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005294 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005295 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005296 * can have the following legal literals {true, false, 1, 0}.
5297 */
5298 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5299 res = 1;
5300 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5301 res = 0;
5302 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5303 res = 1;
5304 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005305 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005306 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005307 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005308 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309 ownerItem, node,
5310 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5311 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005312 NULL, NULL, NULL);
5313 }
5314 if (value != NULL)
5315 xmlFree(value);
5316 return (res);
5317}
5318
5319/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005320 * xmlGetBooleanProp:
5321 * @ctxt: a schema validation context
5322 * @node: a subtree containing XML Schema informations
5323 * @name: the attribute name
5324 * @def: the default value
5325 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005326 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005327 *
5328 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005329 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005330 */
5331static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005332xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5333 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 xmlSchemaTypePtr ownerItem,
5335 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005336 const char *name, int def)
5337{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005338 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005339
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005340 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005341 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005342 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005343 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005344 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005345 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005346 * can have the following legal literals {true, false, 1, 0}.
5347 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348 if (xmlStrEqual(val, BAD_CAST "true"))
5349 def = 1;
5350 else if (xmlStrEqual(val, BAD_CAST "false"))
5351 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 else if (xmlStrEqual(val, BAD_CAST "1"))
5353 def = 1;
5354 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005355 def = 0;
5356 else {
5357 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005358 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005359 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005360 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005361 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5362 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005363 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005364 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005365}
5366
5367/************************************************************************
5368 * *
5369 * Shema extraction from an Infoset *
5370 * *
5371 ************************************************************************/
5372static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5373 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005374 xmlNodePtr node,
5375 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5377 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005378 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005380 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005381static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5382 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005383 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005384 xmlNodePtr node,
5385 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005386static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5387 ctxt,
5388 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005389 xmlNodePtr node,
5390 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005391static xmlSchemaAttributeGroupPtr
5392xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005393 xmlSchemaPtr schema, xmlNodePtr node,
5394 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005395static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5396 xmlSchemaPtr schema,
5397 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005398static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5400 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005401
5402/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005403 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005404 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005405 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005406 * @ownerDes: the designation of the parent element
5407 * @ownerItem: the schema object owner if existent
5408 * @attr: the schema attribute node being validated
5409 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005410 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005411 *
5412 * Validates a value against the given built-in type.
5413 * This one is intended to be used internally for validation
5414 * of schema attribute values during parsing of the schema.
5415 *
5416 * Returns 0 if the value is valid, a positive error code
5417 * number otherwise and -1 in case of an internal or API error.
5418 */
5419static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005420xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5421 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5422 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005423 xmlAttrPtr attr,
5424 const xmlChar *value,
5425 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005426{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005427
5428 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005429
5430 /*
5431 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5432 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005433 */
5434 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005435 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005436 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5437 PERROR_INT("xmlSchemaPValAttrNodeValue",
5438 "the given type is not a built-in type");
5439 return (-1);
5440 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005441 switch (type->builtInType) {
5442 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005443 case XML_SCHEMAS_QNAME:
5444 case XML_SCHEMAS_ANYURI:
5445 case XML_SCHEMAS_TOKEN:
5446 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005447 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5448 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005449 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005450 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005451 PERROR_INT("xmlSchemaPValAttrNodeValue",
5452 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005453 return (-1);
5454 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005455 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005456 /*
5457 * TODO: Should we use the S4S error codes instead?
5458 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005459 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005460 PERROR_INT("xmlSchemaPValAttrNodeValue",
5461 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005462 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 } else if (ret > 0) {
5464 if (VARIETY_LIST(type))
5465 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5466 else
5467 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5468 xmlSchemaPSimpleTypeErr(pctxt,
5469 ret, ownerItem, (xmlNodePtr) attr,
5470 type, NULL, value, NULL, NULL, NULL);
5471 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005472 return (ret);
5473}
5474
5475/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005476 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005477 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005478 * @ctxt: a schema parser context
5479 * @ownerDes: the designation of the parent element
5480 * @ownerItem: the schema object owner if existent
5481 * @attr: the schema attribute node being validated
5482 * @type: the built-in type to be validated against
5483 * @value: the resulting value if any
5484 *
5485 * Extracts and validates a value against the given built-in type.
5486 * This one is intended to be used internally for validation
5487 * of schema attribute values during parsing of the schema.
5488 *
5489 * Returns 0 if the value is valid, a positive error code
5490 * number otherwise and -1 in case of an internal or API error.
5491 */
5492static int
5493xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5494 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495 xmlSchemaTypePtr ownerItem,
5496 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005497 xmlSchemaTypePtr type,
5498 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005499{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005500 const xmlChar *val;
5501
5502 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 return (-1);
5504
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5506 if (value != NULL)
5507 *value = val;
5508
5509 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005510 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005511}
5512
5513/**
5514 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005516 * @ctxt: a schema parser context
5517 * @node: the element node of the attribute
5518 * @ownerDes: the designation of the parent element
5519 * @ownerItem: the schema object owner if existent
5520 * @ownerElem: the owner element node
5521 * @name: the name of the schema attribute node
5522 * @type: the built-in type to be validated against
5523 * @value: the resulting value if any
5524 *
5525 * Extracts and validates a value against the given built-in type.
5526 * This one is intended to be used internally for validation
5527 * of schema attribute values during parsing of the schema.
5528 *
5529 * Returns 0 if the value is valid, a positive error code
5530 * number otherwise and -1 in case of an internal or API error.
5531 */
5532static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005533xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005534 xmlChar **ownerDes,
5535 xmlSchemaTypePtr ownerItem,
5536 xmlNodePtr ownerElem,
5537 const char *name,
5538 xmlSchemaTypePtr type,
5539 const xmlChar **value)
5540{
5541 xmlAttrPtr attr;
5542
5543 if ((ctxt == NULL) || (type == NULL)) {
5544 if (value != NULL)
5545 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005546 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005547 }
5548 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5549 if (value != NULL)
5550 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005551 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005552 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005553 "Internal error: xmlSchemaPValAttr, the given "
5554 "type '%s' is not a built-in type.\n",
5555 type->name, NULL);
5556 return (-1);
5557 }
5558 attr = xmlSchemaGetPropNode(ownerElem, name);
5559 if (attr == NULL) {
5560 if (value != NULL)
5561 *value = NULL;
5562 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005563 }
5564 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005565 type, value));
5566}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005567
5568static int
5569xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5570 xmlSchemaPtr schema,
5571 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005572 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005573 const xmlChar *namespaceName)
5574{
5575 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005576 return (1);
5577 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5578 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005579 if (pctxt->localImports != NULL) {
5580 int i;
5581 for (i = 0; i < pctxt->nbLocalImports; i++)
5582 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5583 return (1);
5584 }
5585 if (namespaceName == NULL)
5586 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005587 NULL, (xmlSchemaTypePtr) item, node,
5588 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005589 "namespace are not valid, since not indicated by an import "
5590 "statement", NULL);
5591 else
5592 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005593 NULL, (xmlSchemaTypePtr) item, node,
5594 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005595 "namespace '%s' are not valid, since not indicated by an import "
5596 "statement", namespaceName);
5597 return (0);
5598}
5599
Daniel Veillardc0826a72004-08-10 14:17:33 +00005600/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005601 * xmlSchemaParseAttrDecls:
5602 * @ctxt: a schema validation context
5603 * @schema: the schema being built
5604 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005605 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005606 *
5607 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005608 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5610 */
5611static xmlNodePtr
5612xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5613 xmlNodePtr child, xmlSchemaTypePtr type)
5614{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005615 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005616
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005618 (IS_SCHEMA(child, "attributeGroup"))) {
5619 attr = NULL;
5620 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005621 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 } else if (IS_SCHEMA(child, "attributeGroup")) {
5623 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005624 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005625 }
5626 if (attr != NULL) {
5627 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005628 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5629 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5630 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005631 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005632 lastattr = attr;
5633 } else {
5634 lastattr->next = attr;
5635 lastattr = attr;
5636 }
5637 }
5638 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005639 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005641}
5642
5643/**
5644 * xmlSchemaParseAnnotation:
5645 * @ctxt: a schema validation context
5646 * @schema: the schema being built
5647 * @node: a subtree containing XML Schema informations
5648 *
5649 * parse a XML schema Attrribute declaration
5650 * *WARNING* this interface is highly subject to change
5651 *
William M. Bracke7091952004-05-11 15:09:58 +00005652 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005653 * 1 in case of success.
5654 */
5655static xmlSchemaAnnotPtr
5656xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5657 xmlNodePtr node)
5658{
5659 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005660 xmlNodePtr child = NULL;
5661 xmlAttrPtr attr;
5662 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005663
Daniel Veillardc0826a72004-08-10 14:17:33 +00005664 /*
5665 * INFO: S4S completed.
5666 */
5667 /*
5668 * id = ID
5669 * {any attributes with non-schema namespace . . .}>
5670 * Content: (appinfo | documentation)*
5671 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5673 return (NULL);
5674 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005675 attr = node->properties;
5676 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005677 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005678 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005679 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005680 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005681
5682 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5684 NULL, NULL, attr);
5685 }
5686 attr = attr->next;
5687 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005688 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005689 /*
5690 * And now for the children...
5691 */
5692 child = node->children;
5693 while (child != NULL) {
5694 if (IS_SCHEMA(child, "appinfo")) {
5695 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005696 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 * source = anyURI
5698 * {any attributes with non-schema namespace . . .}>
5699 * Content: ({any})*
5700 */
5701 attr = child->properties;
5702 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005703 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005704 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005705 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005706 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005707
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005708 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005709 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5710 NULL, NULL, attr);
5711 }
5712 attr = attr->next;
5713 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005714 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5715 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005716 child = child->next;
5717 } else if (IS_SCHEMA(child, "documentation")) {
5718 /* TODO: make available the content of "documentation". */
5719 /*
5720 * source = anyURI
5721 * {any attributes with non-schema namespace . . .}>
5722 * Content: ({any})*
5723 */
5724 attr = child->properties;
5725 while (attr != NULL) {
5726 if (attr->ns == NULL) {
5727 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005728 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5730 NULL, NULL, attr);
5731 }
5732 } else {
5733 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5734 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5735 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736
5737 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005738 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5739 NULL, NULL, attr);
5740 }
5741 }
5742 attr = attr->next;
5743 }
5744 /*
5745 * Attribute "xml:lang".
5746 */
5747 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5748 if (attr != NULL)
5749 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005750 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005751 child = child->next;
5752 } else {
5753 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005754 xmlSchemaPContentErr(ctxt,
5755 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005756 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5757 barked = 1;
5758 child = child->next;
5759 }
5760 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005761
Daniel Veillard4255d502002-04-16 15:50:10 +00005762 return (ret);
5763}
5764
5765/**
5766 * xmlSchemaParseFacet:
5767 * @ctxt: a schema validation context
5768 * @schema: the schema being built
5769 * @node: a subtree containing XML Schema informations
5770 *
5771 * parse a XML schema Facet declaration
5772 * *WARNING* this interface is highly subject to change
5773 *
5774 * Returns the new type structure or NULL in case of error
5775 */
5776static xmlSchemaFacetPtr
5777xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005778 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005779{
5780 xmlSchemaFacetPtr facet;
5781 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005782 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005783
5784 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5785 return (NULL);
5786
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005787 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005788 if (facet == NULL) {
5789 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5790 return (NULL);
5791 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005792 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005793 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005794 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005795 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5796 "Facet %s has no value\n", node->name, NULL);
5797 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 return (NULL);
5799 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005800 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005801 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005802 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005803 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005805 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5822 } else if (IS_SCHEMA(node, "minLength")) {
5823 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5824 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005825 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5826 "Unknown facet type %s\n", node->name, NULL);
5827 xmlSchemaFreeFacet(facet);
5828 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005830 xmlSchemaPValAttrID(ctxt, NULL,
5831 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005832 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005833 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5834 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5835 const xmlChar *fixed;
5836
5837 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5838 if (fixed != NULL) {
5839 if (xmlStrEqual(fixed, BAD_CAST "true"))
5840 facet->fixed = 1;
5841 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005842 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005843 child = node->children;
5844
5845 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5847 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005848 }
5849 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005850 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5851 "Facet %s has unexpected child content\n",
5852 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005853 }
5854 return (facet);
5855}
5856
5857/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 * xmlSchemaParseWildcardNs:
5859 * @ctxt: a schema parser context
5860 * @wildc: the wildcard, already created
5861 * @node: a subtree containing XML Schema informations
5862 *
5863 * Parses the attribute "processContents" and "namespace"
5864 * of a xsd:anyAttribute and xsd:any.
5865 * *WARNING* this interface is highly subject to change
5866 *
5867 * Returns 0 if everything goes fine, a positive error code
5868 * if something is not valid and -1 if an internal error occurs.
5869 */
5870static int
5871xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5872 xmlSchemaPtr schema,
5873 xmlSchemaWildcardPtr wildc,
5874 xmlNodePtr node)
5875{
5876 const xmlChar *pc, *ns, *dictnsItem;
5877 int ret = 0;
5878 xmlChar *nsItem;
5879 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5880 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005881
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5883 if ((pc == NULL)
5884 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5885 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5886 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5887 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5888 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5889 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5890 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005891 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005892 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005893 NULL, node,
5894 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 NULL, NULL, NULL);
5896 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005897 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005898 }
5899 /*
5900 * Build the namespace constraints.
5901 */
5902 attr = xmlSchemaGetPropNode(node, "namespace");
5903 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005904 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 wildc->any = 1;
5906 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5907 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005908 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005909 return (-1);
5910 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 wildc->negNsSet->value = schema->targetNamespace;
5912 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 const xmlChar *end, *cur;
5914
5915 cur = ns;
5916 do {
5917 while (IS_BLANK_CH(*cur))
5918 cur++;
5919 end = cur;
5920 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5921 end++;
5922 if (end == cur)
5923 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005924 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005925 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5926 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005927 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005928 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005929 NULL, (xmlNodePtr) attr,
5930 NULL,
5931 "((##any | ##other) | List of (xs:anyURI | "
5932 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 nsItem, NULL, NULL, NULL);
5934 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5935 } else {
5936 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5937 dictnsItem = schema->targetNamespace;
5938 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5939 dictnsItem = NULL;
5940 } else {
5941 /*
5942 * Validate the item (anyURI).
5943 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005944 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005945 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5946 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5947 }
5948 /*
5949 * Avoid dublicate namespaces.
5950 */
5951 tmp = wildc->nsSet;
5952 while (tmp != NULL) {
5953 if (dictnsItem == tmp->value)
5954 break;
5955 tmp = tmp->next;
5956 }
5957 if (tmp == NULL) {
5958 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5959 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005960 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005961 return (-1);
5962 }
5963 tmp->value = dictnsItem;
5964 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005965 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005966 wildc->nsSet = tmp;
5967 else
5968 lastNs->next = tmp;
5969 lastNs = tmp;
5970 }
5971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005972 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005973 xmlFree(nsItem);
5974 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005975 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005976 }
5977 return (ret);
5978}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005979
5980static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005981xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5982 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 xmlNodePtr node,
5984 int minOccurs,
5985 int maxOccurs) {
5986
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005987 if ((maxOccurs == 0) && ( minOccurs == 0))
5988 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005989 if (maxOccurs != UNBOUNDED) {
5990 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 * TODO: Maybe we should better not create the particle,
5992 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005993 * content model.
5994 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005995 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005996 * 3.9.6 Schema Component Constraint: Particle Correct
5997 *
5998 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 if (maxOccurs < 1) {
6000 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 * 2.2 {max occurs} must be greater than or equal to 1.
6002 */
6003 xmlSchemaPCustomAttrErr(ctxt,
6004 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006005 NULL, NULL,
6006 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006007 "The value must be greater than or equal to 1");
6008 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6009 } else if (minOccurs > maxOccurs) {
6010 /*
6011 * 2.1 {min occurs} must not be greater than {max occurs}.
6012 */
6013 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006014 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006015 NULL, NULL,
6016 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006017 "The value must not be greater than the value of 'maxOccurs'");
6018 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6019 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006020 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006021 return (0);
6022}
6023
Daniel Veillardc0826a72004-08-10 14:17:33 +00006024/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006025 * xmlSchemaParseAny:
6026 * @ctxt: a schema validation context
6027 * @schema: the schema being built
6028 * @node: a subtree containing XML Schema informations
6029 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006030 * Parsea a XML schema <any> element. A particle and wildcard
6031 * will be created (except if minOccurs==maxOccurs==0, in this case
6032 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 * *WARNING* this interface is highly subject to change
6034 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006035 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006036 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006037static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006038xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6039 xmlNodePtr node)
6040{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006041 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006042 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 xmlSchemaWildcardPtr wild;
6044 int min, max;
6045 xmlAttrPtr attr;
6046 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006047
6048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6049 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006050 /*
6051 * Check for illegal attributes.
6052 */
6053 attr = node->properties;
6054 while (attr != NULL) {
6055 if (attr->ns == NULL) {
6056 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6057 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6058 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6059 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6060 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006061 xmlSchemaPIllegalAttrErr(ctxt,
6062 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6063 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006064 }
6065 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006066 xmlSchemaPIllegalAttrErr(ctxt,
6067 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6068 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006069 }
6070 attr = attr->next;
6071 }
6072 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6073 /*
6074 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006075 */
6076 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6077 "(xs:nonNegativeInteger | unbounded)");
6078 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6079 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006080 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6081 /*
6082 * Create & parse the wildcard.
6083 */
6084 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6085 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006086 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006087 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006088 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006089 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006090 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006091 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006092 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006093 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006094 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006095 }
6096 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 xmlSchemaPContentErr(ctxt,
6098 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006100 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006101 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006102 /*
6103 * No component if minOccurs==maxOccurs==0.
6104 */
6105 if ((min == 0) && (max == 0)) {
6106 /* Don't free the wildcard, since it's already on the list. */
6107 return (NULL);
6108 }
6109 /*
6110 * Create the particle.
6111 */
6112 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6113 if (particle == NULL)
6114 return (NULL);
6115 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006116 wild->minOccurs = min;
6117 wild->maxOccurs = max;
6118 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006119
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006120 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006121}
6122
6123/**
6124 * xmlSchemaParseNotation:
6125 * @ctxt: a schema validation context
6126 * @schema: the schema being built
6127 * @node: a subtree containing XML Schema informations
6128 *
6129 * parse a XML schema Notation declaration
6130 *
6131 * Returns the new structure or NULL in case of error
6132 */
6133static xmlSchemaNotationPtr
6134xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006135 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006136{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006137 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 xmlSchemaNotationPtr ret;
6139 xmlNodePtr child = NULL;
6140
6141 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6142 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006143 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006144 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006145 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6146 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006147 return (NULL);
6148 }
6149 ret = xmlSchemaAddNotation(ctxt, schema, name);
6150 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006151 return (NULL);
6152 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006153 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006154
6155 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6156 node, BAD_CAST "id");
6157
6158 if (IS_SCHEMA(child, "annotation")) {
6159 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6160 child = child->next;
6161 }
6162
Daniel Veillard4255d502002-04-16 15:50:10 +00006163 child = node->children;
6164 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006165 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6166 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006167 }
6168 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006169 xmlSchemaPContentErr(ctxt,
6170 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006171 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006172 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006173 }
6174
6175 return (ret);
6176}
6177
6178/**
6179 * xmlSchemaParseAnyAttribute:
6180 * @ctxt: a schema validation context
6181 * @schema: the schema being built
6182 * @node: a subtree containing XML Schema informations
6183 *
6184 * parse a XML schema AnyAttrribute declaration
6185 * *WARNING* this interface is highly subject to change
6186 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006187 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006188 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006189static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006190xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6191 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006192{
Daniel Veillard3646d642004-06-02 19:19:14 +00006193 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006194 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006195 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006196
6197 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6198 return (NULL);
6199
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006200 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6201 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 if (ret == NULL) {
6203 return (NULL);
6204 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006205 /*
6206 * Check for illegal attributes.
6207 */
6208 attr = node->properties;
6209 while (attr != NULL) {
6210 if (attr->ns == NULL) {
6211 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6212 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6213 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006214 xmlSchemaPIllegalAttrErr(ctxt,
6215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6216 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006217 }
6218 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006219 xmlSchemaPIllegalAttrErr(ctxt,
6220 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6221 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006222 }
6223 attr = attr->next;
6224 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006225 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6226 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006227 /*
6228 * Parse the namespace list.
6229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006230 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006231 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006232 /*
6233 * And now for the children...
6234 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006235 child = node->children;
6236 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006237 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6238 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006239 }
6240 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006241 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006242 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006243 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006244 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006245 }
6246
6247 return (ret);
6248}
6249
6250
6251/**
6252 * xmlSchemaParseAttribute:
6253 * @ctxt: a schema validation context
6254 * @schema: the schema being built
6255 * @node: a subtree containing XML Schema informations
6256 *
6257 * parse a XML schema Attrribute declaration
6258 * *WARNING* this interface is highly subject to change
6259 *
William M. Bracke7091952004-05-11 15:09:58 +00006260 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006261 */
6262static xmlSchemaAttributePtr
6263xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006264 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006265{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 const xmlChar *name, *attrValue;
6267 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006268 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006269 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006270 xmlAttrPtr attr, nameAttr;
6271 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006272
6273 /*
6274 * Note that the w3c spec assumes the schema to be validated with schema
6275 * for schemas beforehand.
6276 *
6277 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006278 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006279
6280 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6281 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006282 attr = xmlSchemaGetPropNode(node, "ref");
6283 nameAttr = xmlSchemaGetPropNode(node, "name");
6284
6285 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006286 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006287 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006288 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006290 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6291 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006292 "One of the attributes 'ref' or 'name' must be present");
6293 return (NULL);
6294 }
6295 if ((topLevel) || (attr == NULL)) {
6296 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006297 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6298 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006299 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006300 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006301 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006302 isRef = 1;
6303
Daniel Veillardc0826a72004-08-10 14:17:33 +00006304 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006305 char buf[50];
6306 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006307
6308 /*
6309 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 */
6311 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6312 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6313 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006314 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006315 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006316 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006317 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006318 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 if (ret == NULL) {
6320 if (repName != NULL)
6321 xmlFree(repName);
6322 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006323 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006324 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6325 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006326 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006327 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006328 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6329 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 /*
6331 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6332 */
6333 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6335 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 "ref", "name");
6337 /*
6338 * Check for illegal attributes.
6339 */
6340 attr = node->properties;
6341 while (attr != NULL) {
6342 if (attr->ns == NULL) {
6343 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6344 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006345 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006346 * 3.2.3 : 3.2
6347 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006348 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006349 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 xmlSchemaPIllegalAttrErr(ctxt,
6351 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006352 (xmlSchemaTypePtr) ret, attr);
6353 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6354 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6355 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6357 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006358 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006359 xmlSchemaPIllegalAttrErr(ctxt,
6360 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6361 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006362 }
6363 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 xmlSchemaPIllegalAttrErr(ctxt,
6365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6366 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006367 }
6368 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006369 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006370 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006371 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372
Daniel Veillardc0826a72004-08-10 14:17:33 +00006373 /*
6374 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006375 */
6376 if (xmlSchemaPValAttrNode(ctxt,
6377 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6379 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006380 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 /*
6382 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6383 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006384 /*
6385 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6386 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006387 */
6388 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006389 xmlSchemaPSimpleTypeErr(ctxt,
6390 XML_SCHEMAP_NO_XMLNS,
6391 NULL, (xmlNodePtr) nameAttr,
6392 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6393 "The value of type 'xs:NCName' must not match 'xmlns'",
6394 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 if (repName != NULL)
6396 xmlFree(repName);
6397 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006398 }
6399 /*
6400 * Evaluate the target namespace
6401 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006402 if (topLevel) {
6403 ns = schema->targetNamespace;
6404 } else {
6405 attr = xmlSchemaGetPropNode(node, "form");
6406 if (attr != NULL) {
6407 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6408 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6409 ns = schema->targetNamespace;
6410 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006411 xmlSchemaPSimpleTypeErr(ctxt,
6412 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6413 NULL, (xmlNodePtr) attr,
6414 NULL, "(qualified | unqualified)",
6415 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006416 }
6417 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006418 ns = schema->targetNamespace;
6419 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006420 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006421 if (ret == NULL) {
6422 if (repName != NULL)
6423 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006424 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006425 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006426 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006427 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006428 if (topLevel)
6429 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006430 /*
6431 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6432 * TODO: Move this to the component layer.
6433 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 XML_SCHEMAP_NO_XSI,
6437 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 "The target namespace must not match '%s'",
6439 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006440 }
6441 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006442 * Check for illegal attributes.
6443 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 attr = node->properties;
6445 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006446 if (attr->ns == NULL) {
6447 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6448 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6449 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006450 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6451 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006452 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006453 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6454 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006455 xmlSchemaPIllegalAttrErr(ctxt,
6456 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6457 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 }
6459 }
6460 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006461 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6462 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006463 }
6464 attr = attr->next;
6465 }
6466 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006467 node, "type", &ret->typeNs, &ret->typeName);
6468 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006469 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6470 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006471 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006472 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006473 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6475 if (ret->defValue != NULL)
6476 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006477 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 * Attribute "default".
6479 */
6480 attr = xmlSchemaGetPropNode(node, "default");
6481 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006484 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 */
6486 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6487 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6488 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6489 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6491 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006493 /*
6494 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 */
6496 attr = xmlSchemaGetPropNode(node, "use");
6497 if (attr != NULL) {
6498 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6500 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6501 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6502 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6503 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6504 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6505 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006506 xmlSchemaPSimpleTypeErr(ctxt,
6507 XML_SCHEMAP_INVALID_ATTR_USE,
6508 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6509 NULL, "(optional | prohibited | required)",
6510 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006511 } else
6512 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006513 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 * 3.2.3 : 2
6515 * If default and use are both present, use must have
6516 * the actual value optional.
6517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006518 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6519 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006521 xmlSchemaPSimpleTypeErr(ctxt,
6522 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6523 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6524 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006528 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 /*
6530 * And now for the children...
6531 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006532 child = node->children;
6533 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006534 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6535 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006539 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006540 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 * 3.2.3 : 3.2
6542 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006543 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006544 */
6545 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6546 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6547 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6550 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 }
6553 } else {
6554 if (IS_SCHEMA(child, "simpleType")) {
6555 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 */
6560 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6561 &repName, (xmlSchemaTypePtr) ret, node, child,
6562 "The attribute 'type' and the <simpleType> child "
6563 "are mutually exclusive", NULL);
6564 } else
6565 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6566 child = child->next;
6567 }
6568 if (child != NULL)
6569 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6570 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6571 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006572 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006573 /*
6574 * Cleanup.
6575 */
6576 if (repName != NULL)
6577 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006578 return (ret);
6579}
6580
6581/**
6582 * xmlSchemaParseAttributeGroup:
6583 * @ctxt: a schema validation context
6584 * @schema: the schema being built
6585 * @node: a subtree containing XML Schema informations
6586 *
6587 * parse a XML schema Attribute Group declaration
6588 * *WARNING* this interface is highly subject to change
6589 *
6590 * Returns the attribute group or NULL in case of error.
6591 */
6592static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006593xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006594 xmlSchemaPtr schema, xmlNodePtr node,
6595 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006596{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006597 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006599 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006600 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006601 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006602
6603 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6604 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605
6606 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006607 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006608 if ((topLevel) || (attr == NULL)) {
6609 /*
6610 * Parse as an attribute group definition.
6611 * Note that those are allowed at top level only.
6612 */
6613 if (nameAttr == NULL) {
6614 xmlSchemaPMissingAttrErr(ctxt,
6615 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006616 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006617 return (NULL);
6618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006619 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006620 * (xmlNodePtr) nameAttr);
6621 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006622 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006623 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006624 */
6625 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006626 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006627 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6628 return (NULL);
6629 }
6630 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6631 if (ret == NULL)
6632 return (NULL);
6633 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6634 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6635 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006636 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006637 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006638 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006639 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006640
6641 /*
6642 * Parse as an attribute group definition reference.
6643 */
6644 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006645 xmlSchemaPMissingAttrErr(ctxt,
6646 XML_SCHEMAP_S4S_ATTR_MISSING,
6647 NULL, node, "ref", NULL);
6648 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006649 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006650 NULL, NULL, attr, &refNs,&ref);
6651
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006652 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006653 name = (const xmlChar *) buf;
6654 if (name == NULL) {
6655 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6656 "attribute group definition reference", node);
6657 return (NULL);
6658 }
6659 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6660 if (ret == NULL)
6661 return (NULL);
6662 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6663 ret->ref = ref;
6664 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006665 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006666 xmlSchemaCheckReference(ctxt, schema, node,
6667 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006669 /*
6670 * Check for illegal attributes.
6671 */
6672 attr = node->properties;
6673 while (attr != NULL) {
6674 if (attr->ns == NULL) {
6675 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6676 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006677 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006678 {
6679 xmlSchemaPIllegalAttrErr(ctxt,
6680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6681 NULL, NULL, attr);
6682 }
6683 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6684 xmlSchemaPIllegalAttrErr(ctxt,
6685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6686 NULL, NULL, attr);
6687 }
6688 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006689 }
6690 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006691 /*
6692 * And now for the children...
6693 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006695 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006698 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6699 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006700 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006701 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006702 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006703 if (IS_SCHEMA(child, "anyAttribute")) {
6704 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6705 child = child->next;
6706 }
6707 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006710 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6711 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006712 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006713 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006714 ctxt->container = oldcontainer;
6715 return (ret);
6716}
6717
6718/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006719 * xmlSchemaPValAttrFormDefault:
6720 * @value: the value
6721 * @flags: the flags to be modified
6722 * @flagQualified: the specific flag for "qualified"
6723 *
6724 * Returns 0 if the value is valid, 1 otherwise.
6725 */
6726static int
6727xmlSchemaPValAttrFormDefault(const xmlChar *value,
6728 int *flags,
6729 int flagQualified)
6730{
6731 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6732 if ((*flags & flagQualified) == 0)
6733 *flags |= flagQualified;
6734 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006735 return (1);
6736
William M. Brack2f2a6632004-08-20 23:09:47 +00006737 return (0);
6738}
6739
6740/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 * xmlSchemaPValAttrBlockFinal:
6742 * @value: the value
6743 * @flags: the flags to be modified
6744 * @flagAll: the specific flag for "#all"
6745 * @flagExtension: the specific flag for "extension"
6746 * @flagRestriction: the specific flag for "restriction"
6747 * @flagSubstitution: the specific flag for "substitution"
6748 * @flagList: the specific flag for "list"
6749 * @flagUnion: the specific flag for "union"
6750 *
6751 * Validates the value of the attribute "final" and "block". The value
6752 * is converted into the specified flag values and returned in @flags.
6753 *
6754 * Returns 0 if the value is valid, 1 otherwise.
6755 */
6756
6757static int
6758xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006759 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006760 int flagAll,
6761 int flagExtension,
6762 int flagRestriction,
6763 int flagSubstitution,
6764 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006765 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006766{
6767 int ret = 0;
6768
6769 /*
6770 * TODO: This does not check for dublicate entries.
6771 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006772 if ((flags == NULL) || (value == NULL))
6773 return (-1);
6774 if (value[0] == 0)
6775 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 if (xmlStrEqual(value, BAD_CAST "#all")) {
6777 if (flagAll != -1)
6778 *flags |= flagAll;
6779 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006780 if (flagExtension != -1)
6781 *flags |= flagExtension;
6782 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006783 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006784 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006785 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006786 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006787 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 *flags |= flagUnion;
6790 }
6791 } else {
6792 const xmlChar *end, *cur = value;
6793 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 do {
6796 while (IS_BLANK_CH(*cur))
6797 cur++;
6798 end = cur;
6799 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6800 end++;
6801 if (end == cur)
6802 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006803 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006804 if (xmlStrEqual(item, BAD_CAST "extension")) {
6805 if (flagExtension != -1) {
6806 if ((*flags & flagExtension) == 0)
6807 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006808 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809 ret = 1;
6810 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6811 if (flagRestriction != -1) {
6812 if ((*flags & flagRestriction) == 0)
6813 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815 ret = 1;
6816 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6817 if (flagSubstitution != -1) {
6818 if ((*flags & flagSubstitution) == 0)
6819 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006820 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006821 ret = 1;
6822 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6823 if (flagList != -1) {
6824 if ((*flags & flagList) == 0)
6825 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006826 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 ret = 1;
6828 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6829 if (flagUnion != -1) {
6830 if ((*flags & flagUnion) == 0)
6831 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006832 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006833 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 if (item != NULL)
6837 xmlFree(item);
6838 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006839 } while ((ret == 0) && (*cur != 0));
6840 }
6841
Daniel Veillardc0826a72004-08-10 14:17:33 +00006842 return (ret);
6843}
6844
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006845static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006846xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006847 xmlSchemaIDCPtr idc,
6848 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006849 xmlAttrPtr attr,
6850 int isField)
6851{
6852 xmlNodePtr node;
6853
6854 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006855 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006856 * Schema Component Constraint: Selector Value OK
6857 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006858 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006859 * in [XPath].
6860 */
6861 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006862 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006863 XML_SCHEMAP_INTERNAL,
6864 "Internal error: xmlSchemaCheckCSelectorXPath, "
6865 "the selector is not specified.\n", NULL, NULL);
6866 return (-1);
6867 }
6868 if (attr == NULL)
6869 node = idc->node;
6870 else
6871 node = (xmlNodePtr) attr;
6872 if (selector->xpath == NULL) {
6873 xmlSchemaPCustomErr(ctxt,
6874 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006875 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6876 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006877 "The XPath expression of the selector is not valid", NULL);
6878 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6879 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006880 const xmlChar **nsArray = NULL;
6881 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006882 /*
6883 * Compile the XPath expression.
6884 */
6885 /*
6886 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006887 * TODO: Call xmlPatterncompile with different options for selector/
6888 * field.
6889 */
6890 nsList = xmlGetNsList(attr->doc, attr->parent);
6891 /*
6892 * Build an array of prefixes and namespaces.
6893 */
6894 if (nsList != NULL) {
6895 int i, count = 0;
6896 xmlNsPtr ns;
6897
6898 for (i = 0; nsList[i] != NULL; i++)
6899 count++;
6900
6901 nsArray = (const xmlChar **) xmlMalloc(
6902 (count * 2 + 1) * sizeof(const xmlChar *));
6903 if (nsArray == NULL) {
6904 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6905 NULL);
6906 return (-1);
6907 }
6908 for (i = 0; i < count; i++) {
6909 ns = nsList[i];
6910 nsArray[2 * i] = nsList[i]->href;
6911 nsArray[2 * i + 1] = nsList[i]->prefix;
6912 }
6913 nsArray[count * 2] = NULL;
6914 xmlFree(nsList);
6915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006916 /*
6917 * TODO: Differentiate between "selector" and "field".
6918 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006919 if (isField)
6920 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006921 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006922 else
6923 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006924 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006925 if (nsArray != NULL)
6926 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006927
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006928 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006929 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006930 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006931 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6932 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006933 "The XPath expression '%s' could not be "
6934 "compiled", selector->xpath);
6935 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006936 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006937 }
6938 return (0);
6939}
6940
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006941#define ADD_ANNOTATION(annot) \
6942 xmlSchemaAnnotPtr cur = item->annot; \
6943 if (item->annot == NULL) { \
6944 item->annot = annot; \
6945 return (annot); \
6946 } \
6947 cur = item->annot; \
6948 if (cur->next != NULL) { \
6949 cur = cur->next; \
6950 } \
6951 cur->next = annot;
6952
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006953/**
6954 * xmlSchemaAssignAnnotation:
6955 * @item: the schema component
6956 * @annot: the annotation
6957 *
6958 * Adds the annotation to the given schema component.
6959 *
6960 * Returns the given annotaion.
6961 */
6962static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006963xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6964 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006965{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006966 if ((annItem == NULL) || (annot == NULL))
6967 return (NULL);
6968 switch (annItem->type) {
6969 case XML_SCHEMA_TYPE_ELEMENT: {
6970 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6971 ADD_ANNOTATION(annot)
6972 }
6973 break;
6974 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6975 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6976 ADD_ANNOTATION(annot)
6977 }
6978 break;
6979 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6980 case XML_SCHEMA_TYPE_ANY: {
6981 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6982 ADD_ANNOTATION(annot)
6983 }
6984 break;
6985 case XML_SCHEMA_TYPE_PARTICLE:
6986 case XML_SCHEMA_TYPE_IDC_KEY:
6987 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006988 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006989 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6990 ADD_ANNOTATION(annot)
6991 }
6992 break;
6993 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6994 xmlSchemaAttributeGroupPtr item =
6995 (xmlSchemaAttributeGroupPtr) annItem;
6996 ADD_ANNOTATION(annot)
6997 }
6998 break;
6999 case XML_SCHEMA_TYPE_NOTATION: {
7000 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7001 ADD_ANNOTATION(annot)
7002 }
7003 break;
7004 case XML_SCHEMA_FACET_MININCLUSIVE:
7005 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7006 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7007 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7008 case XML_SCHEMA_FACET_TOTALDIGITS:
7009 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7010 case XML_SCHEMA_FACET_PATTERN:
7011 case XML_SCHEMA_FACET_ENUMERATION:
7012 case XML_SCHEMA_FACET_WHITESPACE:
7013 case XML_SCHEMA_FACET_LENGTH:
7014 case XML_SCHEMA_FACET_MAXLENGTH:
7015 case XML_SCHEMA_FACET_MINLENGTH: {
7016 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7017 ADD_ANNOTATION(annot)
7018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007019 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007020 case XML_SCHEMA_TYPE_SIMPLE:
7021 case XML_SCHEMA_TYPE_COMPLEX: {
7022 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7023 ADD_ANNOTATION(annot)
7024 }
7025 break;
7026 case XML_SCHEMA_TYPE_GROUP: {
7027 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7028 ADD_ANNOTATION(annot)
7029 }
7030 break;
7031 case XML_SCHEMA_TYPE_SEQUENCE:
7032 case XML_SCHEMA_TYPE_CHOICE:
7033 case XML_SCHEMA_TYPE_ALL: {
7034 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7035 ADD_ANNOTATION(annot)
7036 }
7037 break;
7038 default:
7039 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007040 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007041 NULL, NULL, NULL,
7042 "Internal error: xmlSchemaAddAnnotation, "
7043 "The item is not a annotated schema component", NULL);
7044 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007045 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007046 return (annot);
7047}
7048
7049/**
7050 * xmlSchemaParseIDCSelectorAndField:
7051 * @ctxt: a schema validation context
7052 * @schema: the schema being built
7053 * @node: a subtree containing XML Schema informations
7054 *
7055 * Parses a XML Schema identity-contraint definition's
7056 * <selector> and <field> elements.
7057 *
7058 * Returns the parsed identity-constraint definition.
7059 */
7060static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007061xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007062 xmlSchemaPtr schema,
7063 xmlSchemaIDCPtr idc,
7064 xmlNodePtr node,
7065 int isField)
7066{
7067 xmlSchemaIDCSelectPtr item;
7068 xmlNodePtr child = NULL;
7069 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007070
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007071 /*
7072 * Check for illegal attributes.
7073 */
7074 attr = node->properties;
7075 while (attr != NULL) {
7076 if (attr->ns == NULL) {
7077 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7078 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007079 xmlSchemaPIllegalAttrErr(ctxt,
7080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7081 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007082 }
7083 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007084 xmlSchemaPIllegalAttrErr(ctxt,
7085 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7086 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007087 }
7088 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007089 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 /*
7091 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007093 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7094 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007095 xmlSchemaPErrMemory(ctxt,
7096 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007097 NULL);
7098 return (NULL);
7099 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007101 /*
7102 * Attribute "xpath" (mandatory).
7103 */
7104 attr = xmlSchemaGetPropNode(node, "xpath");
7105 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007106 xmlSchemaPMissingAttrErr(ctxt,
7107 XML_SCHEMAP_S4S_ATTR_MISSING,
7108 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 "name", NULL);
7110 } else {
7111 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7112 /*
7113 * URGENT TODO: "field"s have an other syntax than "selector"s.
7114 */
7115
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007116 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7117 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007118 xmlSchemaPErr(ctxt,
7119 (xmlNodePtr) attr,
7120 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007121 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007122 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007123 NULL, NULL);
7124 }
7125
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007127 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007128 /*
7129 * And now for the children...
7130 */
7131 child = node->children;
7132 if (IS_SCHEMA(child, "annotation")) {
7133 /*
7134 * Add the annotation to the parent IDC.
7135 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007136 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007137 xmlSchemaParseAnnotation(ctxt, schema, child));
7138 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007139 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007140 if (child != NULL) {
7141 xmlSchemaPContentErr(ctxt,
7142 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007143 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007144 NULL, "(annotation?)");
7145 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007146
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007147 return (item);
7148}
7149
7150/**
7151 * xmlSchemaParseIDC:
7152 * @ctxt: a schema validation context
7153 * @schema: the schema being built
7154 * @node: a subtree containing XML Schema informations
7155 *
7156 * Parses a XML Schema identity-contraint definition.
7157 *
7158 * Returns the parsed identity-constraint definition.
7159 */
7160static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007161xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007162 xmlSchemaPtr schema,
7163 xmlNodePtr node,
7164 xmlSchemaTypeType idcCategory,
7165 const xmlChar *targetNamespace)
7166{
7167 xmlSchemaIDCPtr item = NULL;
7168 xmlNodePtr child = NULL;
7169 xmlAttrPtr attr;
7170 const xmlChar *name = NULL;
7171 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7172 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007173
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007174 /*
7175 * Check for illegal attributes.
7176 */
7177 attr = node->properties;
7178 while (attr != NULL) {
7179 if (attr->ns == NULL) {
7180 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7181 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7182 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7183 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007184 xmlSchemaPIllegalAttrErr(ctxt,
7185 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7186 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007187 }
7188 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007189 xmlSchemaPIllegalAttrErr(ctxt,
7190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7191 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 }
7193 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007194 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 /*
7196 * Attribute "name" (mandatory).
7197 */
7198 attr = xmlSchemaGetPropNode(node, "name");
7199 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007200 xmlSchemaPMissingAttrErr(ctxt,
7201 XML_SCHEMAP_S4S_ATTR_MISSING,
7202 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 "name", NULL);
7204 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007205 } else if (xmlSchemaPValAttrNode(ctxt,
7206 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007207 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7208 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007209 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007210 /*
7211 * Create the component.
7212 */
7213 if (schema->idcDef == NULL)
7214 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007215 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007216 return (NULL);
7217
7218 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7219 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007220 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007221 "allocating an identity-constraint definition", NULL);
7222 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 /*
7225 * Add the IDC to the list of IDCs on the schema component.
7226 */
7227 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 xmlSchemaPCustomErrExt(ctxt,
7230 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007233 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007234 name, targetNamespace, NULL);
7235 xmlFree(item);
7236 return (NULL);
7237 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007238 memset(item, 0, sizeof(xmlSchemaIDC));
7239 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007240 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007241 item->node = node;
7242 /*
7243 * The target namespace of the parent element declaration.
7244 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007245 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007246 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7247 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007248 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7249 /*
7250 * Attribute "refer" (mandatory).
7251 */
7252 attr = xmlSchemaGetPropNode(node, "refer");
7253 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007254 xmlSchemaPMissingAttrErr(ctxt,
7255 XML_SCHEMAP_S4S_ATTR_MISSING,
7256 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007257 "refer", NULL);
7258 } else {
7259 /*
7260 * Create a reference item.
7261 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007262 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007263 NULL, NULL);
7264 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007265 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007266 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007267 NULL, NULL, attr,
7268 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007269 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007270 xmlSchemaCheckReference(ctxt, schema, node,
7271 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007272 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007273 }
7274 }
7275 /*
7276 * And now for the children...
7277 */
7278 child = node->children;
7279 if (IS_SCHEMA(child, "annotation")) {
7280 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7281 child = child->next;
7282 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007283 if (child == NULL) {
7284 xmlSchemaPContentErr(ctxt,
7285 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007286 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007287 "A child element is missing",
7288 "(annotation?, (selector, field+))");
7289 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007290 /*
7291 * Child element <selector>.
7292 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007293 if (IS_SCHEMA(child, "selector")) {
7294 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007295 item, child, 0);
7296 child = child->next;
7297 /*
7298 * Child elements <field>.
7299 */
7300 if (IS_SCHEMA(child, "field")) {
7301 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007302 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007303 item, child, 1);
7304 if (field != NULL) {
7305 field->index = item->nbFields;
7306 item->nbFields++;
7307 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007308 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007309 else
7310 item->fields = field;
7311 lastField = field;
7312 }
7313 child = child->next;
7314 } while (IS_SCHEMA(child, "field"));
7315 } else {
7316 xmlSchemaPContentErr(ctxt,
7317 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007319 NULL, "(annotation?, (selector, field+))");
7320 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007321 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007322 if (child != NULL) {
7323 xmlSchemaPContentErr(ctxt,
7324 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007325 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007326 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007327 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007328
7329 return (item);
7330}
7331
Daniel Veillardc0826a72004-08-10 14:17:33 +00007332/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007333 * xmlSchemaParseElement:
7334 * @ctxt: a schema validation context
7335 * @schema: the schema being built
7336 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007337 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007338 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007339 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007340 * *WARNING* this interface is highly subject to change
7341 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007342 * Returns the element declaration or a particle; NULL in case
7343 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007344 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007345static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007346xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007347 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007348{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007349 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007350 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007351 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007352 xmlNodePtr child = NULL;
7353 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007354 int min, max, isRef = 0;
7355 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007356
7357 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7358 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007359
Daniel Veillard4255d502002-04-16 15:50:10 +00007360 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007361 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007362 /*
7363 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007364 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007365 * robust.
7366 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007367 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007368 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007369 if ((topLevel) || (attr == NULL)) {
7370 if (nameAttr == NULL) {
7371 xmlSchemaPMissingAttrErr(ctxt,
7372 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007373 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007374 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007375 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007376 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007377 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007378
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007379 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007380 child = node->children;
7381 if (IS_SCHEMA(child, "annotation")) {
7382 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7383 child = child->next;
7384 }
7385 /*
7386 * Skip particle part if a global declaration.
7387 */
7388 if (topLevel)
7389 goto declaration_part;
7390 /*
7391 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007392 */
7393 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7394 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7395 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007396 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7397 if (particle == NULL)
7398 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007399
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007400 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7401
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007402 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007403 const xmlChar *refNs = NULL, *ref = NULL;
7404 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007405 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007407 */
7408 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007410 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007411 /*
7412 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007413 */
7414 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007415 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007416 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007417 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007418 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007422 attr = node->properties;
7423 while (attr != NULL) {
7424 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007425 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7426 xmlStrEqual(attr->name, BAD_CAST "name") ||
7427 xmlStrEqual(attr->name, BAD_CAST "id") ||
7428 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7429 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7430 {
7431 attr = attr->next;
7432 continue;
7433 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007434 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007435 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007436 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007437 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007438 "Only the attributes 'minOccurs', 'maxOccurs' and "
7439 "'id' are allowed in addition to 'ref'");
7440 break;
7441 }
7442 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7443 xmlSchemaPIllegalAttrErr(ctxt,
7444 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007445 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 }
7447 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007448 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007449 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007450 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007451 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007452 if (child != NULL) {
7453 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7454 NULL, NULL, node, child, NULL, "(annotation?)");
7455 }
7456 if ((min == 0) && (max == 0))
7457 goto return_null;
7458 /*
7459 * Create the reference item.
7460 */
7461 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7462 ref, refNs);
7463 if (refer == NULL)
7464 goto return_null;
7465 particle->children = (xmlSchemaTreeItemPtr) refer;
7466 particle->annot = annot;
7467 /*
7468 * Add to assembled items; the reference need to be resolved.
7469 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007470 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007471 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7472
7473 return ((xmlSchemaBasicItemPtr) particle);
7474 }
7475 /*
7476 * The declaration part ===============================================
7477 */
7478declaration_part:
7479 {
7480 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7481 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7482
7483 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007484 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007485 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007486 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007487 * Evaluate the target namespace.
7488 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007489 if (topLevel) {
7490 ns = schema->targetNamespace;
7491 } else {
7492 attr = xmlSchemaGetPropNode(node, "form");
7493 if (attr != NULL) {
7494 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7495 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007496 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007497 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007498 xmlSchemaPSimpleTypeErr(ctxt,
7499 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7500 NULL, (xmlNodePtr) attr,
7501 NULL, "(qualified | unqualified)",
7502 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007503 }
7504 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007505 ns = schema->targetNamespace;
7506 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007507 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007508 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007509 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007510 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007511 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7512 decl->node = node;
7513 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007514 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007515 * Check for illegal attributes.
7516 */
William M. Bracke7091952004-05-11 15:09:58 +00007517 attr = node->properties;
7518 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 if (attr->ns == NULL) {
7520 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7521 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007522 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007523 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007526 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7527 {
7528 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007529 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007530 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007531 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007532 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007533 xmlSchemaPIllegalAttrErr(ctxt,
7534 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7535 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007536 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007537 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7538 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007539 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7540
7541 xmlSchemaPIllegalAttrErr(ctxt,
7542 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007543 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007544 }
7545 }
7546 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547
Daniel Veillardc0826a72004-08-10 14:17:33 +00007548 xmlSchemaPIllegalAttrErr(ctxt,
7549 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007550 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007551 }
7552 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 }
William M. Bracke7091952004-05-11 15:09:58 +00007554 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 * Extract/validate attributes.
7556 */
7557 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007558 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007559 * Process top attributes of global element declarations here.
7560 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007561 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7562 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7564 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7565 &(decl->substGroupNs), &(decl->substGroup));
7566 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007567 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 /*
7570 * Attribute "final".
7571 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007572 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007573 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007574 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7575 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7576 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7577 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007578 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007579 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7580 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007581 -1,
7582 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7583 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007584 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007585 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007586 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7587 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 attrValue, NULL, NULL, NULL);
7589 }
7590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007591 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007592 /*
7593 * Attribute "block".
7594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007595 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007596 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007597 /*
7598 * Apply default "block" values.
7599 */
7600 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7601 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7602 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7603 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7604 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7605 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007607 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7608 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007609 -1,
7610 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007611 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007612 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7613 xmlSchemaPSimpleTypeErr(ctxt,
7614 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007615 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007616 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 "restriction | substitution))", attrValue,
7618 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 }
7620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007621 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007622 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007623 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007624
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 attr = xmlSchemaGetPropNode(node, "type");
7626 if (attr != NULL) {
7627 xmlSchemaPValAttrNodeQName(ctxt, schema,
7628 NULL, (xmlSchemaTypePtr) decl, attr,
7629 &(decl->namedTypeNs), &(decl->namedType));
7630 xmlSchemaCheckReference(ctxt, schema, node,
7631 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7632 }
7633 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7634 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007635 if (attr != NULL) {
7636 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007637 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007638 /*
7639 * 3.3.3 : 1
7640 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007641 */
7642 xmlSchemaPMutualExclAttrErr(ctxt,
7643 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007644 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 "default", "fixed");
7646 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007647 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7648 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007649 }
William M. Bracke7091952004-05-11 15:09:58 +00007650 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007651 /*
7652 * And now for the children...
7653 */
7654 oldcontainer = ctxt->container;
7655 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007656 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007657 /*
7658 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007660 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007661 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007662 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 xmlSchemaPContentErr(ctxt,
7664 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007665 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007666 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007668 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007669 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007670 child = child->next;
7671 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007672 /*
7673 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007674 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007675 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007677 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007678 xmlSchemaPContentErr(ctxt,
7679 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007680 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007681 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007683 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007684 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007685 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007686 }
William M. Bracke7091952004-05-11 15:09:58 +00007687 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007689 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007690 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007691 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007692 } else if (IS_SCHEMA(child, "key")) {
7693 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007694 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007695 } else if (IS_SCHEMA(child, "keyref")) {
7696 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007698 }
7699 if (lastIDC != NULL)
7700 lastIDC->next = curIDC;
7701 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007702 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007703 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007704 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007705 }
7706 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 xmlSchemaPContentErr(ctxt,
7708 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007709 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007710 NULL, "(annotation?, ((simpleType | complexType)?, "
7711 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007712 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007713 ctxt->container = oldcontainer;
7714 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007715 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007716 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007717 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007718 * different layer.
7719 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007720 FREE_AND_NULL(des)
7721 if (topLevel)
7722 return ((xmlSchemaBasicItemPtr) decl);
7723 else {
7724 particle->children = (xmlSchemaTreeItemPtr) decl;
7725 return ((xmlSchemaBasicItemPtr) particle);
7726 }
7727
7728return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007729 FREE_AND_NULL(des);
7730 if (annot != NULL) {
7731 if (particle != NULL)
7732 particle->annot = NULL;
7733 if (decl != NULL)
7734 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007735 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007736 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007737 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007738}
7739
7740/**
7741 * xmlSchemaParseUnion:
7742 * @ctxt: a schema validation context
7743 * @schema: the schema being built
7744 * @node: a subtree containing XML Schema informations
7745 *
7746 * parse a XML schema Union definition
7747 * *WARNING* this interface is highly subject to change
7748 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007749 * Returns -1 in case of internal error, 0 in case of success and a positive
7750 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007751 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007752static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007753xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007754 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007755{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007756 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007757 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007758 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007760
7761 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007762 return (-1);
7763 /* Not a component, don't create it. */
7764 type = ctxt->ctxtType;
7765 /*
7766 * Mark the simple type as being of variety "union".
7767 */
7768 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007769 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007770 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7771 * then the ·simple ur-type definition·."
7772 */
7773 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007774 /*
7775 * Check for illegal attributes.
7776 */
7777 attr = node->properties;
7778 while (attr != NULL) {
7779 if (attr->ns == NULL) {
7780 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7781 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007782 xmlSchemaPIllegalAttrErr(ctxt,
7783 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7784 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007785 }
7786 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007787 xmlSchemaPIllegalAttrErr(ctxt,
7788 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7789 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007790 }
7791 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007792 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007793 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007794 /*
7795 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007796 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007797 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007798 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007799 if (attr != NULL) {
7800 const xmlChar *end;
7801 xmlChar *tmp;
7802 const xmlChar *localName, *nsName;
7803 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7804 xmlSchemaQNameRefPtr ref;
7805
7806 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007807 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007808 do {
7809 while (IS_BLANK_CH(*cur))
7810 cur++;
7811 end = cur;
7812 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7813 end++;
7814 if (end == cur)
7815 break;
7816 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007817 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7818 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007819 /*
7820 * Create the member type link.
7821 */
7822 link = (xmlSchemaTypeLinkPtr)
7823 xmlMalloc(sizeof(xmlSchemaTypeLink));
7824 if (link == NULL) {
7825 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7826 "allocating a type link", NULL);
7827 return (-1);
7828 }
7829 link->type = NULL;
7830 link->next = NULL;
7831 if (lastLink == NULL)
7832 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007833 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007834 lastLink->next = link;
7835 lastLink = link;
7836 /*
7837 * Create a reference item.
7838 */
7839 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7840 localName, nsName);
7841 if (ref == NULL) {
7842 FREE_AND_NULL(tmp)
7843 return (-1);
7844 }
7845 /*
7846 * Assign the reference to the link, it will be resolved
7847 * later during fixup of the union simple type.
7848 */
7849 link->type = (xmlSchemaTypePtr) ref;
7850 }
7851 FREE_AND_NULL(tmp)
7852 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007854
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007855 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007856 /*
7857 * And now for the children...
7858 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007859 child = node->children;
7860 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007861 /*
7862 * Add the annotation to the simple type ancestor.
7863 */
7864 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7865 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007866 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007867 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007868 if (IS_SCHEMA(child, "simpleType")) {
7869 xmlSchemaTypePtr subtype, last = NULL;
7870
7871 /*
7872 * Anchor the member types in the "subtypes" field of the
7873 * simple type.
7874 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007875 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007876 subtype = (xmlSchemaTypePtr)
7877 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7878 if (subtype != NULL) {
7879 if (last == NULL) {
7880 type->subtypes = subtype;
7881 last = subtype;
7882 } else {
7883 last->next = subtype;
7884 last = subtype;
7885 }
7886 last->next = NULL;
7887 }
7888 child = child->next;
7889 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007890 }
7891 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007892 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007893 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007894 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007895 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007896 if ((attr == NULL) && (type->subtypes == NULL)) {
7897 /*
7898 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007899 * Either the memberTypes [attribute] of the <union> element must
7900 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007901 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007902 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007903 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7904 NULL, NULL, node,
7905 "Either the attribute 'memberTypes' or "
7906 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007907 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007908 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007909}
7910
7911/**
7912 * xmlSchemaParseList:
7913 * @ctxt: a schema validation context
7914 * @schema: the schema being built
7915 * @node: a subtree containing XML Schema informations
7916 *
7917 * parse a XML schema List definition
7918 * *WARNING* this interface is highly subject to change
7919 *
William M. Bracke7091952004-05-11 15:09:58 +00007920 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007921 * 1 in case of success.
7922 */
7923static xmlSchemaTypePtr
7924xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007925 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007926{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007927 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007928 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007929 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007930
7931 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7932 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007933 /* Not a component, don't create it. */
7934 type = ctxt->ctxtType;
7935 /*
7936 * Mark the type as being of variety "list".
7937 */
7938 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007939 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007940 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7941 * then the ·simple ur-type definition·."
7942 */
7943 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007944 /*
7945 * Check for illegal attributes.
7946 */
7947 attr = node->properties;
7948 while (attr != NULL) {
7949 if (attr->ns == NULL) {
7950 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7951 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007952 xmlSchemaPIllegalAttrErr(ctxt,
7953 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7954 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007955 }
7956 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007957 xmlSchemaPIllegalAttrErr(ctxt,
7958 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7959 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007960 }
7961 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007963
7964 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7965
William M. Brack2f2a6632004-08-20 23:09:47 +00007966 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007967 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7968 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007969 */
7970 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007971 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007972 /*
7973 * And now for the children...
7974 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007975 child = node->children;
7976 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007977 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7978 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007979 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007980 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007981 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007982 /*
7983 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007984 * Either the itemType [attribute] or the <simpleType> [child] of
7985 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007986 */
7987 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007988 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007989 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007992 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007993 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007994 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007995 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007996 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007997 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007998 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008001 "Either the attribute 'itemType' or the <simpleType> child "
8002 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008003 }
8004 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008007 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008008 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 if ((type->ref == NULL) &&
8010 (type->subtypes == NULL) &&
8011 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008012 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008013 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008014 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008015 "Either the attribute 'itemType' or the <simpleType> child "
8016 "must be present", NULL);
8017 }
8018 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008019}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008020
Daniel Veillard4255d502002-04-16 15:50:10 +00008021/**
8022 * xmlSchemaParseSimpleType:
8023 * @ctxt: a schema validation context
8024 * @schema: the schema being built
8025 * @node: a subtree containing XML Schema informations
8026 *
8027 * parse a XML schema Simple Type definition
8028 * *WARNING* this interface is highly subject to change
8029 *
William M. Bracke7091952004-05-11 15:09:58 +00008030 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008031 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008032 */
8033static xmlSchemaTypePtr
8034xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008035 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008036{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008037 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008038 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008039 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008040 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008041
8042 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8043 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008044
Daniel Veillardc0826a72004-08-10 14:17:33 +00008045 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008046 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008047 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008048 xmlSchemaPMissingAttrErr(ctxt,
8049 XML_SCHEMAP_S4S_ATTR_MISSING,
8050 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 "name", NULL);
8052 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008053 } else {
8054 if (xmlSchemaPValAttrNode(ctxt,
8055 NULL, NULL, attr,
8056 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8057 return (NULL);
8058 /*
8059 * Skip built-in types.
8060 */
8061 if (ctxt->isS4S) {
8062 xmlSchemaTypePtr biType;
8063
8064 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8065 if (biType != NULL)
8066 return (biType);
8067 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008068 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008069 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008070
Daniel Veillardc0826a72004-08-10 14:17:33 +00008071 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008072 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008073
Daniel Veillard01fa6152004-06-29 17:04:39 +00008074 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008075 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008076 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008077 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008078 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008079 if (type == NULL)
8080 return (NULL);
8081 type->node = node;
8082 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008083 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008084 /*
8085 * Check for illegal attributes.
8086 */
8087 attr = node->properties;
8088 while (attr != NULL) {
8089 if (attr->ns == NULL) {
8090 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008091 xmlSchemaPIllegalAttrErr(ctxt,
8092 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8093 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008094 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008095 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008096 xmlSchemaPIllegalAttrErr(ctxt,
8097 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8098 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008099 }
8100 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008101 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008102 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008103 /*
8104 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008105 *
8106 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008107 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008108 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008109 if (type == NULL)
8110 return (NULL);
8111 type->node = node;
8112 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008113 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008114 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8115 /*
8116 * Check for illegal attributes.
8117 */
8118 attr = node->properties;
8119 while (attr != NULL) {
8120 if (attr->ns == NULL) {
8121 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8122 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008123 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008124 xmlSchemaPIllegalAttrErr(ctxt,
8125 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8126 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008127 }
8128 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008129 xmlSchemaPIllegalAttrErr(ctxt,
8130 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8131 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008132 }
8133 attr = attr->next;
8134 }
8135 /*
8136 * Attribute "final".
8137 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008138 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008139 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008140 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8141 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8142 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8143 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8144 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8145 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008146 } else {
8147 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008148 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8149 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008150 XML_SCHEMAS_TYPE_FINAL_LIST,
8151 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8152
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008153 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008154 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008155 type, (xmlNodePtr) attr,
8156 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008157 attrValue, NULL, NULL, NULL);
8158 }
8159 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008160 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008161 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008162 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008163 /*
8164 * And now for the children...
8165 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008166 oldCtxtType = ctxt->ctxtType;
8167 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008168 ctxt->ctxtType = type;
8169 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008170 child = node->children;
8171 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008172 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8173 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008174 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008175 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008176 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8177 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008178 "(annotation?, (restriction | list | union))");
8179 } else if (IS_SCHEMA(child, "restriction")) {
8180 xmlSchemaParseRestriction(ctxt, schema, child,
8181 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008183 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008184 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008185 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008187 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008188 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008189 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008190 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008191 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8192 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008193 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008194 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008195 ctxt->parentItem = oldParentItem;
8196 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008197
Daniel Veillard4255d502002-04-16 15:50:10 +00008198 return (type);
8199}
8200
Daniel Veillard4255d502002-04-16 15:50:10 +00008201/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008202 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008203 * @ctxt: a schema validation context
8204 * @schema: the schema being built
8205 * @node: a subtree containing XML Schema informations
8206 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008207 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 * *WARNING* this interface is highly subject to change
8209 *
William M. Bracke7091952004-05-11 15:09:58 +00008210 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008211 * 1 in case of success.
8212 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008213static xmlSchemaTreeItemPtr
8214xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8215 xmlSchemaPtr schema,
8216 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008217{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008218 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008219 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008220 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008221 const xmlChar *ref = NULL, *refNs = NULL;
8222 int min, max;
8223
8224 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008225 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008226
8227 attr = xmlSchemaGetPropNode(node, "ref");
8228 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 xmlSchemaPMissingAttrErr(ctxt,
8230 XML_SCHEMAP_S4S_ATTR_MISSING,
8231 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008232 "ref", NULL);
8233 return (NULL);
8234 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008235 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008236 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 }
8238 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008239 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008240 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 /*
8242 * Check for illegal attributes.
8243 */
8244 attr = node->properties;
8245 while (attr != NULL) {
8246 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008248 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8249 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8250 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008251 xmlSchemaPIllegalAttrErr(ctxt,
8252 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8253 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008254 }
8255 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008256 xmlSchemaPIllegalAttrErr(ctxt,
8257 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8258 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008259 }
8260 attr = attr->next;
8261 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008262 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008263 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8264 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008265 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008266 /*
8267 * Create a reference item as the term; it will be substituted for
8268 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008269 */
8270 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008271 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8272 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8273 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8274 /*
8275 * And now for the children...
8276 */
8277 child = node->children;
8278 /* TODO: Is annotation even allowed for a model group reference? */
8279 if (IS_SCHEMA(child, "annotation")) {
8280 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008281 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008282 */
8283 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8284 child = child->next;
8285 }
8286 if (child != NULL) {
8287 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008288 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008289 NULL, NULL, node, child, NULL,
8290 "(annotation?)");
8291 }
8292 /*
8293 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8294 */
8295 if ((min == 0) && (max == 0))
8296 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008297 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008298 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8299 return ((xmlSchemaTreeItemPtr) item);
8300}
8301
8302/**
8303 * xmlSchemaParseModelGroupDefinition:
8304 * @ctxt: a schema validation context
8305 * @schema: the schema being built
8306 * @node: a subtree containing XML Schema informations
8307 *
8308 * Parses a XML schema model group definition.
8309 * *WARNING* this interface is highly subject to change
8310 *
8311 * Returns -1 in case of error, 0 if the declaration is improper and
8312 * 1 in case of success.
8313 */
8314static xmlSchemaModelGroupDefPtr
8315xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8316 xmlSchemaPtr schema,
8317 xmlNodePtr node)
8318{
8319 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008320 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008321 xmlAttrPtr attr;
8322 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008323
8324 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008325 return (NULL);
8326
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008327 attr = xmlSchemaGetPropNode(node, "name");
8328 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008329 xmlSchemaPMissingAttrErr(ctxt,
8330 XML_SCHEMAP_S4S_ATTR_MISSING,
8331 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008332 "name", NULL);
8333 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008334 } else if (xmlSchemaPValAttrNode(ctxt,
8335 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008336 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8337 return (NULL);
8338 }
8339 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8340 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008341 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008342 /*
8343 * Check for illegal attributes.
8344 */
8345 attr = node->properties;
8346 while (attr != NULL) {
8347 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008348 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008349 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008350 xmlSchemaPIllegalAttrErr(ctxt,
8351 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8352 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008353 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008354 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008355 xmlSchemaPIllegalAttrErr(ctxt,
8356 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8357 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008358 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008359 attr = attr->next;
8360 }
8361 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8362 /*
8363 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008364 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008365 child = node->children;
8366 if (IS_SCHEMA(child, "annotation")) {
8367 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8368 child = child->next;
8369 }
8370 if (IS_SCHEMA(child, "all")) {
8371 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8372 XML_SCHEMA_TYPE_ALL, 0);
8373 child = child->next;
8374 } else if (IS_SCHEMA(child, "choice")) {
8375 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8376 XML_SCHEMA_TYPE_CHOICE, 0);
8377 child = child->next;
8378 } else if (IS_SCHEMA(child, "sequence")) {
8379 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8380 XML_SCHEMA_TYPE_SEQUENCE, 0);
8381 child = child->next;
8382 }
8383 if (child != NULL) {
8384 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008385 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8386 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008387 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008388 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008389
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008390 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008391}
8392
8393/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008394 * xmlSchemaCleanupDoc:
8395 * @ctxt: a schema validation context
8396 * @node: the root of the document.
8397 *
8398 * removes unwanted nodes in a schemas document tree
8399 */
8400static void
8401xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8402{
8403 xmlNodePtr delete, cur;
8404
8405 if ((ctxt == NULL) || (root == NULL)) return;
8406
8407 /*
8408 * Remove all the blank text nodes
8409 */
8410 delete = NULL;
8411 cur = root;
8412 while (cur != NULL) {
8413 if (delete != NULL) {
8414 xmlUnlinkNode(delete);
8415 xmlFreeNode(delete);
8416 delete = NULL;
8417 }
8418 if (cur->type == XML_TEXT_NODE) {
8419 if (IS_BLANK_NODE(cur)) {
8420 if (xmlNodeGetSpacePreserve(cur) != 1) {
8421 delete = cur;
8422 }
8423 }
8424 } else if ((cur->type != XML_ELEMENT_NODE) &&
8425 (cur->type != XML_CDATA_SECTION_NODE)) {
8426 delete = cur;
8427 goto skip_children;
8428 }
8429
8430 /*
8431 * Skip to next node
8432 */
8433 if (cur->children != NULL) {
8434 if ((cur->children->type != XML_ENTITY_DECL) &&
8435 (cur->children->type != XML_ENTITY_REF_NODE) &&
8436 (cur->children->type != XML_ENTITY_NODE)) {
8437 cur = cur->children;
8438 continue;
8439 }
8440 }
8441 skip_children:
8442 if (cur->next != NULL) {
8443 cur = cur->next;
8444 continue;
8445 }
8446
8447 do {
8448 cur = cur->parent;
8449 if (cur == NULL)
8450 break;
8451 if (cur == root) {
8452 cur = NULL;
8453 break;
8454 }
8455 if (cur->next != NULL) {
8456 cur = cur->next;
8457 break;
8458 }
8459 } while (cur != NULL);
8460 }
8461 if (delete != NULL) {
8462 xmlUnlinkNode(delete);
8463 xmlFreeNode(delete);
8464 delete = NULL;
8465 }
8466}
8467
William M. Brack2f2a6632004-08-20 23:09:47 +00008468
8469/**
8470 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008471 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008472 * @ctxt: a schema validation context
8473 * @schemaLocation: an URI defining where to find the imported schema
8474 *
8475 * import a XML schema
8476 * *WARNING* this interface is highly subject to change
8477 *
8478 * Returns -1 in case of error and 1 in case of success.
8479 */
8480#if 0
8481static xmlSchemaImportPtr
8482xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8483 const xmlChar *schemaLocation)
8484{
8485 xmlSchemaImportPtr import;
8486 xmlSchemaParserCtxtPtr newctxt;
8487
8488 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8489 if (newctxt == NULL) {
8490 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8491 NULL);
8492 return (NULL);
8493 }
8494 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8495 /* Keep the same dictionnary for parsing, really */
8496 xmlDictReference(ctxt->dict);
8497 newctxt->dict = ctxt->dict;
8498 newctxt->includes = 0;
8499 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8500
8501 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8502 ctxt->userData);
8503
8504 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8505 if (import == NULL) {
8506 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8507 NULL);
8508 xmlSchemaFreeParserCtxt(newctxt);
8509 return (NULL);
8510 }
8511
8512 memset(import, 0, sizeof(xmlSchemaImport));
8513 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8514 import->schema = xmlSchemaParse(newctxt);
8515
8516 if (import->schema == NULL) {
8517 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008518 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008519 "Failed to import schema from location \"%s\".\n",
8520 schemaLocation, NULL);
8521
8522 xmlSchemaFreeParserCtxt(newctxt);
8523 /* The schemaLocation is held by the dictionary.
8524 if (import->schemaLocation != NULL)
8525 xmlFree((xmlChar *)import->schemaLocation);
8526 */
8527 xmlFree(import);
8528 return NULL;
8529 }
8530
8531 xmlSchemaFreeParserCtxt(newctxt);
8532 return import;
8533}
8534#endif
8535
8536static void
8537xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8538{
8539 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8540 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8541
8542 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8543 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8544
8545 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8546 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8547 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8548 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8549 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8550 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8551 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8552 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8553
8554 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8555 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8556 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8557 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8558 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8559 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8560}
8561
8562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008563xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008564 xmlSchemaPtr schema,
8565 xmlNodePtr node)
8566{
8567 xmlAttrPtr attr;
8568 const xmlChar *val;
8569
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008570 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8571 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008572 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008573 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8574 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008575 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008576 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8577
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008578 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008579 if (attr != NULL) {
8580 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008581 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008582 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008583 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008584 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008586 "(qualified | unqualified)", val, NULL, NULL, NULL);
8587 }
8588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008589
8590 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008591 if (attr != NULL) {
8592 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008594 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008598 "(qualified | unqualified)", val, NULL, NULL, NULL);
8599 }
8600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601
8602 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008603 if (attr != NULL) {
8604 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8605 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8606 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8607 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8608 -1,
8609 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8610 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8611 xmlSchemaPSimpleTypeErr(ctxt,
8612 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008613 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008614 "(#all | List of (extension | restriction | list | union))",
8615 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008616 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008617 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008618
8619 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008620 if (attr != NULL) {
8621 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8622 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8623 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8624 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8625 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8626 xmlSchemaPSimpleTypeErr(ctxt,
8627 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008629 "(#all | List of (extension | restriction | substitution))",
8630 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008631 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008632 }
8633}
8634
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008635/**
8636 * xmlSchemaParseSchemaTopLevel:
8637 * @ctxt: a schema validation context
8638 * @schema: the schemas
8639 * @nodes: the list of top level nodes
8640 *
8641 * Returns the internal XML Schema structure built from the resource or
8642 * NULL in case of error
8643 */
8644static void
8645xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8646 xmlSchemaPtr schema, xmlNodePtr nodes)
8647{
8648 xmlNodePtr child;
8649 xmlSchemaAnnotPtr annot;
8650
8651 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8652 return;
8653
8654 child = nodes;
8655 while ((IS_SCHEMA(child, "include")) ||
8656 (IS_SCHEMA(child, "import")) ||
8657 (IS_SCHEMA(child, "redefine")) ||
8658 (IS_SCHEMA(child, "annotation"))) {
8659 if (IS_SCHEMA(child, "annotation")) {
8660 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8661 if (schema->annot == NULL)
8662 schema->annot = annot;
8663 else
8664 xmlSchemaFreeAnnot(annot);
8665 } else if (IS_SCHEMA(child, "import")) {
8666 xmlSchemaParseImport(ctxt, schema, child);
8667 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008668 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008669 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008670 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008671 } else if (IS_SCHEMA(child, "redefine")) {
8672 TODO
8673 }
8674 child = child->next;
8675 }
8676 while (child != NULL) {
8677 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008678 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 child = child->next;
8680 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008681 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008682 child = child->next;
8683 } else if (IS_SCHEMA(child, "element")) {
8684 xmlSchemaParseElement(ctxt, schema, child, 1);
8685 child = child->next;
8686 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008687 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008688 child = child->next;
8689 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008690 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008691 child = child->next;
8692 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008693 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008694 child = child->next;
8695 } else if (IS_SCHEMA(child, "notation")) {
8696 xmlSchemaParseNotation(ctxt, schema, child);
8697 child = child->next;
8698 } else {
8699 xmlSchemaPErr2(ctxt, NULL, child,
8700 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008701 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008702 child->name, NULL);
8703 child = child->next;
8704 }
8705 while (IS_SCHEMA(child, "annotation")) {
8706 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8707 if (schema->annot == NULL)
8708 schema->annot = annot;
8709 else
8710 xmlSchemaFreeAnnot(annot);
8711 child = child->next;
8712 }
8713 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008714 ctxt->parentItem = NULL;
8715 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008716}
8717
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008718static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008719xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008720 xmlHashTablePtr *imports,
8721 const xmlChar *nsName)
8722{
8723 xmlSchemaImportPtr ret;
8724
8725 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008726 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008727 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008728 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008729 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8730 NULL, NULL, (xmlNodePtr) ctxt->doc,
8731 "Internal error: failed to build the import table",
8732 NULL);
8733 return (NULL);
8734 }
8735 }
8736 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8737 if (ret == NULL) {
8738 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8739 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008740 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008741 memset(ret, 0, sizeof(xmlSchemaImport));
8742 if (nsName == NULL)
8743 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008744 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008745
8746 return (ret);
8747}
8748
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008749/**
8750 * xmlSchemaNewParserCtxtUseDict:
8751 * @URL: the location of the schema
8752 * @dict: the dictionary to be used
8753 *
8754 * Create an XML Schemas parse context for that file/resource expected
8755 * to contain an XML Schemas file.
8756 *
8757 * Returns the parser context or NULL in case of error
8758 */
8759static xmlSchemaParserCtxtPtr
8760xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8761{
8762 xmlSchemaParserCtxtPtr ret;
8763 /*
8764 if (URL == NULL)
8765 return (NULL);
8766 */
8767
8768 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8769 if (ret == NULL) {
8770 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8771 NULL);
8772 return (NULL);
8773 }
8774 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8775 ret->dict = dict;
8776 xmlDictReference(dict);
8777 if (URL != NULL)
8778 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8779 ret->includes = 0;
8780 return (ret);
8781}
8782
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008783static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008784xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8785{
8786 if (vctxt->pctxt == NULL) {
8787 if (vctxt->schema != NULL)
8788 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8789 else
8790 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8791 if (vctxt->pctxt == NULL) {
8792 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8793 "failed to create a temp. parser context");
8794 return (-1);
8795 }
8796 /* TODO: Pass user data. */
8797 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8798 }
8799 return (0);
8800}
8801
8802static int
8803xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008804 xmlSchemaPtr schema,
8805 xmlNodePtr node,
8806 const xmlChar *nsName,
8807 const xmlChar *location,
8808 xmlDocPtr *doc,
8809 const xmlChar **targetNamespace,
8810 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008811{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008812 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008813 xmlParserCtxtPtr parserCtxt;
8814 xmlSchemaImportPtr import;
8815 const xmlChar *ns;
8816 xmlNodePtr root;
8817
8818 /*
8819 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8820 * <xsi:noNamespaceSchemaLocation>.
8821 */
8822 *doc = NULL;
8823 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008824 * Given that the schemaLocation [attribute] is only a hint, it is open
8825 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008826 * namespace, regardless of the ·actual value· of schemaLocation, but
8827 * such a strategy risks missing useful information when new
8828 * schemaLocations are offered.
8829 *
8830 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8831 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8832 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008833 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008834 */
8835 if (location == NULL) {
8836 /*
8837 * Schema Document Location Strategy:
8838 *
8839 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008840 * either as a resource which is an XML document or a <schema> element
8841 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008842 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008844 *
8845 * NOTE: Those stategies are not supported, so we will skip.
8846 */
8847 return (0);
8848 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008849 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008850 ns = XML_SCHEMAS_NO_NAMESPACE;
8851 else
8852 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008855 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008856 /*
8857 * There was a valid resource for the specified namespace already
8858 * defined, so skip.
8859 * TODO: This might be changed someday to allow import of
8860 * components from multiple documents for a single target namespace.
8861 */
8862 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863 }
8864 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8865 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8866 else {
8867 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8868 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8869 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008870 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008871 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008872 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 * 2 Based on the location URI, identify an existing schema document,
8874 * either as a resource which is an XML document or a <schema> element
8875 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008876 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008877 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008878 * web which is or contains or references a <schema> element;
8879 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8880 *
8881 */
8882 if ((absolute == 0) && (node != NULL)) {
8883 xmlChar *base, *URI;
8884
8885 base = xmlNodeGetBase(node->doc, node);
8886 if (base == NULL) {
8887 URI = xmlBuildURI(location, node->doc->URL);
8888 } else {
8889 URI = xmlBuildURI(location, base);
8890 xmlFree(base);
8891 }
8892 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008893 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008894 xmlFree(URI);
8895 }
8896 }
8897 parserCtxt = xmlNewParserCtxt();
8898 if (parserCtxt == NULL) {
8899 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8900 "allocating a parser context", NULL);
8901 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008902 }
8903 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008904 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008905 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008906 xmlDictReference(parserCtxt->dict);
8907 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008908 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008909 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008910 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008911 * 2.1 The referent is (a fragment of) a resource which is an
8912 * XML document (see clause 1.1), which in turn corresponds to
8913 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008914 * set, which in turn corresponds to a valid schema.
8915 * TODO: What to do with the "fragment" stuff?
8916 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008917 * 2.2 The referent is a <schema> element information item in
8918 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008919 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008920 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008921 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008922 */
8923 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008924 xmlErrorPtr lerr;
8925 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008926 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008927 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008928 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * If the doc is NULL and the parser error is an IO error we
8930 * will assume that the resource could not be located or accessed.
8931 *
8932 * TODO: Try to find specific error codes to react only on
8933 * localisation failures.
8934 *
8935 * TODO, FIXME: Check the spec: is a namespace added to the imported
8936 * namespaces, even if the schemaLocation did not provide
8937 * a resource? I guess so, since omitting the "schemaLocation"
8938 * attribute, imports a namespace as well.
8939 */
8940 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008941 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008942 xmlFreeParserCtxt(parserCtxt);
8943 return(0);
8944 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008945 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008946 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008947 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008948 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008949 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008950 xmlFreeParserCtxt(parserCtxt);
8951 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8952 }
8953 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008954
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008955 root = xmlDocGetRootElement(*doc);
8956 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008961 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008962 xmlFreeDoc(*doc);
8963 *doc = NULL;
8964 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008965 }
8966
8967 xmlSchemaCleanupDoc(pctxt, root);
8968
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008969 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008970 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008971 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008972 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008973 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008975 xmlFreeDoc(*doc);
8976 *doc = NULL;
8977 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008978 }
8979 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 /*
8981 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 if (nsName == NULL) {
8984 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008985 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008986 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008987 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008988 "The XML schema to be imported is not expected "
8989 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008990 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008991 xmlFreeDoc(*doc);
8992 *doc = NULL;
8993 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8994 }
8995 } else {
8996 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008997 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008999 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009000 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009001 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009002 xmlFreeDoc(*doc);
9003 *doc = NULL;
9004 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9005 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009006 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009007 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009008 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009009 "The XML schema to be imported is expected to have a "
9010 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 "its target namespace of '%s'",
9012 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009013 xmlFreeDoc(*doc);
9014 *doc = NULL;
9015 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9016 }
9017 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9021 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009022 xmlFreeDoc(*doc);
9023 *doc = NULL;
9024 return (-1);
9025 }
9026 import->schemaLocation = location;
9027 import->doc = *doc;
9028 return (0);
9029}
William M. Brack2f2a6632004-08-20 23:09:47 +00009030
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009031static void
9032xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9033 xmlSchemaPtr schema,
9034 const xmlChar *targetNamespace,
9035 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009037 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009038 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009039
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009040 /*
9041 * Save and reset the context & schema.
9042 */
9043 oldURL = pctxt->URL;
9044 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009045 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009046 oldLocImps = pctxt->localImports;
9047 pctxt->localImports = NULL;
9048 oldNumLocImps = pctxt->nbLocalImports;
9049 pctxt->nbLocalImports = 0;
9050 oldSizeLocImps = pctxt->sizeLocalImports;
9051 pctxt->sizeLocalImports = 0;
9052 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009053 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009054 xmlSchemaClearSchemaDefaults(schema);
9055 oldTNS = schema->targetNamespace;
9056 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009057 if ((targetNamespace != NULL) &&
9058 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9059 /*
9060 * We are parsing the schema for schema!
9061 */
9062 pctxt->isS4S = 1;
9063 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 /*
9065 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009066 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009067 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9068 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9069 /*
9070 * Restore the context & schema.
9071 */
9072 schema->flags = oldFlags;
9073 schema->targetNamespace = oldTNS;
9074 if (pctxt->localImports != NULL)
9075 xmlFree((xmlChar *) pctxt->localImports);
9076 pctxt->localImports = oldLocImps;
9077 pctxt->nbLocalImports = oldNumLocImps;
9078 pctxt->sizeLocalImports = oldSizeLocImps;
9079 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009080 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009081}
9082
William M. Brack2f2a6632004-08-20 23:09:47 +00009083/**
9084 * xmlSchemaParseImport:
9085 * @ctxt: a schema validation context
9086 * @schema: the schema being built
9087 * @node: a subtree containing XML Schema informations
9088 *
9089 * parse a XML schema Import definition
9090 * *WARNING* this interface is highly subject to change
9091 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009092 * Returns 0 in case of success, a positive error code if
9093 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009094 */
9095static int
9096xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9097 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009098{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009099 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009100 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009101 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009102 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009103 xmlAttrPtr attr;
9104 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009105 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009106
9107 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9108 return (-1);
9109
9110 /*
9111 * Check for illegal attributes.
9112 */
9113 attr = node->properties;
9114 while (attr != NULL) {
9115 if (attr->ns == NULL) {
9116 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9117 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9118 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009119 xmlSchemaPIllegalAttrErr(ctxt,
9120 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9121 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009122 }
9123 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009124 xmlSchemaPIllegalAttrErr(ctxt,
9125 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9126 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009127 }
9128 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009130 /*
9131 * Extract and validate attributes.
9132 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009133 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9134 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009135 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009136 xmlSchemaPSimpleTypeErr(ctxt,
9137 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9138 NULL, node,
9139 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009140 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009141 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9142 }
9143
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009144 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9145 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009146 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009147 xmlSchemaPSimpleTypeErr(ctxt,
9148 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9149 NULL, node,
9150 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009151 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009152 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009153 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009154 /*
9155 * And now for the children...
9156 */
9157 child = node->children;
9158 if (IS_SCHEMA(child, "annotation")) {
9159 /*
9160 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009161 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009162 */
9163 child = child->next;
9164 }
9165 if (child != NULL) {
9166 xmlSchemaPContentErr(ctxt,
9167 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9168 NULL, NULL, node, child, NULL,
9169 "(annotation?)");
9170 }
9171 /*
9172 * Apply additional constraints.
9173 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009174 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009175 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009176 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9177 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009178 * targetNamespace [attribute].
9179 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009180 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009181 xmlSchemaPCustomErr(ctxt,
9182 XML_SCHEMAP_SRC_IMPORT_1_1,
9183 NULL, NULL, node,
9184 "The value of the attribute 'namespace' must not match "
9185 "the target namespace '%s' of the importing schema",
9186 schema->targetNamespace);
9187 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9188 }
9189 } else {
9190 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009191 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009192 * <schema> must have a targetNamespace [attribute].
9193 */
9194 if (schema->targetNamespace == NULL) {
9195 xmlSchemaPCustomErr(ctxt,
9196 XML_SCHEMAP_SRC_IMPORT_1_2,
9197 NULL, NULL, node,
9198 "The attribute 'namespace' must be existent if "
9199 "the importing schema has no target namespace",
9200 NULL);
9201 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9202 }
9203 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009204 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009205 * Add the namespace to the list of locally imported namespace.
9206 */
9207 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009208 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009209 sizeof(const xmlChar*));
9210 ctxt->sizeLocalImports = 10;
9211 ctxt->nbLocalImports = 0;
9212 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9213 ctxt->sizeLocalImports *= 2;
9214 ctxt->localImports = (const xmlChar **) xmlRealloc(
9215 (xmlChar **) ctxt->localImports,
9216 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9217 }
9218 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9219 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009220 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009221 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009222 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9223 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009224 schemaLocation, &doc, &targetNamespace, 0);
9225 if (ret != 0) {
9226 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009227 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009228 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009229 } else if (doc != NULL) {
9230 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9231 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009232 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009233
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009234 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009235}
9236
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009237/**
9238 * xmlSchemaParseInclude:
9239 * @ctxt: a schema validation context
9240 * @schema: the schema being built
9241 * @node: a subtree containing XML Schema informations
9242 *
9243 * parse a XML schema Include definition
9244 *
William M. Bracke7091952004-05-11 15:09:58 +00009245 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009246 * 1 in case of success.
9247 */
9248static int
9249xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9250 xmlNodePtr node)
9251{
9252 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009253 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009254 xmlDocPtr doc = NULL;
9255 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009256 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009257 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009258 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009259 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009260
9261
9262 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9263 return (-1);
9264
9265 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009266 * Check for illegal attributes.
9267 */
9268 attr = node->properties;
9269 while (attr != NULL) {
9270 if (attr->ns == NULL) {
9271 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9272 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009273 xmlSchemaPIllegalAttrErr(ctxt,
9274 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9275 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009276 }
9277 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009278 xmlSchemaPIllegalAttrErr(ctxt,
9279 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9280 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009281 }
9282 attr = attr->next;
9283 }
9284 /*
9285 * Extract and validate attributes.
9286 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009287 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009288 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009289 * Preliminary step, extract the URI-Reference for the include and
9290 * make an URI from the base.
9291 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009292 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9293 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009294 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009295 xmlChar *uri = NULL;
9296
9297 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9298 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009300 base = xmlNodeGetBase(node->doc, node);
9301 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009302 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009303 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009304 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009305 xmlFree(base);
9306 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009307 if (uri == NULL) {
9308 xmlSchemaPErr(ctxt,
9309 node,
9310 XML_SCHEMAP_INTERNAL,
9311 "Internal error: xmlSchemaParseInclude, "
9312 "could not build an URI from the schemaLocation.\n",
9313 NULL, NULL);
9314 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009316 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9317 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009318 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009319 xmlSchemaPMissingAttrErr(ctxt,
9320 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9321 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009322 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009323 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009324 /*
9325 * And now for the children...
9326 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009327 child = node->children;
9328 while (IS_SCHEMA(child, "annotation")) {
9329 /*
9330 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009331 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009332 */
9333 child = child->next;
9334 }
9335 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009336 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009337 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9338 NULL, NULL, node, child, NULL,
9339 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009340 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009341 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009342 * Report self-inclusion.
9343 */
9344 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9345 xmlSchemaPCustomErr(ctxt,
9346 XML_SCHEMAP_SRC_INCLUDE,
9347 NULL, NULL, node,
9348 "The schema document '%s' cannot include itself.",
9349 schemaLocation);
9350 return (XML_SCHEMAP_SRC_INCLUDE);
9351 }
9352 /*
9353 * Check if this one was already processed to avoid incorrect
9354 * duplicate component errors and infinite circular inclusion.
9355 */
9356 include = schema->includes;
9357 while (include != NULL) {
9358 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9359 targetNamespace = include->origTargetNamespace;
9360 if (targetNamespace == NULL) {
9361 /*
9362 * Chameleon include: skip only if it was build for
9363 * the targetNamespace of the including schema.
9364 */
9365 if (xmlStrEqual(schema->targetNamespace,
9366 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009367 goto check_targetNamespace;
9368 }
9369 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009370 goto check_targetNamespace;
9371 }
9372 }
9373 include = include->next;
9374 }
9375 /*
9376 * First step is to parse the input document into an DOM/Infoset
9377 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009378 */
9379 parserCtxt = xmlNewParserCtxt();
9380 if (parserCtxt == NULL) {
9381 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9382 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009383 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009384 }
9385
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009386 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9387 xmlDictFree(parserCtxt->dict);
9388 parserCtxt->dict = ctxt->dict;
9389 xmlDictReference(parserCtxt->dict);
9390 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009391
9392 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009393 NULL, SCHEMAS_PARSE_OPTIONS);
9394 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009395 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009396 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009397 * TODO: It is not an error for the ·actual value· of the
9398 * schemaLocation [attribute] to fail to resolve it all, in which
9399 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009400 * So do we need a warning report here?
9401 */
9402 xmlSchemaPCustomErr(ctxt,
9403 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009404 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009405 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009406 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009407 }
9408
9409 /*
9410 * Then extract the root of the schema
9411 */
9412 root = xmlDocGetRootElement(doc);
9413 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009414 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009415 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009416 NULL, NULL, node,
9417 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009418 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009419 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009420 }
9421
9422 /*
9423 * Remove all the blank text nodes
9424 */
9425 xmlSchemaCleanupDoc(ctxt, root);
9426
9427 /*
9428 * Check the schemas top level element
9429 */
9430 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009431 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009432 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009433 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009434 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009435 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009436 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009437 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009438
William M. Brack2f2a6632004-08-20 23:09:47 +00009439 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009440 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009441 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9442 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009443 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9444 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009445check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009446 if (targetNamespace != NULL) {
9447 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009448 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009449 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009450 NULL, NULL, node,
9451 "The target namespace of the included schema "
9452 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009453 "has no target namespace",
9454 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009455 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009456 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9457 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009458 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009459 NULL, NULL, node,
9460 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009461 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009462 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009463 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009464 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009465 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009466 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009467 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 } else
9469 wasConvertingNs = 1;
9470 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009471
9472 if (include != NULL)
9473 goto exit;
9474
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009475 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009476 * URGENT TODO: If the schema is a chameleon-include then copy the
9477 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009478 * of those components, do nothing otherwise.
9479 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009480 * for every destinct including targetNamespace; thus not performant at
9481 * the moment.
9482 * TODO: Check when the namespace in wildcards for chameleons needs
9483 * to be converted: before we built wildcard intersections or after.
9484 */
9485 /*
9486 * Register the include.
9487 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009488 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9489 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009490 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9491 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009492 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009493 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009494 include->next = schema->includes;
9495 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009496 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009497 * TODO: Use the resolved URI for the this location, since it might
9498 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009499 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 include->schemaLocation = schemaLocation;
9501 include->doc = doc;
9502 /*
9503 * In case of chameleons, the original target namespace will differ
9504 * from the resulting namespace.
9505 */
9506 include->origTargetNamespace = targetNamespace;
9507 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009508#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009509 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009510 xmlGenericError(xmlGenericErrorContext,
9511 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9512 " into TNS '%s'\n", schemaLocation,
9513 targetNamespace, schema->targetNamespace);
9514 else
9515 xmlGenericError(xmlGenericErrorContext,
9516 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9517 targetNamespace);
9518#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009519 /*
9520 * Compile the included schema.
9521 */
9522 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9523
9524exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009525 /*
9526 * Remove the converting flag.
9527 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009528 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009529 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009530 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009531 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009532
9533exit_invalid:
9534 if (doc != NULL) {
9535 if (include != NULL)
9536 include->doc = NULL;
9537 xmlFreeDoc(doc);
9538 }
9539 return (ctxt->err);
9540
9541exit_failure:
9542 if (doc != NULL) {
9543 if (include != NULL)
9544 include->doc = NULL;
9545 xmlFreeDoc(doc);
9546 }
9547 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009548}
9549
9550/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009551 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009552 * @ctxt: a schema validation context
9553 * @schema: the schema being built
9554 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009555 * @type: the "compositor" type
9556 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009557 *
9558 * parse a XML schema Sequence definition
9559 * *WARNING* this interface is highly subject to change
9560 *
William M. Bracke7091952004-05-11 15:09:58 +00009561 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009562 * 1 in case of success.
9563 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009564static xmlSchemaTreeItemPtr
9565xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9566 xmlNodePtr node, xmlSchemaTypeType type,
9567 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009568{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009569 xmlSchemaModelGroupPtr item;
9570 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009571 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009572 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009573 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009574 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009575
9576 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009577 return (NULL);
9578 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009579 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009581 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9582 if (item == NULL)
9583 return (NULL);
9584
9585 if (withParticle) {
9586 if (type == XML_SCHEMA_TYPE_ALL) {
9587 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009588 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 } else {
9590 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009591 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9592 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9593 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009594 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009595 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9596 /*
9597 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009598 */
9599 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9600 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009601 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009602 particle->children = (xmlSchemaTreeItemPtr) item;
9603 /*
9604 * Check for illegal attributes.
9605 */
9606 attr = node->properties;
9607 while (attr != NULL) {
9608 if (attr->ns == NULL) {
9609 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9610 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9611 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009612 xmlSchemaPIllegalAttrErr(ctxt,
9613 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9614 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009615 }
9616 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009617 xmlSchemaPIllegalAttrErr(ctxt,
9618 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9619 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009620 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009621 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009622 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009623 } else {
9624 /*
9625 * Check for illegal attributes.
9626 */
9627 attr = node->properties;
9628 while (attr != NULL) {
9629 if (attr->ns == NULL) {
9630 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009631 xmlSchemaPIllegalAttrErr(ctxt,
9632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9633 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009634 }
9635 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009636 xmlSchemaPIllegalAttrErr(ctxt,
9637 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9638 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009639 }
9640 attr = attr->next;
9641 }
9642
William M. Brack2f2a6632004-08-20 23:09:47 +00009643 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009644
William M. Brack2f2a6632004-08-20 23:09:47 +00009645 /*
9646 * Extract and validate attributes.
9647 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009648 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009649 /*
9650 * And now for the children...
9651 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009652 child = node->children;
9653 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009654 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009655 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009656 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009657 oldcontainer = ctxt->container;
9658 ctxt->container = container;
9659 if (type == XML_SCHEMA_TYPE_ALL) {
9660 xmlSchemaParticlePtr part, last = NULL;
9661
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009662 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009663 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9664 schema, child, 0);
9665 if (part != NULL) {
9666 if (part->minOccurs > 1)
9667 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009668 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009669 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9670 if (part->maxOccurs > 1)
9671 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009673 "Invalid value for maxOccurs (must be 0 or 1)",
9674 NULL);
9675 if (last == NULL)
9676 item->children = (xmlSchemaTreeItemPtr) part;
9677 else
9678 last->next = (xmlSchemaTreeItemPtr) part;
9679 last = part;
9680 }
9681 child = child->next;
9682 }
9683 if (child != NULL) {
9684 xmlSchemaPContentErr(ctxt,
9685 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9686 NULL, NULL, node, child, NULL,
9687 "(annotation?, (annotation?, element*)");
9688 }
9689 } else {
9690 /* choice + sequence */
9691 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9692
9693 while ((IS_SCHEMA(child, "element")) ||
9694 (IS_SCHEMA(child, "group")) ||
9695 (IS_SCHEMA(child, "any")) ||
9696 (IS_SCHEMA(child, "choice")) ||
9697 (IS_SCHEMA(child, "sequence"))) {
9698
9699 if (IS_SCHEMA(child, "element")) {
9700 part = (xmlSchemaTreeItemPtr)
9701 xmlSchemaParseElement(ctxt, schema, child, 0);
9702 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009703 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009704 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9705 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009706 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009707 xmlSchemaParseAny(ctxt, schema, child);
9708 } else if (IS_SCHEMA(child, "choice")) {
9709 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9710 XML_SCHEMA_TYPE_CHOICE, 1);
9711 } else if (IS_SCHEMA(child, "sequence")) {
9712 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9713 XML_SCHEMA_TYPE_SEQUENCE, 1);
9714 }
9715 if (part != NULL) {
9716 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009717 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009718 else
9719 last->next = part;
9720 last = part;
9721 }
9722 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009723 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009724 if (child != NULL) {
9725 xmlSchemaPContentErr(ctxt,
9726 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9727 NULL, NULL, node, child, NULL,
9728 "(annotation?, (element | group | choice | sequence | any)*)");
9729 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009730 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009731 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009732 if (withParticle) {
9733 if ((min == 0) && (max == 0))
9734 return (NULL);
9735 else
9736 return ((xmlSchemaTreeItemPtr) particle);
9737 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009738 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009739}
9740
9741/**
9742 * xmlSchemaParseRestriction:
9743 * @ctxt: a schema validation context
9744 * @schema: the schema being built
9745 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009746 *
9747 * parse a XML schema Restriction definition
9748 * *WARNING* this interface is highly subject to change
9749 *
9750 * Returns the type definition or NULL in case of error
9751 */
9752static xmlSchemaTypePtr
9753xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009754 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009755{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009756 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009757 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009758 char buf[30];
9759 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009760 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009761
9762 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9763 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009764 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009765 type = ctxt->ctxtType;
9766 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009767
9768 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009769 * TODO: Is the container needed at all? the anonymous
9770 * items inside should generate unique names already.
9771 */
9772 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009773 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009774 /*
9775 * Check for illegal attributes.
9776 */
9777 attr = node->properties;
9778 while (attr != NULL) {
9779 if (attr->ns == NULL) {
9780 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9781 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009782 xmlSchemaPIllegalAttrErr(ctxt,
9783 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9784 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009785 }
9786 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009787 xmlSchemaPIllegalAttrErr(ctxt,
9788 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9789 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009790 }
9791 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009792 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009793 /*
9794 * Extract and validate attributes.
9795 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009796 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009797 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009798 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009799 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009800 /*
9801 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9802 * among its [children]), the simple type definition which is
9803 * the {content type} of the type definition ·resolved· to by
9804 * the ·actual value· of the base [attribute]"
9805 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009806 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009807 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009808 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009809 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009810 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009811 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009812 XML_SCHEMAP_S4S_ATTR_MISSING,
9813 type, node, "base", NULL);
9814 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009815 /*
9816 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009817 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009818 child = node->children;
9819 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 /*
9821 * Add the annotation to the simple type ancestor.
9822 */
9823 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9824 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009825 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009826 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009827 oldcontainer = ctxt->container;
9828 ctxt->container = container;
9829 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9830 /*
9831 * Corresponds to <simpleType><restriction><simpleType>.
9832 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009833 if (IS_SCHEMA(child, "simpleType")) {
9834 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009835 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009836 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009837 * Either the base [attribute] or the simpleType [child] of the
9838 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009839 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009840 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009841 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009842 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009843 "The attribute 'base' and the <simpleType> child are "
9844 "mutually exclusive", NULL);
9845 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009846 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009847 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009848 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009849 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009850 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009851 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9853 NULL, NULL, node, child,
9854 "Either the attribute 'base' or a <simpleType> child "
9855 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009856 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009857 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9858 /*
9859 * Corresponds to <complexType><complexContent><restriction>...
9860 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009861 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009862 * Model groups <all>, <choice> and <sequence>.
9863 */
9864 if (IS_SCHEMA(child, "all")) {
9865 type->subtypes = (xmlSchemaTypePtr)
9866 xmlSchemaParseModelGroup(ctxt, schema, child,
9867 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009868 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009869 } else if (IS_SCHEMA(child, "choice")) {
9870 type->subtypes = (xmlSchemaTypePtr)
9871 xmlSchemaParseModelGroup(ctxt,
9872 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9873 child = child->next;
9874 } else if (IS_SCHEMA(child, "sequence")) {
9875 type->subtypes = (xmlSchemaTypePtr)
9876 xmlSchemaParseModelGroup(ctxt, schema, child,
9877 XML_SCHEMA_TYPE_SEQUENCE, 1);
9878 child = child->next;
9879 /*
9880 * Model group reference <group>.
9881 */
9882 } else if (IS_SCHEMA(child, "group")) {
9883 type->subtypes = (xmlSchemaTypePtr)
9884 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9885 child = child->next;
9886 }
9887 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009888 /*
9889 * Corresponds to <complexType><simpleContent><restriction>...
9890 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009891 * "1.1 the simple type definition corresponding to the <simpleType>
9892 * among the [children] of <restriction> if there is one;"
9893 */
9894 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009895 /*
9896 * We will store the to-be-restricted simple type in
9897 * type->contentTypeDef *temporarily*.
9898 */
9899 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009900 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009901 if ( type->contentTypeDef == NULL)
9902 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009903 child = child->next;
9904 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009906
9907 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009908 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009909 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 /*
9911 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009912 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009914
Daniel Veillard01fa6152004-06-29 17:04:39 +00009915 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009917 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009918 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009919 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9920 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009921 * *Single Facet Value*
9922 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009923 while ((IS_SCHEMA(child, "minInclusive")) ||
9924 (IS_SCHEMA(child, "minExclusive")) ||
9925 (IS_SCHEMA(child, "maxInclusive")) ||
9926 (IS_SCHEMA(child, "maxExclusive")) ||
9927 (IS_SCHEMA(child, "totalDigits")) ||
9928 (IS_SCHEMA(child, "fractionDigits")) ||
9929 (IS_SCHEMA(child, "pattern")) ||
9930 (IS_SCHEMA(child, "enumeration")) ||
9931 (IS_SCHEMA(child, "whiteSpace")) ||
9932 (IS_SCHEMA(child, "length")) ||
9933 (IS_SCHEMA(child, "maxLength")) ||
9934 (IS_SCHEMA(child, "minLength"))) {
9935 facet = xmlSchemaParseFacet(ctxt, schema, child);
9936 if (facet != NULL) {
9937 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009938 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009939 else
9940 lastfacet->next = facet;
9941 lastfacet = facet;
9942 lastfacet->next = NULL;
9943 }
9944 child = child->next;
9945 }
9946 /*
9947 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009948 */
9949 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009950 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9951
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009952 facet = type->facets;
9953 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009954 facetLink = (xmlSchemaFacetLinkPtr)
9955 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009956 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009957 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009958 xmlFree(facetLink);
9959 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009960 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009961 facetLink->facet = facet;
9962 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009963 if (lastFacetLink == NULL)
9964 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009965 else
9966 lastFacetLink->next = facetLink;
9967 lastFacetLink = facetLink;
9968 facet = facet->next;
9969 } while (facet != NULL);
9970 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009971 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009972 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9973 /*
9974 * Attribute uses/declarations.
9975 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009976 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009977 /*
9978 * Attribute wildcard.
9979 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009980 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009981 type->attributeWildcard =
9982 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009983 child = child->next;
9984 }
9985 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009986 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009987 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9988 xmlSchemaPContentErr(ctxt,
9989 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009990 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009991 "annotation?, (group | all | choice | sequence)?, "
9992 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009993 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009994 xmlSchemaPContentErr(ctxt,
9995 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009996 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009997 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9998 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9999 "length | minLength | maxLength | enumeration | whiteSpace | "
10000 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10001 } else {
10002 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010003 xmlSchemaPContentErr(ctxt,
10004 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010005 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010006 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10007 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10008 "length | minLength | maxLength | enumeration | whiteSpace | "
10009 "pattern)*))");
10010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010011 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010012 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010013 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010014}
10015
10016/**
10017 * xmlSchemaParseExtension:
10018 * @ctxt: a schema validation context
10019 * @schema: the schema being built
10020 * @node: a subtree containing XML Schema informations
10021 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010022 * Parses an <extension>, which is found inside a
10023 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010024 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010025 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010026 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010027 */
10028static xmlSchemaTypePtr
10029xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010030 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010031{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010033 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010034 char buf[30];
10035 const xmlChar *oldcontainer, *container;
10036 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010037
10038 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10039 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010040 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010041 type = ctxt->ctxtType;
10042 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010043
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10045 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10046 /*
10047 * Check for illegal attributes.
10048 */
10049 attr = node->properties;
10050 while (attr != NULL) {
10051 if (attr->ns == NULL) {
10052 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10053 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010054 xmlSchemaPIllegalAttrErr(ctxt,
10055 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10056 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010057 }
10058 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010059 xmlSchemaPIllegalAttrErr(ctxt,
10060 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10061 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010062 }
10063 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010065
10066 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010067
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010068 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010069 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010070 */
10071 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010072 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10073 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010074 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010075 XML_SCHEMAP_S4S_ATTR_MISSING,
10076 NULL, node, "base", NULL);
10077 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010078 /*
10079 * And now for the children...
10080 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010081 child = node->children;
10082 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010083 /*
10084 * Add the annotation to the type ancestor.
10085 */
10086 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10087 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010089 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010090 oldcontainer = ctxt->container;
10091 ctxt->container = container;
10092 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10093 /*
10094 * Corresponds to <complexType><complexContent><extension>... and:
10095 *
10096 * Model groups <all>, <choice>, <sequence> and <group>.
10097 */
10098 if (IS_SCHEMA(child, "all")) {
10099 type->subtypes = (xmlSchemaTypePtr)
10100 xmlSchemaParseModelGroup(ctxt, schema,
10101 child, XML_SCHEMA_TYPE_ALL, 1);
10102 child = child->next;
10103 } else if (IS_SCHEMA(child, "choice")) {
10104 type->subtypes = (xmlSchemaTypePtr)
10105 xmlSchemaParseModelGroup(ctxt, schema,
10106 child, XML_SCHEMA_TYPE_CHOICE, 1);
10107 child = child->next;
10108 } else if (IS_SCHEMA(child, "sequence")) {
10109 type->subtypes = (xmlSchemaTypePtr)
10110 xmlSchemaParseModelGroup(ctxt, schema,
10111 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10112 child = child->next;
10113 } else if (IS_SCHEMA(child, "group")) {
10114 type->subtypes = (xmlSchemaTypePtr)
10115 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10116 child = child->next;
10117 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010118 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010119 if (child != NULL) {
10120 /*
10121 * Attribute uses/declarations.
10122 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010123 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010124 /*
10125 * Attribute wildcard.
10126 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010127 if (IS_SCHEMA(child, "anyAttribute")) {
10128 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010129 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10130 child = child->next;
10131 }
10132 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010133 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10135 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010136 xmlSchemaPContentErr(ctxt,
10137 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010138 NULL, NULL, node, child, NULL,
10139 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010140 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010141 } else {
10142 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010143 xmlSchemaPContentErr(ctxt,
10144 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010145 NULL, NULL, node, child, NULL,
10146 "(annotation?, ((attribute | attributeGroup)*, "
10147 "anyAttribute?))");
10148 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010149 }
10150 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010151 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010152}
10153
10154/**
10155 * xmlSchemaParseSimpleContent:
10156 * @ctxt: a schema validation context
10157 * @schema: the schema being built
10158 * @node: a subtree containing XML Schema informations
10159 *
10160 * parse a XML schema SimpleContent definition
10161 * *WARNING* this interface is highly subject to change
10162 *
10163 * Returns the type definition or NULL in case of error
10164 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010165static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010166xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10167 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010168{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010169 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010170 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010171 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010172
10173 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010174 return (-1);
10175 /* Not a component, don't create it. */
10176 type = ctxt->ctxtType;
10177 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10178 /*
10179 * Check for illegal attributes.
10180 */
10181 attr = node->properties;
10182 while (attr != NULL) {
10183 if (attr->ns == NULL) {
10184 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010185 xmlSchemaPIllegalAttrErr(ctxt,
10186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10187 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010188 }
10189 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010190 xmlSchemaPIllegalAttrErr(ctxt,
10191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10192 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010193 }
10194 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010195 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010196
10197 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010198
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010199 /*
10200 * And now for the children...
10201 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010202 child = node->children;
10203 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010204 /*
10205 * Add the annotation to the complex type ancestor.
10206 */
10207 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10208 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010209 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010210 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010211 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010212 xmlSchemaParseRestriction(ctxt, schema, child,
10213 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010214 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010215 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010216 xmlSchemaParseExtension(ctxt, schema, child,
10217 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010218 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010219 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010220 if (child != NULL) {
10221 xmlSchemaPContentErr(ctxt,
10222 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010223 NULL, NULL, node, child, NULL,
10224 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010225 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010227}
10228
10229/**
10230 * xmlSchemaParseComplexContent:
10231 * @ctxt: a schema validation context
10232 * @schema: the schema being built
10233 * @node: a subtree containing XML Schema informations
10234 *
10235 * parse a XML schema ComplexContent definition
10236 * *WARNING* this interface is highly subject to change
10237 *
10238 * Returns the type definition or NULL in case of error
10239 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010240static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010241xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10242 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010243{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010245 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010246 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010247
10248 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010249 return (-1);
10250 /* Not a component, don't create it. */
10251 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010252 /*
10253 * Check for illegal attributes.
10254 */
10255 attr = node->properties;
10256 while (attr != NULL) {
10257 if (attr->ns == NULL) {
10258 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010259 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010260 {
10261 xmlSchemaPIllegalAttrErr(ctxt,
10262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10263 NULL, NULL, attr);
10264 }
10265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10266 xmlSchemaPIllegalAttrErr(ctxt,
10267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10268 NULL, NULL, attr);
10269 }
10270 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010271 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010272
10273 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10274
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010275 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010276 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010277 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010278 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10279 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10280 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010281 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010282 child = node->children;
10283 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010284 /*
10285 * Add the annotation to the complex type ancestor.
10286 */
10287 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10288 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010289 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010290 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010291 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010292 xmlSchemaParseRestriction(ctxt, schema, child,
10293 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010294 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010295 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010296 xmlSchemaParseExtension(ctxt, schema, child,
10297 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010298 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010299 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010300 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010301 xmlSchemaPContentErr(ctxt,
10302 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10303 NULL, NULL, node, child,
10304 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010305 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010307}
10308
10309/**
10310 * xmlSchemaParseComplexType:
10311 * @ctxt: a schema validation context
10312 * @schema: the schema being built
10313 * @node: a subtree containing XML Schema informations
10314 *
10315 * parse a XML schema Complex Type definition
10316 * *WARNING* this interface is highly subject to change
10317 *
10318 * Returns the type definition or NULL in case of error
10319 */
10320static xmlSchemaTypePtr
10321xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010322 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010323{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010324 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010325 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010326 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010327 xmlAttrPtr attr;
10328 const xmlChar *attrValue;
10329 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010330 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010331 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010332
Daniel Veillard4255d502002-04-16 15:50:10 +000010333
10334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10335 return (NULL);
10336
Daniel Veillard01fa6152004-06-29 17:04:39 +000010337 ctxtType = ctxt->ctxtType;
10338
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010339 if (topLevel) {
10340 attr = xmlSchemaGetPropNode(node, "name");
10341 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010342 xmlSchemaPMissingAttrErr(ctxt,
10343 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010344 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010345 } else if (xmlSchemaPValAttrNode(ctxt,
10346 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010347 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10348 return (NULL);
10349 }
10350 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010351
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010352 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010353 /*
10354 * Parse as local complex type definition.
10355 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010356 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010357 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10358 if (type == NULL)
10359 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010360 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010361 type->node = node;
10362 type->type = XML_SCHEMA_TYPE_COMPLEX;
10363 /*
10364 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010365 */
10366 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 /*
10368 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010369 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010370 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 if (type == NULL)
10372 return (NULL);
10373 type->node = node;
10374 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010375 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010376 }
10377 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010378 /*
10379 * Handle attributes.
10380 */
10381 attr = node->properties;
10382 while (attr != NULL) {
10383 if (attr->ns == NULL) {
10384 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10385 /*
10386 * Attribute "id".
10387 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010388 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10389 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010390 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10391 /*
10392 * Attribute "mixed".
10393 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010394 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010395 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010396 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10397 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010398 /*
10399 * Attributes of global complex type definitions.
10400 */
10401 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10402 /* Pass. */
10403 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10404 /*
10405 * Attribute "abstract".
10406 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010407 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10408 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010409 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10410 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10411 /*
10412 * Attribute "final".
10413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010414 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010415 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010416 if (xmlSchemaPValAttrBlockFinal(attrValue,
10417 &(type->flags),
10418 -1,
10419 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10420 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10421 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010422 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010423 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010424 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010425 type, (xmlNodePtr) attr, NULL,
10426 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010427 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010428 } else
10429 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010430 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10431 /*
10432 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010433 */
10434 attrValue = xmlSchemaGetNodeContent(ctxt,
10435 (xmlNodePtr) attr);
10436 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 -1,
10438 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010439 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010440 -1, -1, -1) != 0) {
10441 xmlSchemaPSimpleTypeErr(ctxt,
10442 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 type, (xmlNodePtr) attr, NULL,
10444 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010445 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010446 } else
10447 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010448 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 xmlSchemaPIllegalAttrErr(ctxt,
10450 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010451 &des, type, attr);
10452 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010453 } else {
10454 xmlSchemaPIllegalAttrErr(ctxt,
10455 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010456 &des, type, attr);
10457 }
10458 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 xmlSchemaPIllegalAttrErr(ctxt,
10460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10461 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010462 }
10463 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010464 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010465 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010466 /*
10467 * Apply default "block" values.
10468 */
10469 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10470 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10471 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10472 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10473 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010474 if (! final) {
10475 /*
10476 * Apply default "block" values.
10477 */
10478 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10479 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10480 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10481 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10482 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010483 /*
10484 * And now for the children...
10485 */
10486 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010487 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010488 child = node->children;
10489 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010490 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10491 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010492 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010493 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010494 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010495 /*
10496 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010497 * Specifying mixed='true' when the <simpleContent>
10498 * alternative is chosen has no effect
10499 */
William M. Bracke7091952004-05-11 15:09:58 +000010500 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10501 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010502 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010503 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010504 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010505 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10506 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010507 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010508 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010509 /*
10510 * SPEC
10511 * "...the third alternative (neither <simpleContent> nor
10512 * <complexContent>) is chosen. This case is understood as shorthand
10513 * for complex content restricting the ·ur-type definition·, and the
10514 * details of the mappings should be modified as necessary.
10515 */
10516 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10517 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010518 /*
10519 * Parse model groups.
10520 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010521 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010522 type->subtypes = (xmlSchemaTypePtr)
10523 xmlSchemaParseModelGroup(ctxt, schema, child,
10524 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010525 child = child->next;
10526 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010527 type->subtypes = (xmlSchemaTypePtr)
10528 xmlSchemaParseModelGroup(ctxt, schema, child,
10529 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010530 child = child->next;
10531 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010532 type->subtypes = (xmlSchemaTypePtr)
10533 xmlSchemaParseModelGroup(ctxt, schema, child,
10534 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010535 child = child->next;
10536 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010537 type->subtypes = (xmlSchemaTypePtr)
10538 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010539 child = child->next;
10540 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010541 /*
10542 * Parse attribute decls/refs.
10543 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010544 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010545 /*
10546 * Parse attribute wildcard.
10547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010548 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010549 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10550 child = child->next;
10551 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010552 }
10553 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010554 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010555 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010556 &des, type, node, child,
10557 NULL, "(annotation?, (simpleContent | complexContent | "
10558 "((group | all | choice | sequence)?, ((attribute | "
10559 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010560 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010561 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010562 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010563 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010564 return (type);
10565}
10566
Daniel Veillard4255d502002-04-16 15:50:10 +000010567/**
10568 * xmlSchemaParseSchema:
10569 * @ctxt: a schema validation context
10570 * @node: a subtree containing XML Schema informations
10571 *
10572 * parse a XML schema definition from a node set
10573 * *WARNING* this interface is highly subject to change
10574 *
10575 * Returns the internal XML Schema structure built from the resource or
10576 * NULL in case of error
10577 */
10578static xmlSchemaPtr
10579xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10580{
10581 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010582 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010583 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010584 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010585
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010586 /*
10587 * This one is called by xmlSchemaParse only and is used if
10588 * the schema to be parsed was specified via the API; i.e. not
10589 * automatically by the validated instance document.
10590 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010591 if ((ctxt == NULL) || (node == NULL))
10592 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010593 nberrors = ctxt->nberrors;
10594 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010595 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010596 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010597 xmlSchemaImportPtr import;
10598
Daniel Veillard4255d502002-04-16 15:50:10 +000010599 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010600 if (schema == NULL)
10601 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010602 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010603 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010604 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010605 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10606 /*
10607 * TODO: Should we proceed with an invalid target namespace?
10608 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010609 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010610 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10611 /*
10612 * We are parsing the schema for schema!
10613 */
10614 ctxt->isS4S = 1;
10615 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010616 } else {
10617 schema->targetNamespace = NULL;
10618 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010619 /*
10620 * Add the current ns name and location to the import table;
10621 * this is needed to have a consistent mechanism, regardless
10622 * if all schemata are constructed dynamically fired by the
10623 * instance or if the schema to be used was specified via
10624 * the API.
10625 */
10626 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10627 schema->targetNamespace);
10628 if (import == NULL) {
10629 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10630 NULL, NULL, (xmlNodePtr) ctxt->doc,
10631 "Internal error: xmlSchemaParseSchema, "
10632 "failed to add an import entry", NULL);
10633 xmlSchemaFree(schema);
10634 schema = NULL;
10635 return (NULL);
10636 }
10637 import->schemaLocation = ctxt->URL;
10638 /*
10639 * NOTE: We won't set the doc here, otherwise it will be freed
10640 * if the import struct is freed.
10641 * import->doc = ctxt->doc;
10642 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010643 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010644 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10645 } else {
10646 xmlDocPtr doc;
10647
10648 doc = node->doc;
10649
10650 if ((doc != NULL) && (doc->URL != NULL)) {
10651 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10652 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010653 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010654 } else {
10655 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10656 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010657 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010658 }
10659 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010660 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010661 if (ctxt->nberrors != 0) {
10662 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010663 xmlSchemaFree(schema);
10664 schema = NULL;
10665 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010666 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010667 if (schema != NULL)
10668 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010669 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010670#ifdef DEBUG
10671 if (schema == NULL)
10672 xmlGenericError(xmlGenericErrorContext,
10673 "xmlSchemaParse() failed\n");
10674#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010675 return (schema);
10676}
10677
10678/************************************************************************
10679 * *
10680 * Validating using Schemas *
10681 * *
10682 ************************************************************************/
10683
10684/************************************************************************
10685 * *
10686 * Reading/Writing Schemas *
10687 * *
10688 ************************************************************************/
10689
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010690#if 0 /* Will be enabled if it is clear what options are needed. */
10691/**
10692 * xmlSchemaParserCtxtSetOptions:
10693 * @ctxt: a schema parser context
10694 * @options: a combination of xmlSchemaParserOption
10695 *
10696 * Sets the options to be used during the parse.
10697 *
10698 * Returns 0 in case of success, -1 in case of an
10699 * API error.
10700 */
10701static int
10702xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10703 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010704
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010705{
10706 int i;
10707
10708 if (ctxt == NULL)
10709 return (-1);
10710 /*
10711 * WARNING: Change the start value if adding to the
10712 * xmlSchemaParseOption.
10713 */
10714 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10715 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010716 return (-1);
10717 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010718 }
10719 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010720 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010721}
10722
10723/**
10724 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010725 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010726 *
10727 * Returns the option combination of the parser context.
10728 */
10729static int
10730xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010731
10732{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010733 if (ctxt == NULL)
10734 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 else
10736 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010737}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010738#endif
10739
Daniel Veillard4255d502002-04-16 15:50:10 +000010740/**
10741 * xmlSchemaNewParserCtxt:
10742 * @URL: the location of the schema
10743 *
10744 * Create an XML Schemas parse context for that file/resource expected
10745 * to contain an XML Schemas file.
10746 *
10747 * Returns the parser context or NULL in case of error
10748 */
10749xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010750xmlSchemaNewParserCtxt(const char *URL)
10751{
Daniel Veillard4255d502002-04-16 15:50:10 +000010752 xmlSchemaParserCtxtPtr ret;
10753
10754 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010755 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010756
10757 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10758 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010759 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010760 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010761 return (NULL);
10762 }
10763 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010764 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010765 ret->dict = xmlDictCreate();
10766 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010767 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010768 return (ret);
10769}
10770
10771/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010772 * xmlSchemaNewMemParserCtxt:
10773 * @buffer: a pointer to a char array containing the schemas
10774 * @size: the size of the array
10775 *
10776 * Create an XML Schemas parse context for that memory buffer expected
10777 * to contain an XML Schemas file.
10778 *
10779 * Returns the parser context or NULL in case of error
10780 */
10781xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010782xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10783{
Daniel Veillard6045c902002-10-09 21:13:59 +000010784 xmlSchemaParserCtxtPtr ret;
10785
10786 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010787 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010788
10789 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10790 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010791 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010792 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010793 return (NULL);
10794 }
10795 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10796 ret->buffer = buffer;
10797 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010798 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010799 return (ret);
10800}
10801
10802/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010803 * xmlSchemaNewDocParserCtxt:
10804 * @doc: a preparsed document tree
10805 *
10806 * Create an XML Schemas parse context for that document.
10807 * NB. The document may be modified during the parsing process.
10808 *
10809 * Returns the parser context or NULL in case of error
10810 */
10811xmlSchemaParserCtxtPtr
10812xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10813{
10814 xmlSchemaParserCtxtPtr ret;
10815
10816 if (doc == NULL)
10817 return (NULL);
10818
10819 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10820 if (ret == NULL) {
10821 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10822 NULL);
10823 return (NULL);
10824 }
10825 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10826 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010827 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010828 /* The application has responsibility for the document */
10829 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010830
10831 return (ret);
10832}
10833
10834/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010835 * xmlSchemaFreeParserCtxt:
10836 * @ctxt: the schema parser context
10837 *
10838 * Free the resources associated to the schema parser context
10839 */
10840void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010841xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10842{
Daniel Veillard4255d502002-04-16 15:50:10 +000010843 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010844 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010845 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010846 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010847 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010848 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010849 xmlFree(ctxt->assemble);
10850 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010851 if (ctxt->vctxt != NULL) {
10852 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10853 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010854 if (ctxt->localImports != NULL)
10855 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010856 if (ctxt->substGroups != NULL)
10857 xmlHashFree(ctxt->substGroups,
10858 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010859 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010860 xmlFree(ctxt);
10861}
10862
10863/************************************************************************
10864 * *
10865 * Building the content models *
10866 * *
10867 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010868
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010869static void
10870xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010871 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010872{
10873 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010874 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010875 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010876 xmlSchemaSubstGroupPtr substGroup;
10877 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010878
10879 elemDecl = (xmlSchemaElementPtr) particle->children;
10880 /*
10881 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010882 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010883 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010884 end = xmlAutomataNewState(pctxt->am);
10885 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10886 if (substGroup == NULL) {
10887 xmlSchemaPErr(pctxt, GET_NODE(particle),
10888 XML_SCHEMAP_INTERNAL,
10889 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10890 "declaration is marked having a subst. group but none "
10891 "available.\n", elemDecl->name, NULL);
10892 return;
10893 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010894 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010895 /*
10896 * NOTE that we put the declaration in, even if it's abstract,
10897 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010898 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010899 xmlAutomataNewTransition2(pctxt->am,
10900 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010901 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10902 /*
10903 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010904 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010905 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010906 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10907 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010908 xmlAutomataNewTransition2(pctxt->am,
10909 start, NULL,
10910 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010911 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010912 }
10913 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010914 int counter;
10915 xmlAutomataStatePtr hop;
10916 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10917 UNBOUNDED : particle->maxOccurs - 1;
10918 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10919
10920 counter =
10921 xmlAutomataNewCounter(pctxt->am, minOccurs,
10922 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010923 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010924
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010925 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010926 xmlAutomataNewTransition2(pctxt->am,
10927 start, NULL,
10928 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010929 hop);
10930 /*
10931 * Add subst. group members.
10932 */
10933 for (i = 0; i < substGroup->members->nbItems; i++) {
10934 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10935 xmlAutomataNewEpsilon(pctxt->am,
10936 xmlAutomataNewTransition2(pctxt->am,
10937 start, NULL,
10938 member->name, member->targetNamespace, member),
10939 hop);
10940 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010941 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10942 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10943 }
10944 if (particle->minOccurs == 0)
10945 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010946 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010947}
10948
10949static void
10950xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10951 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010952{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010953 if (((xmlSchemaElementPtr) particle->children)->flags &
10954 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010955 /*
10956 * Substitution groups.
10957 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010958 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010959 } else {
10960 xmlSchemaElementPtr elemDecl;
10961 xmlAutomataStatePtr start;
10962
10963 elemDecl = (xmlSchemaElementPtr) particle->children;
10964
10965 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010966 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010967 if (particle->maxOccurs == 1) {
10968 start = ctxt->state;
10969 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10970 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10971 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10972 /* Special case. */
10973 start = ctxt->state;
10974 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10975 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010976 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010977 } else {
10978 int counter;
10979 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10980 UNBOUNDED : particle->maxOccurs - 1;
10981 int minOccurs = particle->minOccurs < 1 ?
10982 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010983
10984 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010985 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10986 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10987 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10988 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10989 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
10990 NULL, counter);
10991 }
10992 if (particle->minOccurs == 0)
10993 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
10994 }
10995}
10996
Daniel Veillard4255d502002-04-16 15:50:10 +000010997/**
10998 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000010999 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011000 * @particle: the particle component
11001 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011002 *
11003 * Generate the automata sequence needed for that type
11004 */
11005static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011006xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011007 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011008 const xmlChar * name)
11009{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011010 if (particle == NULL) {
11011 xmlSchemaPErr(ctxt, NULL,
11012 XML_SCHEMAP_INTERNAL,
11013 "Internal error: xmlSchemaBuildAContentModel, "
11014 "particle is NULL.\n", NULL, NULL);
11015 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011016 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011017 if (particle->children == NULL) {
11018 xmlSchemaPErr(ctxt, GET_NODE(particle),
11019 XML_SCHEMAP_INTERNAL,
11020 "Internal error: xmlSchemaBuildAContentModel, "
11021 "no term on particle.\n", NULL, NULL);
11022 return;
11023 }
11024
11025 switch (particle->children->type) {
11026 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011027 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011028 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011029 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011030
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011031 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011032
Daniel Veillardc0826a72004-08-10 14:17:33 +000011033 start = ctxt->state;
11034 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011035
11036 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011037 if (wild->any == 1) {
11038 /*
11039 * We need to add both transitions:
11040 *
11041 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011042 */
11043 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011044 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011045 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011046 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11047 /*
11048 * 2. the {"*"} for elements in no namespace.
11049 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011050 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011051 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011052 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011053 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11054
11055 } else if (wild->nsSet != NULL) {
11056 ns = wild->nsSet;
11057 do {
11058 ctxt->state = start;
11059 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011060 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11062 ns = ns->next;
11063 } while (ns != NULL);
11064
11065 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011066
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011067 /*
11068 * Lead nodes with the negated namespace to the sink-state
11069 * {"*", "##other"}.
11070 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011071 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011072 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011073 /*
11074 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011075 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011076 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011077 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011078 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011079 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011080 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011081 } else {
11082 int counter;
11083 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011084 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011085 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011086 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011087 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011088
Daniel Veillardc0826a72004-08-10 14:17:33 +000011089 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090 hop = xmlAutomataNewState(ctxt->am);
11091 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011092 ctxt->state =
11093 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011094 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011095 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011096 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011097 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011098 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011099 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011100 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 ns = wild->nsSet;
11102 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011103 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011104 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011105 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011106 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11107 ns = ns->next;
11108 } while (ns != NULL);
11109
11110 } else if (wild->negNsSet != NULL) {
11111 xmlAutomataStatePtr deadEnd;
11112
11113 deadEnd = xmlAutomataNewState(ctxt->am);
11114 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011115 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011117 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011118 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011119 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011120 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11121 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11122 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011123 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011124 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011125 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011126 ctxt->state = end;
11127 break;
11128 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011129 case XML_SCHEMA_TYPE_ELEMENT:
11130 xmlSchemaBuildContentModelForElement(ctxt, particle);
11131 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011132 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011133 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011134
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011135 /*
11136 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011137 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011138 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011139 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11140 sub = particle->children->children;
11141 while (sub != NULL) {
11142 xmlSchemaBuildAContentModel(ctxt,
11143 (xmlSchemaParticlePtr) sub, name);
11144 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011145 }
11146 } else {
11147 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011148
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011149 if (particle->maxOccurs >= UNBOUNDED) {
11150 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011151 xmlAutomataStatePtr tmp;
11152 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011153
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011154 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011155 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011156 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011157
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011158 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011159 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011160
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 sub = particle->children->children;
11162 while (sub != NULL) {
11163 xmlSchemaBuildAContentModel(ctxt,
11164 (xmlSchemaParticlePtr) sub, name);
11165 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011166 }
11167 tmp = ctxt->state;
11168 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11169 oldstate, counter);
11170 ctxt->state =
11171 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11172 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011173
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011174 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011175 sub = particle->children->children;
11176 while (sub != NULL) {
11177 xmlSchemaBuildAContentModel(ctxt,
11178 (xmlSchemaParticlePtr) sub, name);
11179 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011180 }
11181 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11182 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011183 if (particle->minOccurs == 0) {
11184 xmlAutomataNewEpsilon(ctxt->am,
11185 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011186 }
11187 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011188 } else if ((particle->maxOccurs > 1)
11189 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 xmlAutomataStatePtr tmp;
11191 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011192
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011193 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011194 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011195 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011196
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011197 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011198 particle->minOccurs - 1,
11199 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011200
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011201 sub = particle->children->children;
11202 while (sub != NULL) {
11203 xmlSchemaBuildAContentModel(ctxt,
11204 (xmlSchemaParticlePtr) sub, name);
11205 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011206 }
11207 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011208 xmlAutomataNewCountedTrans(ctxt->am,
11209 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011210 ctxt->state =
11211 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11212 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213 if (particle->minOccurs == 0) {
11214 xmlAutomataNewEpsilon(ctxt->am,
11215 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011216 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011217 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 sub = particle->children->children;
11219 while (sub != NULL) {
11220 xmlSchemaBuildAContentModel(ctxt,
11221 (xmlSchemaParticlePtr) sub, name);
11222 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011223 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011224 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011225 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11226 ctxt->state);
11227 }
11228 }
11229 }
11230 break;
11231 }
11232 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011234 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011235
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011236 start = ctxt->state;
11237 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011238
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011239 /*
11240 * iterate over the subtypes and remerge the end with an
11241 * epsilon transition
11242 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 if (particle->maxOccurs == 1) {
11244 sub = particle->children->children;
11245 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011247 xmlSchemaBuildAContentModel(ctxt,
11248 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011249 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011250 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011251 }
11252 } else {
11253 int counter;
11254 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011255 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11256 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011258 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011259
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011260 /*
11261 * use a counter to keep track of the number of transtions
11262 * which went through the choice.
11263 */
11264 counter =
11265 xmlAutomataNewCounter(ctxt->am, minOccurs,
11266 maxOccurs);
11267 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011268
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011269 sub = particle->children->children;
11270 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011272 xmlSchemaBuildAContentModel(ctxt,
11273 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011274 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011275 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 }
11277 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11278 counter);
11279 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11280 counter);
11281 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011283 xmlAutomataNewEpsilon(ctxt->am, start, end);
11284 }
11285 ctxt->state = end;
11286 break;
11287 }
11288 case XML_SCHEMA_TYPE_ALL:{
11289 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 xmlSchemaParticlePtr sub;
11291 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011293
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011294 sub = (xmlSchemaParticlePtr) particle->children->children;
11295 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 break;
11297 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011298 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011299 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011300
11301 elemDecl = (xmlSchemaElementPtr) sub->children;
11302 if (elemDecl == NULL) {
11303 xmlSchemaPErr(ctxt, NULL,
11304 XML_SCHEMAP_INTERNAL,
11305 "Internal error: xmlSchemaBuildAContentModel, "
11306 "<element> particle a NULL term.\n", NULL, NULL);
11307 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011308 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011309 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011310 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011311 * {particles} of the group must be 0 or 1; this is
11312 * already ensured during the parse of the content of
11313 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011314 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011315 if ((sub->minOccurs == 1) &&
11316 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011317 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011318 ctxt->state,
11319 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011320 elemDecl->targetNamespace,
11321 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011322 } else if ((sub->minOccurs == 0) &&
11323 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011324
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011325 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011326 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011327 elemDecl->name,
11328 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011329 0,
11330 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011331 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011332 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011333 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011334 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011336 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011337 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011338 break;
11339 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 default:
11341 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 "Internal error: xmlSchemaBuildAContentModel, found "
11343 "unexpected term of type %d in content model of complex "
11344 "type '%s'.\n",
11345 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011346 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011347 }
11348}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011349
Daniel Veillard4255d502002-04-16 15:50:10 +000011350/**
11351 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011352 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011353 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011354 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011355 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011356 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011357 */
11358static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011359xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011360 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011361 const xmlChar * name)
11362{
Daniel Veillard4255d502002-04-16 15:50:10 +000011363 xmlAutomataStatePtr start;
11364
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011365 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11366 (type->contModel != NULL) ||
11367 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11368 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011369 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011370
11371#ifdef DEBUG_CONTENT
11372 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011373 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011374#endif
11375
Daniel Veillard4255d502002-04-16 15:50:10 +000011376 ctxt->am = xmlNewAutomata();
11377 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011378 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011379 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011380 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011381 }
11382 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011383 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011384 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011385 type->contModel = xmlAutomataCompile(ctxt->am);
11386 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011387 xmlSchemaPCustomErr(ctxt,
11388 XML_SCHEMAP_INTERNAL,
11389 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011390 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011391 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011392 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011393 XML_SCHEMAP_NOT_DETERMINISTIC,
11394 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011395 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011396 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011397 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011398#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011399 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011400 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011401 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011402#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011403 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011404 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011405 xmlFreeAutomata(ctxt->am);
11406 ctxt->am = NULL;
11407}
11408
11409/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011410 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011411 * @elem: the schema element context
11412 * @ctxt: the schema parser context
11413 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011414 * Resolves the references of an element declaration
11415 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011416 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011417 */
11418static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011419xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011420 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011421 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011422 const xmlChar * context ATTRIBUTE_UNUSED,
11423 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011424{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011425 if ((ctxt == NULL) || (elemDecl == NULL) ||
11426 ((elemDecl != NULL) &&
11427 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011428 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011429 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011430
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011431 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011432 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011433
11434 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011435 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011437 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 elemDecl->namedTypeNs);
11439 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011440 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011441 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011442 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011443 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011444 XML_SCHEMA_TYPE_BASIC, "type definition");
11445 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011446 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011447 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011448 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011449 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011450
Daniel Veillardc0826a72004-08-10 14:17:33 +000011451 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011453 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011455 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11456 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011457 if (substHead == NULL) {
11458 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011459 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011460 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011461 "substitutionGroup", elemDecl->substGroup,
11462 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011463 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011464 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011465 /*
11466 * Set the "substitution group affiliation".
11467 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011468 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011469 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011470 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011471 * (type definition)...otherwise the {type definition} of the
11472 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011473 * the substitutionGroup [attribute], if present
11474 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011475 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011476 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011477 }
11478 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011479 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11480 (elemDecl->substGroup == NULL))
11481 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011482}
11483
11484/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011485 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011486 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011488 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011489 * Checks and builds the "member type definitions" property of the union
11490 * simple type. This handles part (1), part (2) is done in
11491 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11492 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011493 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011494 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011495static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011496xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11497 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011498{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011499
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011500 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011501 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011502
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011503 /*
11504 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11505 * define the explicit members as the type definitions ·resolved·
11506 * to by the items in the ·actual value· of the memberTypes [attribute],
11507 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011508 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011509 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011510 /*
11511 * Resolve references.
11512 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011514 lastLink = NULL;
11515 while (link != NULL) {
11516 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011517
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011518 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11519 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11520
11521 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11522 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11523 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011525 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11526 /*
11527 * Remove the member type link.
11528 */
11529 if (lastLink == NULL)
11530 type->memberTypes = link->next;
11531 else
11532 lastLink->next = link->next;
11533 newLink = link;
11534 link = link->next;
11535 xmlFree(newLink);
11536 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 lastLink = link;
11539 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011540 }
11541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011542 /*
11543 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011544 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011545 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011546 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011547 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11548 if (link == NULL) {
11549 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11550 return (-1);
11551 }
11552 link->type = memberType;
11553 link->next = NULL;
11554 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011555 type->memberTypes = link;
11556 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011557 lastLink->next = link;
11558 lastLink = link;
11559 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011560 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011561 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011562}
11563
Daniel Veillard4255d502002-04-16 15:50:10 +000011564/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011565 * xmlSchemaIsDerivedFromBuiltInType:
11566 * @ctxt: the schema parser context
11567 * @type: the type definition
11568 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011569 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011570 *
11571 * Returns 1 if the type has the given value type, or
11572 * is derived from such a type.
11573 */
William M. Brack803812b2004-06-03 02:11:24 +000011574static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011575xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011576{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011577 if (type == NULL)
11578 return (0);
11579 if (IS_COMPLEX_TYPE(type))
11580 return (0);
11581 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11582 if (type->builtInType == valType)
11583 return(1);
11584 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11585 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11586 return (0);
11587 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11588 } else
11589 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011590
11591 return (0);
11592}
11593
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011594#if 0
11595/**
11596 * xmlSchemaIsDerivedFromBuiltInType:
11597 * @ctxt: the schema parser context
11598 * @type: the type definition
11599 * @valType: the value type
11600 *
11601 *
11602 * Returns 1 if the type has the given value type, or
11603 * is derived from such a type.
11604 */
11605static int
11606xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11607{
11608 if (type == NULL)
11609 return (0);
11610 if (IS_COMPLEX_TYPE(type))
11611 return (0);
11612 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11613 if (type->builtInType == valType)
11614 return(1);
11615 return (0);
11616 } else
11617 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11618
11619 return (0);
11620}
11621#endif
11622
11623static xmlSchemaTypePtr
11624xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11625{
11626 if (type == NULL)
11627 return (NULL);
11628 if (IS_COMPLEX_TYPE(type))
11629 return (NULL);
11630 if (type->type == XML_SCHEMA_TYPE_BASIC)
11631 return(type);
11632 else
11633 return(xmlSchemaQueryBuiltInType(type->subtypes));
11634
11635 return (NULL);
11636}
11637
Daniel Veillard3646d642004-06-02 19:19:14 +000011638/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011639 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011640 * @type: the simpleType definition
11641 *
11642 * Returns the primitive type of the given type or
11643 * NULL in case of error.
11644 */
11645static xmlSchemaTypePtr
11646xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11647{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011648
Daniel Veillard01fa6152004-06-29 17:04:39 +000011649 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011650 /*
11651 * Note that anySimpleType is actually not a primitive type
11652 * but we need that here.
11653 */
11654 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11655 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011656 return (type);
11657 type = type->baseType;
11658 }
11659
11660 return (NULL);
11661}
11662
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011663#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011664/**
11665 * xmlSchemaGetBuiltInTypeAncestor:
11666 * @type: the simpleType definition
11667 *
11668 * Returns the primitive type of the given type or
11669 * NULL in case of error.
11670 */
11671static xmlSchemaTypePtr
11672xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11673{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011674 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011675 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011676 while (type != NULL) {
11677 if (type->type == XML_SCHEMA_TYPE_BASIC)
11678 return (type);
11679 type = type->baseType;
11680 }
11681
11682 return (NULL);
11683}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011684#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011685
Daniel Veillard01fa6152004-06-29 17:04:39 +000011686/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011687 * xmlSchemaBuildAttributeUsesOwned:
11688 * @ctxt: the schema parser context
11689 * @type: the complex type definition
11690 * @cur: the attribute declaration list
11691 * @lastUse: the top of the attribute use list
11692 *
11693 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011694 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011695 * xmlSchemaBuildAttributeValidation only.
11696 */
11697static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011698xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011699 xmlSchemaAttributePtr cur,
11700 xmlSchemaAttributeLinkPtr *uses,
11701 xmlSchemaAttributeLinkPtr *lastUse)
11702{
11703 xmlSchemaAttributeLinkPtr tmp;
11704 while (cur != NULL) {
11705 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011706 /*
11707 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11708 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011709 * <attributeGroup> [children], if any."
11710 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011711 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11712 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011713 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011714 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011715 }
11716 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011717 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011718 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011719 */
11720 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011721 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11722 if (tmp == NULL) {
11723 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11724 return (-1);
11725 }
11726 tmp->attr = cur;
11727 tmp->next = NULL;
11728 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011729 *uses = tmp;
11730 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011731 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011732 *lastUse = tmp;
11733 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011734 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011735 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011736 return (0);
11737}
11738
Daniel Veillard50355f02004-06-08 17:52:16 +000011739/**
11740 * xmlSchemaCloneWildcardNsConstraints:
11741 * @ctxt: the schema parser context
11742 * @dest: the destination wildcard
11743 * @source: the source wildcard
11744 *
11745 * Clones the namespace constraints of source
11746 * and assignes them to dest.
11747 * Returns -1 on internal error, 0 otherwise.
11748 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011749static int
11750xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11751 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011752 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011753{
11754 xmlSchemaWildcardNsPtr cur, tmp, last;
11755
11756 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011757 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011758 (*dest)->any = source->any;
11759 cur = source->nsSet;
11760 last = NULL;
11761 while (cur != NULL) {
11762 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11763 if (tmp == NULL)
11764 return(-1);
11765 tmp->value = cur->value;
11766 if (last == NULL)
11767 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011768 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011769 last->next = tmp;
11770 last = tmp;
11771 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011772 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011773 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011774 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011775 if (source->negNsSet != NULL) {
11776 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11777 if ((*dest)->negNsSet == NULL)
11778 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011779 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011780 } else
11781 (*dest)->negNsSet = NULL;
11782 return(0);
11783}
11784
Daniel Veillard50355f02004-06-08 17:52:16 +000011785/**
11786 * xmlSchemaUnionWildcards:
11787 * @ctxt: the schema parser context
11788 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011789 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011790 *
11791 * Unions the namespace constraints of the given wildcards.
11792 * @completeWild will hold the resulting union.
11793 * Returns a positive error code on failure, -1 in case of an
11794 * internal error, 0 otherwise.
11795 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011796static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011797xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011798 xmlSchemaWildcardPtr completeWild,
11799 xmlSchemaWildcardPtr curWild)
11800{
11801 xmlSchemaWildcardNsPtr cur, curB, tmp;
11802
11803 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011804 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011805 * value.
11806 */
11807 if ((completeWild->any == curWild->any) &&
11808 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11809 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011810
Daniel Veillard3646d642004-06-02 19:19:14 +000011811 if ((completeWild->negNsSet == NULL) ||
11812 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011813
Daniel Veillard3646d642004-06-02 19:19:14 +000011814 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011815 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011816
11817 /*
11818 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011819 */
11820 cur = completeWild->nsSet;
11821 while (cur != NULL) {
11822 found = 0;
11823 curB = curWild->nsSet;
11824 while (curB != NULL) {
11825 if (cur->value == curB->value) {
11826 found = 1;
11827 break;
11828 }
11829 curB = curB->next;
11830 }
11831 if (!found)
11832 break;
11833 cur = cur->next;
11834 }
11835 if (found)
11836 return(0);
11837 } else
11838 return(0);
11839 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011840 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011841 /*
11842 * 2 If either O1 or O2 is any, then any must be the value
11843 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011844 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011845 if (completeWild->any == 0) {
11846 completeWild->any = 1;
11847 if (completeWild->nsSet != NULL) {
11848 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11849 completeWild->nsSet = NULL;
11850 }
11851 if (completeWild->negNsSet != NULL) {
11852 xmlFree(completeWild->negNsSet);
11853 completeWild->negNsSet = NULL;
11854 }
11855 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011856 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011857 }
11858 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011860 * then the union of those sets must be the value.
11861 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011862 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011863 int found;
11864 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011865
Daniel Veillard3646d642004-06-02 19:19:14 +000011866 cur = curWild->nsSet;
11867 start = completeWild->nsSet;
11868 while (cur != NULL) {
11869 found = 0;
11870 curB = start;
11871 while (curB != NULL) {
11872 if (cur->value == curB->value) {
11873 found = 1;
11874 break;
11875 }
11876 curB = curB->next;
11877 }
11878 if (!found) {
11879 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011880 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011881 return (-1);
11882 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011883 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011884 completeWild->nsSet = tmp;
11885 }
11886 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011887 }
11888
Daniel Veillard3646d642004-06-02 19:19:14 +000011889 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011890 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011891 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011893 * or ·absent·), then a pair of not and ·absent· must be the value.
11894 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011895 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011896 (curWild->negNsSet != NULL) &&
11897 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11898 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011899
11900 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011901 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011903 * 5.
11904 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011905 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011906 (completeWild->negNsSet->value != NULL) &&
11907 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011908 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011909 (curWild->negNsSet->value != NULL) &&
11910 (completeWild->nsSet != NULL))) {
11911
11912 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011913
Daniel Veillard3646d642004-06-02 19:19:14 +000011914 if (completeWild->nsSet != NULL) {
11915 cur = completeWild->nsSet;
11916 curB = curWild->negNsSet;
11917 } else {
11918 cur = curWild->nsSet;
11919 curB = completeWild->negNsSet;
11920 }
11921 nsFound = 0;
11922 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011923 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011924 absentFound = 1;
11925 else if (cur->value == curB->value)
11926 nsFound = 1;
11927 if (nsFound && absentFound)
11928 break;
11929 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011930 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011931
11932 if (nsFound && absentFound) {
11933 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011934 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011935 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011936 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011937 completeWild->any = 1;
11938 if (completeWild->nsSet != NULL) {
11939 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11940 completeWild->nsSet = NULL;
11941 }
11942 if (completeWild->negNsSet != NULL) {
11943 xmlFree(completeWild->negNsSet);
11944 completeWild->negNsSet = NULL;
11945 }
11946 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011947 /*
11948 * 5.2 If the set S includes the negated namespace name
11949 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011950 * be the value.
11951 */
11952 if (completeWild->nsSet != NULL) {
11953 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11954 completeWild->nsSet = NULL;
11955 }
11956 if (completeWild->negNsSet == NULL) {
11957 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11958 if (completeWild->negNsSet == NULL)
11959 return (-1);
11960 }
11961 completeWild->negNsSet->value = NULL;
11962 } else if ((!nsFound) && absentFound) {
11963 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011964 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011965 * namespace name, then the union is not expressible.
11966 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011968 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011969 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011970 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011971 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011972 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011973 /*
11974 * 5.4 If the set S does not include either the negated namespace
11975 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011976 * and a namespace name must be the value.
11977 */
11978 if (completeWild->negNsSet == NULL) {
11979 if (completeWild->nsSet != NULL) {
11980 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11981 completeWild->nsSet = NULL;
11982 }
11983 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11984 if (completeWild->negNsSet == NULL)
11985 return (-1);
11986 completeWild->negNsSet->value = curWild->negNsSet->value;
11987 }
11988 }
11989 return (0);
11990 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011991 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011992 * 6.
11993 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011994 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011995 (completeWild->negNsSet->value == NULL) &&
11996 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011997 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011998 (curWild->negNsSet->value == NULL) &&
11999 (completeWild->nsSet != NULL))) {
12000
12001 if (completeWild->nsSet != NULL) {
12002 cur = completeWild->nsSet;
12003 } else {
12004 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012005 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012006 while (cur != NULL) {
12007 if (cur->value == NULL) {
12008 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012009 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012010 * value.
12011 */
12012 completeWild->any = 1;
12013 if (completeWild->nsSet != NULL) {
12014 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12015 completeWild->nsSet = NULL;
12016 }
12017 if (completeWild->negNsSet != NULL) {
12018 xmlFree(completeWild->negNsSet);
12019 completeWild->negNsSet = NULL;
12020 }
12021 return (0);
12022 }
12023 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012024 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012025 if (completeWild->negNsSet == NULL) {
12026 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012027 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012028 * and ·absent· must be the value.
12029 */
12030 if (completeWild->nsSet != NULL) {
12031 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12032 completeWild->nsSet = NULL;
12033 }
12034 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12035 if (completeWild->negNsSet == NULL)
12036 return (-1);
12037 completeWild->negNsSet->value = NULL;
12038 }
12039 return (0);
12040 }
12041 return (0);
12042
12043}
12044
Daniel Veillard50355f02004-06-08 17:52:16 +000012045/**
12046 * xmlSchemaIntersectWildcards:
12047 * @ctxt: the schema parser context
12048 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012049 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012050 *
12051 * Intersects the namespace constraints of the given wildcards.
12052 * @completeWild will hold the resulting intersection.
12053 * Returns a positive error code on failure, -1 in case of an
12054 * internal error, 0 otherwise.
12055 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012056static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012057xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012058 xmlSchemaWildcardPtr completeWild,
12059 xmlSchemaWildcardPtr curWild)
12060{
William M. Brack803812b2004-06-03 02:11:24 +000012061 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012062
12063 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012064 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012065 * value.
12066 */
12067 if ((completeWild->any == curWild->any) &&
12068 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12069 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012070
Daniel Veillard3646d642004-06-02 19:19:14 +000012071 if ((completeWild->negNsSet == NULL) ||
12072 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012073
Daniel Veillard3646d642004-06-02 19:19:14 +000012074 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012075 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012076
12077 /*
12078 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012079 */
12080 cur = completeWild->nsSet;
12081 while (cur != NULL) {
12082 found = 0;
12083 curB = curWild->nsSet;
12084 while (curB != NULL) {
12085 if (cur->value == curB->value) {
12086 found = 1;
12087 break;
12088 }
12089 curB = curB->next;
12090 }
12091 if (!found)
12092 break;
12093 cur = cur->next;
12094 }
12095 if (found)
12096 return(0);
12097 } else
12098 return(0);
12099 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012100 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012101 /*
12102 * 2 If either O1 or O2 is any, then the other must be the value.
12103 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012104 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012105 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012106 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012107 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012108 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012109 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012110 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12111 * name or ·absent·) and the other is a set of (namespace names or
12112 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012113 * the set, minus ·absent· if it was in the set, must be the value.
12114 */
12115 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12116 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12117 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012118
Daniel Veillard3646d642004-06-02 19:19:14 +000012119 if (completeWild->nsSet == NULL) {
12120 neg = completeWild->negNsSet->value;
12121 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12122 return(-1);
12123 } else
12124 neg = curWild->negNsSet->value;
12125 /*
12126 * Remove absent and negated.
12127 */
12128 prev = NULL;
12129 cur = completeWild->nsSet;
12130 while (cur != NULL) {
12131 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012132 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012133 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012134 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012135 prev->next = cur->next;
12136 xmlFree(cur);
12137 break;
12138 }
12139 prev = cur;
12140 cur = cur->next;
12141 }
12142 if (neg != NULL) {
12143 prev = NULL;
12144 cur = completeWild->nsSet;
12145 while (cur != NULL) {
12146 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012147 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012148 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012149 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012150 prev->next = cur->next;
12151 xmlFree(cur);
12152 break;
12153 }
12154 prev = cur;
12155 cur = cur->next;
12156 }
12157 }
12158
12159 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012160 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012161 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012162 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012163 * then the intersection of those sets must be the value.
12164 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012165 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012166 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012167
Daniel Veillard3646d642004-06-02 19:19:14 +000012168 cur = completeWild->nsSet;
12169 prev = NULL;
12170 while (cur != NULL) {
12171 found = 0;
12172 curB = curWild->nsSet;
12173 while (curB != NULL) {
12174 if (cur->value == curB->value) {
12175 found = 1;
12176 break;
12177 }
12178 curB = curB->next;
12179 }
12180 if (!found) {
12181 if (prev == NULL)
12182 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012183 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012184 prev->next = cur->next;
12185 tmp = cur->next;
12186 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012187 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012188 continue;
12189 }
12190 prev = cur;
12191 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012192 }
12193
Daniel Veillard3646d642004-06-02 19:19:14 +000012194 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012195 }
12196 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012197 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012198 */
12199 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012200 (curWild->negNsSet != NULL) &&
12201 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012202 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012203 (curWild->negNsSet->value != NULL)) {
12204
12205 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012206 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012207 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012208 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012209 }
12210 /*
12211 * 6 If the one is a negation of a namespace name and the other
12212 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012213 * of a namespace name must be the value.
12214 */
12215 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12216 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217 (completeWild->negNsSet->value == NULL)) {
12218 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012219 }
12220 return(0);
12221}
12222
Daniel Veillard50355f02004-06-08 17:52:16 +000012223/**
12224 * xmlSchemaIsWildcardNsConstraintSubset:
12225 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012226 * @sub: the first wildcard
12227 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012228 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012229 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12230 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012231 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012232 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012233 */
12234static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012235xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12236 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012237{
Daniel Veillard50355f02004-06-08 17:52:16 +000012238 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012239 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012240 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012241 if (super->any)
12242 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012243 /*
12244 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12245 * 2.2 super must be a pair of not and the same value.
12246 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012247 if ((sub->negNsSet != NULL) &&
12248 (super->negNsSet != NULL) &&
12249 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012250 return (0);
12251 /*
12252 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012253 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012254 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012255 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012256 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012257 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012258 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012259 xmlSchemaWildcardNsPtr cur, curB;
12260 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012261
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012262 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012263 while (cur != NULL) {
12264 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012265 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012266 while (curB != NULL) {
12267 if (cur->value == curB->value) {
12268 found = 1;
12269 break;
12270 }
12271 curB = curB->next;
12272 }
12273 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012274 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012275 cur = cur->next;
12276 }
12277 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012278 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012279 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012280 xmlSchemaWildcardNsPtr cur;
12281 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012282 * 3.2.2 super must be a pair of not and a namespace name or
12283 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012284 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012285 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012286 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012287 if (cur->value == super->negNsSet->value)
12288 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012289 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012290 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012291 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012292 }
12293 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012294 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012295}
12296
12297/**
12298 * xmlSchemaBuildCompleteAttributeWildcard:
12299 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012300 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012301 * @completeWild: the resulting complete wildcard
12302 *
12303 * Returns -1 in case of an internal error, 0 otherwise.
12304 */
12305static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012306xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012307 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012308 xmlSchemaWildcardPtr *completeWild)
12309{
Daniel Veillard3646d642004-06-02 19:19:14 +000012310 while (attrs != NULL) {
12311 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12312 xmlSchemaAttributeGroupPtr group;
12313
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012314 group = (xmlSchemaAttributeGroupPtr) attrs;
12315 /*
12316 * Handle attribute group references.
12317 */
12318 if (group->ref != NULL) {
12319 if (group->refItem == NULL) {
12320 /*
12321 * TODO: Should we raise a warning here?
12322 */
12323 /*
12324 * The referenced attribute group definition could not
12325 * be resolved beforehand, so skip.
12326 */
12327 attrs = attrs->next;
12328 continue;
12329 } else
12330 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012331 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012332 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012333 * For every attribute group definition, an intersected wildcard
12334 * will be created (assumed that a wildcard exists on the
12335 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012336 * at all).
12337 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12338 * that the intersection will be performed only once.
12339 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012340 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12341 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012342 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012343 group->attributes, &group->attributeWildcard) == -1)
12344 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012345 }
12346 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012347 }
12348 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012349 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012350 /*
12351 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012352 *
12353 * Although the complete wildcard might not correspond to any
12354 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012355 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012356 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12357 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12358 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012359 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012360 completeWild, group->attributeWildcard) == -1)
12361 return (-1);
12362 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012363 (*completeWild)->node = group->attributeWildcard->node;
12364 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012365 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012366 }
12367 }
12368 attrs = attrs->next;
12369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012370
12371 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012372}
12373
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012374static int
12375xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12376 int *fixed,
12377 const xmlChar **value,
12378 xmlSchemaValPtr *val)
12379{
12380 *fixed = 0;
12381 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012382 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012383 *val = NULL;
12384
12385 if (item->defValue == NULL)
12386 item = item->refDecl;
12387
12388 if (item == NULL)
12389 return (0);
12390
12391 if (item->defValue != NULL) {
12392 *value = item->defValue;
12393 if (val != 0)
12394 *val = item->defVal;
12395 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12396 *fixed = 1;
12397 return (1);
12398 }
12399 return (0);
12400}
Daniel Veillard3646d642004-06-02 19:19:14 +000012401/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012403 * @wild: the wildcard
12404 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012405 *
12406 * Validation Rule: Wildcard allows Namespace Name
12407 * (cvc-wildcard-namespace)
12408 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012409 *
12410 * Returns 1 if the given namespace matches the wildcard,
12411 * 0 otherwise.
12412 */
12413static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012414xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12415 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012416{
12417 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012418 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012419
12420 if (wild->any)
12421 return(1);
12422 else if (wild->nsSet != NULL) {
12423 xmlSchemaWildcardNsPtr cur;
12424
12425 cur = wild->nsSet;
12426 while (cur != NULL) {
12427 if (xmlStrEqual(cur->value, ns))
12428 return(1);
12429 cur = cur->next;
12430 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012431 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012432 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012433 return(1);
12434
Daniel Veillard3646d642004-06-02 19:19:14 +000012435 return(0);
12436}
12437
12438/**
12439 * xmlSchemaBuildAttributeValidation:
12440 * @ctxt: the schema parser context
12441 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012442 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012443 *
12444 * Builds the wildcard and the attribute uses on the given complex type.
12445 * Returns -1 if an internal error occurs, 0 otherwise.
12446 */
12447static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012448xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12449 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012450{
12451 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012452 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12453 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012454 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012455 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012456 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012457 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012458
Daniel Veillard01fa6152004-06-29 17:04:39 +000012459 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012460 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012461 * Complex Type Definition with complex content Schema Component.
12462 *
12463 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012464 * TODO: Add checks for absent referenced attribute declarations and
12465 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012466 */
12467 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012468 PERROR_INT("xmlSchemaBuildAttributeValidation",
12469 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012470 return (-1);
12471 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012472 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012473 PERROR_INT("xmlSchemaBuildAttributeValidation",
12474 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012475 return (-1);
12476 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012477 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012478 /*
12479 * Inherit the attribute uses of the base type.
12480 */
12481 /*
12482 * NOTE: It is allowed to "extend" the anyType complex type.
12483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012484 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012485 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012486 for (cur = baseType->attributeUses; cur != NULL;
12487 cur = cur->next) {
12488 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012489 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12490 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012491 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012492 "building attribute uses of complexType", NULL);
12493 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012494 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012495 tmp->attr = cur->attr;
12496 tmp->next = NULL;
12497 if (type->attributeUses == NULL) {
12498 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012499 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012500 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012501 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012502 }
12503 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012504 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012505 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012506 /*
12507 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012508 */
12509 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12510 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012511 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012512 * NOTE: During the parse time, the wildcard is created on the complexType
12513 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012514 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012515 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012516 PERROR_INT("xmlSchemaBuildAttributeValidation",
12517 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012518 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012519 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012520
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012521 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12522 ((IS_ANYTYPE(baseType)) ||
12523 ((baseType != NULL) &&
12524 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12525 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012526 if (type->attributeWildcard != NULL) {
12527 /*
12528 * Union the complete wildcard with the base wildcard.
12529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012531 baseType->attributeWildcard) == -1)
12532 return (-1);
12533 } else {
12534 /*
12535 * Just inherit the wildcard.
12536 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012537 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012538 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012539 * wildcard is shared.
12540 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012541 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012542 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012544
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012545 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12546 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012547 /*
12548 * Derivation Valid (Restriction, Complex)
12549 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012550 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 if (baseType->attributeWildcard == NULL) {
12552 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012553 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012555 "The type has an attribute wildcard, "
12556 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012557 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012558 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012559 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012560 } else if (xmlSchemaCheckCOSNSSubset(
12561 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012562 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012563 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012564 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012565 NULL, type, NULL,
12566 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012567 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012568 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12569 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012570 return (1);
12571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012572 /* 4.3 Unless the {base type definition} is the ·ur-type
12573 * definition·, the complex type definition's {attribute
12574 * wildcard}'s {process contents} must be identical to or
12575 * stronger than the {base type definition}'s {attribute
12576 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012577 * than lax is stronger than skip.
12578 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012579 if ((! IS_ANYTYPE(baseType)) &&
12580 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012581 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012582 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012583 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012584 NULL, type, NULL,
12585 "The 'process contents' of the attribute wildcard is "
12586 "weaker than the one in the base type %s",
12587 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012588 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012589 return (1);
12590 }
12591 }
12592 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12593 /*
12594 * Derivation Valid (Extension)
12595 * At this point the type and the base have both, either
12596 * no wildcard or a wildcard.
12597 */
12598 if ((baseType->attributeWildcard != NULL) &&
12599 (baseType->attributeWildcard != type->attributeWildcard)) {
12600 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012601 if (xmlSchemaCheckCOSNSSubset(
12602 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012603 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012604 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012605 NULL, type, NULL,
12606 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012607 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12609 FREE_AND_NULL(str)
12610 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012612 }
12613 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012614
Daniel Veillard3646d642004-06-02 19:19:14 +000012615 /*
12616 * Gather attribute uses defined by this type.
12617 */
12618 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012619 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012620 &uses, &lastUse) == -1) {
12621 return (-1);
12622 }
12623 }
12624 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012626 * not have identical {name}s and {target namespace}s."
12627 *
12628 * For "extension" this is done further down.
12629 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012630 if ((uses != NULL) && ((type->flags &
12631 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012632 cur = uses;
12633 while (cur != NULL) {
12634 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012635 while (tmp != NULL) {
12636 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012637 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012638 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012639 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12640
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012641 xmlSchemaPAttrUseErr(pctxt,
12642 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12643 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012644 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012645 xmlSchemaFormatQName(&str,
12646 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12647 xmlSchemaGetAttrName(tmp->attr)));
12648 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012649 break;
12650 }
12651 tmp = tmp->next;
12652 }
12653 cur = cur->next;
12654 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012655 }
12656 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012657 /*
12658 * Derive by restriction.
12659 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012660 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012661 type->attributeUses = uses;
12662 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012663 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012664 const xmlChar *bEffValue;
12665 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012666
12667 cur = uses;
12668 while (cur != NULL) {
12669 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012670 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012671 base = type->attributeUses;
12672 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012673 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012674 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012675 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012677
12678 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012679
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012680 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012681 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12682 (base->attr->occurs ==
12683 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12684 /*
12685 * NOOP.
12686 */
12687 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012688 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12689 (base->attr->occurs ==
12690 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012691 /*
12692 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012693 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012694 xmlSchemaPAttrUseErr(pctxt,
12695 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12696 type, cur->attr,
12697 "The 'optional' use is inconsistent with a "
12698 "matching 'required' use of the base type",
12699 NULL);
12700 } else if ((cur->attr->occurs ==
12701 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12702 (base->attr->occurs ==
12703 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12704 /*
12705 * derivation-ok-restriction 3
12706 */
12707 xmlSchemaPCustomErr(pctxt,
12708 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12709 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012710 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012711 "attribute use '%s' of the base type is "
12712 "missing",
12713 xmlSchemaFormatQName(&str,
12714 xmlSchemaGetAttrTargetNsURI(base->attr),
12715 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012716 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012717 } else if (xmlSchemaCheckCOSSTDerivedOK(
12718 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12719
12720 /*
12721 * SPEC (2.1.2) "R's {attribute declaration}'s
12722 * {type definition} must be validly derived from
12723 * B's {type definition} given the empty set as
12724 * defined in Type Derivation OK (Simple) (§3.14.6)."
12725 */
12726 xmlSchemaPAttrUseErr(pctxt,
12727 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12728 type, cur->attr,
12729 "The attribute declaration's type "
12730 "definition is not validly derived from "
12731 "the corresponding definition in the "
12732 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012733 } else {
12734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012735 * 2.1.3 [Definition:] Let the effective value
12736 * constraint of an attribute use be its {value
12737 * constraint}, if present, otherwise its {attribute
12738 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012739 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012740 xmlSchemaGetEffectiveValueConstraint(base->attr,
12741 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012742 /*
12743 * 2.1.3 ... one of the following must be true
12744 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012745 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012746 * ·absent· or default.
12747 */
12748 if ((bEffValue != NULL) &&
12749 (effFixed == 1)) {
12750 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012751
12752 xmlSchemaGetEffectiveValueConstraint(base->attr,
12753 &effFixed, &rEffValue, 0);
12754 /*
12755 * 2.1.3.2 R's ·effective value constraint· is
12756 * fixed with the same string as B's.
12757 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012758 */
12759 if ((effFixed == 0) ||
12760 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012761 xmlSchemaPAttrUseErr(pctxt,
12762 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12763 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012764 "The effective value constraint of the "
12765 "attribute use is inconsistent with "
12766 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012767 NULL);
12768 } else {
12769 /*
12770 * Override the attribute use.
12771 */
12772 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012773 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012774 } else
12775 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012776 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012777
Daniel Veillard3646d642004-06-02 19:19:14 +000012778 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012779 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012780 base = base->next;
12781 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012782
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012783 if ((!found) && (cur->attr->occurs !=
12784 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12785 /*
12786 * derivation-ok-restriction 2.2
12787 */
12788 if ((baseType->attributeWildcard == NULL) ||
12789 (xmlSchemaCheckCVCWildcardNamespace(
12790 baseType->attributeWildcard,
12791 cur->attr->targetNamespace) != 1)) {
12792 xmlSchemaPAttrUseErr(pctxt,
12793 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12794 type, cur->attr,
12795 "Neither a matching attribute use, "
12796 "nor a matching wildcard in the base type does exist",
12797 NULL);
12798 } else {
12799 /*
12800 * Add the attribute use.
12801 *
12802 * Note that this may lead to funny derivation error reports, if
12803 * multiple equal attribute uses exist; but this is not
12804 * allowed anyway, and it will be reported beforehand.
12805 */
12806 tmp = cur;
12807 if (prev != NULL)
12808 prev->next = cur->next;
12809 else
12810 uses = cur->next;
12811 cur = cur->next;
12812 tmp->next = NULL;
12813 if (type->attributeUses == NULL) {
12814 type->attributeUses = tmp;
12815 } else
12816 lastBaseUse->next = tmp;
12817 lastBaseUse = tmp;
12818
12819 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012820 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012821 }
12822 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012823 cur = cur->next;
12824 }
12825 if (uses != NULL)
12826 xmlSchemaFreeAttributeUseList(uses);
12827 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012828 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012829 /*
12830 * The spec allows only appending, and not other kinds of extensions.
12831 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012832 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012833 */
12834 if (uses != NULL) {
12835 if (type->attributeUses == NULL) {
12836 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012837 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012838 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012839 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012840 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012841 PERROR_INT("xmlSchemaBuildAttributeValidation",
12842 "no derivation method");
12843 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012844 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012845 /*
12846 * 3.4.6 -> Complex Type Definition Properties Correct
12847 */
12848 if (type->attributeUses != NULL) {
12849 cur = type->attributeUses;
12850 prev = NULL;
12851 while (cur != NULL) {
12852 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012853 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012854 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012855 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012856 * Note that this was already done for "restriction" and types derived from
12857 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012858 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012859 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12860 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012861 while (tmp != NULL) {
12862 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012863 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012864 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012865 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012866
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012867 xmlSchemaPAttrUseErr(pctxt,
12868 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12869 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012870 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012871 break;
12872 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012873 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012874 }
12875 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012876 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012877 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012878 * not have {type definition}s which are or are derived from ID.
12879 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012880 if ((cur->attr->subtypes != NULL) &&
12881 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12882 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012883 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012884 xmlSchemaPAttrUseErr(pctxt,
12885 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12886 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012887 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012888 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012889 NULL);
12890 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012891 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012892 id = cur;
12893 }
12894 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012895 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012896 * stage is to be able to catch dublicate attribute uses. So we had to keep
12897 * prohibited uses in the list as well.
12898 */
12899 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12900 tmp = cur;
12901 if (prev == NULL)
12902 type->attributeUses = cur->next;
12903 else
12904 prev->next = cur->next;
12905 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012906 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012907 } else {
12908 prev = cur;
12909 cur = cur->next;
12910 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012911 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012912 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012913 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012914 * TODO: This check should be removed if we are 100% sure of
12915 * the base type attribute uses already being built.
12916 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012917 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012918 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012919 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920 PERROR_INT("xmlSchemaBuildAttributeValidation",
12921 "attribute uses not builded on base type");
12922 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012923 return (0);
12924}
12925
12926/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012927 * xmlSchemaTypeFinalContains:
12928 * @schema: the schema
12929 * @type: the type definition
12930 * @final: the final
12931 *
12932 * Evaluates if a type definition contains the given "final".
12933 * This does take "finalDefault" into account as well.
12934 *
12935 * Returns 1 if the type does containt the given "final",
12936 * 0 otherwise.
12937 */
12938static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012939xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012940{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012941 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012942 return (0);
12943 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012944 return (1);
12945 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012946 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012947}
12948
12949/**
12950 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12951 * @type: the Union Simple Type
12952 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012953 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012954 * returns NULL otherwise.
12955 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012956static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012957xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12958{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012959 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012960 if (type->memberTypes != NULL)
12961 return (type->memberTypes);
12962 else
12963 type = type->baseType;
12964 }
12965 return (NULL);
12966}
12967
12968/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012969 * xmlSchemaGetParticleTotalRangeMin:
12970 * @particle: the particle
12971 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012972 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012973 * (all and sequence) + (choice)
12974 *
12975 * Returns the minimun Effective Total Range.
12976 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012977static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012978xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012979{
12980 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012981 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012982 return (0);
12983 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012984 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012985 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012986 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012987
12988 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012989 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012990 while (part != NULL) {
12991 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12992 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012993 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012994 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012995 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012996 if (cur == 0)
12997 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012998 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012999 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013000 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013001 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013002 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013003 } else {
13004 /* <all> and <sequence> */
13005 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013006 xmlSchemaParticlePtr part =
13007 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013008
13009 if (part == NULL)
13010 return (0);
13011 do {
13012 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13013 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013014 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013015 else
13016 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013017 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013018 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013019 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013020 }
13021}
13022
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013023/**
13024 * xmlSchemaGetParticleTotalRangeMax:
13025 * @particle: the particle
13026 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013027 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013028 * (all and sequence) + (choice)
13029 *
13030 * Returns the maximum Effective Total Range.
13031 */
13032static int
13033xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13034{
13035 if ((particle->children == NULL) ||
13036 (particle->children->children == NULL))
13037 return (0);
13038 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13039 int max = -1, cur;
13040 xmlSchemaParticlePtr part =
13041 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013042
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013043 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13044 if (part->children == NULL)
13045 continue;
13046 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13047 (part->children->type == XML_SCHEMA_TYPE_ANY))
13048 cur = part->maxOccurs;
13049 else
13050 cur = xmlSchemaGetParticleTotalRangeMax(part);
13051 if (cur == UNBOUNDED)
13052 return (UNBOUNDED);
13053 if ((max < cur) || (max == -1))
13054 max = cur;
13055 }
13056 /* TODO: Handle overflows? */
13057 return (particle->maxOccurs * max);
13058 } else {
13059 /* <all> and <sequence> */
13060 int sum = 0, cur;
13061 xmlSchemaParticlePtr part =
13062 (xmlSchemaParticlePtr) particle->children->children;
13063
13064 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13065 if (part->children == NULL)
13066 continue;
13067 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13068 (part->children->type == XML_SCHEMA_TYPE_ANY))
13069 cur = part->maxOccurs;
13070 else
13071 cur = xmlSchemaGetParticleTotalRangeMax(part);
13072 if (cur == UNBOUNDED)
13073 return (UNBOUNDED);
13074 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13075 return (UNBOUNDED);
13076 sum += cur;
13077 }
13078 /* TODO: Handle overflows? */
13079 return (particle->maxOccurs * sum);
13080 }
13081}
13082
13083/**
13084 * xmlSchemaIsParticleEmptiable:
13085 * @particle: the particle
13086 *
13087 * Schema Component Constraint: Particle Emptiable
13088 * Checks whether the given particle is emptiable.
13089 *
13090 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013091 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013092static int
13093xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13094{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013095 /*
13096 * SPEC (1) "Its {min occurs} is 0."
13097 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013098 if ((particle == NULL) || (particle->minOccurs == 0) ||
13099 (particle->children == NULL))
13100 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013101 /*
13102 * SPEC (2) "Its {term} is a group and the minimum part of the
13103 * effective total range of that group, [...] is 0."
13104 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013105 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013106 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013107 return (1);
13108 }
13109 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013110}
13111
13112/**
13113 * xmlSchemaCheckCOSSTDerivedOK:
13114 * @type: the derived simple type definition
13115 * @baseType: the base type definition
13116 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013117 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013118 * Type Derivation OK (Simple) (cos-st-derived-OK)
13119 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013120 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013121 * derived from @baseType.
13122 *
13123 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013124 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013125static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013126xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13127 xmlSchemaTypePtr baseType,
13128 int subset)
13129{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013130 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013131 * 1 They are the same type definition.
13132 * TODO: The identy check might have to be more complex than this.
13133 */
13134 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013135 return (0);
13136 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013137 * 2.1 restriction is not in the subset, or in the {final}
13138 * of its own {base type definition};
13139 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013140 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013141 (xmlSchemaTypeFinalContains(type->baseType,
13142 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13143 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013144 }
13145 /* 2.2 */
13146 if (type->baseType == baseType) {
13147 /*
13148 * 2.2.1 D's ·base type definition· is B.
13149 */
13150 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013151 }
13152 /*
13153 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13154 * and is validly derived from B given the subset, as defined by this
13155 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013156 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013157 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013158 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013159 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013160 return (0);
13161 }
13162 /*
13163 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013164 * definition·.
13165 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013166 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013167 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013168 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013169 }
13170 /*
13171 * 2.2.4 B's {variety} is union and D is validly derived from a type
13172 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013173 * defined by this constraint.
13174 *
13175 * NOTE: This seems not to involve built-in types, since there is no
13176 * built-in Union Simple Type.
13177 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013178 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013179 xmlSchemaTypeLinkPtr cur;
13180
13181 cur = baseType->memberTypes;
13182 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013183 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 return (0);
13185 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013186 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013188
Daniel Veillard01fa6152004-06-29 17:04:39 +000013189 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13190}
13191
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013192/**
13193 * xmlSchemaCheckTypeDefCircularInternal:
13194 * @pctxt: the schema parser context
13195 * @ctxtType: the type definition
13196 * @ancestor: an ancestor of @ctxtType
13197 *
13198 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013199 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013200 *
13201 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13202 * circular, 0 otherwise.
13203 */
13204static int
13205xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13206 xmlSchemaTypePtr ctxtType,
13207 xmlSchemaTypePtr ancestor)
13208{
13209 int ret;
13210
13211 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13212 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013213
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013214 if (ctxtType == ancestor) {
13215 xmlSchemaPCustomErr(pctxt,
13216 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13217 NULL, ctxtType, GET_NODE(ctxtType),
13218 "The definition is circular", NULL);
13219 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13220 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013221 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13222 /*
13223 * Avoid inifinite recursion on circular types not yet checked.
13224 */
13225 return (0);
13226 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013227 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13228 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13229 ancestor->baseType);
13230 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13231 return (ret);
13232}
13233
13234/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013235 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013236 * @item: the complex/simple type definition
13237 * @ctxt: the parser context
13238 * @name: the name
13239 *
13240 * Checks for circular type definitions.
13241 */
13242static void
13243xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013244 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013245 const xmlChar * name ATTRIBUTE_UNUSED)
13246{
13247 if ((item == NULL) ||
13248 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13249 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13250 return;
13251 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13252
13253}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013254
13255/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013256 * xmlSchemaResolveTypeDefs:
13257 * @item: the complex/simple type definition
13258 * @ctxt: the parser context
13259 * @name: the name
13260 *
13261 * Checks for circular type definitions.
13262 */
13263static void
13264xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013265 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013266 const xmlChar * name ATTRIBUTE_UNUSED)
13267{
13268 if (typeDef == NULL)
13269 return;
13270
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013271 /*
13272 * Resolve the base type.
13273 */
13274 if (typeDef->baseType == NULL) {
13275 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13276 typeDef->base, typeDef->baseNs);
13277 if (typeDef->baseType == NULL) {
13278 xmlSchemaPResCompAttrErr(ctxt,
13279 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013280 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013281 "base", typeDef->base, typeDef->baseNs,
13282 XML_SCHEMA_TYPE_SIMPLE, NULL);
13283 return;
13284 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 }
13286 if (IS_SIMPLE_TYPE(typeDef)) {
13287 if (VARIETY_UNION(typeDef)) {
13288 /*
13289 * Resolve the memberTypes.
13290 */
13291 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13292 return;
13293 } else if (VARIETY_LIST(typeDef)) {
13294 /*
13295 * Resolve the itemType.
13296 */
13297 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13298 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13299 typeDef->ref, typeDef->refNs);
13300 if ((typeDef->subtypes == NULL) ||
13301 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13302 typeDef->subtypes = NULL;
13303 xmlSchemaPResCompAttrErr(ctxt,
13304 XML_SCHEMAP_SRC_RESOLVE,
13305 typeDef, typeDef->node,
13306 "itemType", typeDef->ref, typeDef->refNs,
13307 XML_SCHEMA_TYPE_SIMPLE, NULL);
13308 }
13309 }
13310 return;
13311 }
13312 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013313}
13314
13315
13316
13317/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013318 * xmlSchemaCheckSTPropsCorrect:
13319 * @ctxt: the schema parser context
13320 * @type: the simple type definition
13321 *
13322 * Checks st-props-correct.
13323 *
13324 * Returns 0 if the properties are correct,
13325 * if not, a positive error code and -1 on internal
13326 * errors.
13327 */
13328static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013329xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013330 xmlSchemaTypePtr type)
13331{
13332 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13333 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013334 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335
Daniel Veillardc0826a72004-08-10 14:17:33 +000013336 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013337 /*
13338 * Schema Component Constraint: Simple Type Definition Properties Correct
13339 *
13340 * NOTE: This is somehow redundant, since we actually built a simple type
13341 * to have all the needed information; this acts as an self test.
13342 */
13343 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13344 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013345 /* Base type: If the datatype has been ·derived· by ·restriction·
13346 * then the Simple Type Definition component from which it is ·derived·,
13347 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013348 */
13349 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013350 /*
13351 * TODO: Think about: "modulo the impact of Missing
13352 * Sub-components (§5.3)."
13353 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013354 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013355 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013356 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013357 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013358 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013359
Daniel Veillard01fa6152004-06-29 17:04:39 +000013360 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013361 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013362 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013363 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013364 NULL, type, NULL,
13365 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013366 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013367 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013368 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013370 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13371 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13372 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013373 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013374 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013375 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013376 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013377 "the simple ur-type definition as base type, not '%s'",
13378 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013379 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013380 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13381 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013382 /*
13383 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013384 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013385 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13386 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013387 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013388 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013389 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013390 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013391 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13392 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013393 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013394
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013395 /*
13396 * 3 The {final} of the {base type definition} must not contain restriction.
13397 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013398 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013399 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13400 xmlSchemaPCustomErr(ctxt,
13401 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013402 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013403 "The 'final' of its base type '%s' must not contain "
13404 "'restriction'",
13405 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013406 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013407 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013409
13410 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013411 * 2 All simple type definitions must be derived ultimately from the ·simple
13412 * ur-type definition (so· circular definitions are disallowed). That is, it
13413 * must be possible to reach a built-in primitive datatype or the ·simple
13414 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013415 *
13416 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013418 return (0);
13419}
13420
13421/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013422 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 * @ctxt: the schema parser context
13424 * @type: the simple type definition
13425 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013426 * Schema Component Constraint:
13427 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13428
13429 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013430 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013431 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 * a positive error code otherwise.
13434 */
13435static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013436xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013437 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013439 xmlChar *str = NULL;
13440
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013442 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13443 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013444 return (-1);
13445 }
13446
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013448 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 /*
13450 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013451 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 */
13453 if (! VARIETY_ATOMIC(type->baseType)) {
13454 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013455 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013456 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013457 "The base type '%s' is not an atomic simple type",
13458 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013459 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013460 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13461 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013462 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013463 * restriction.
13464 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013465 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013466 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013467 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013468 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013469 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013470 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013471 "The final of its base type '%s' must not contain 'restriction'",
13472 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013473 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013474 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13475 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476
13477 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013478 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013479 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 * Primitive datatypes.
13481 */
13482 if (type->facets != NULL) {
13483 xmlSchemaFacetPtr facet;
13484 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 primitive = xmlSchemaGetPrimitiveType(type);
13487 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13489 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013492 facet = type->facets;
13493 do {
13494 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013495 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013497 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013499 }
13500 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013501 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013502 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013503 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013504 }
13505 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013506 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13507 * of the {base type definition} (call this BF),then the DF's {value}
13508 * must be a valid restriction of BF's {value} as defined in
13509 * [XML Schemas: Datatypes]."
13510 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013512 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013513 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013514 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 xmlSchemaTypePtr itemType = NULL;
13516
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013517 itemType = type->subtypes;
13518 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013519 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13520 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013521 return (-1);
13522 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013523 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013526 * 2.1 The {item type definition} must have a {variety} of atomic or
13527 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013528 * must be atomic).
13529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013530 if ((! VARIETY_ATOMIC(itemType)) &&
13531 (! VARIETY_UNION(itemType))) {
13532 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013535 "The item type '%s' does not have a variety of atomic or union",
13536 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013537 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013538 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013539 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 xmlSchemaTypeLinkPtr member;
13541
13542 member = itemType->memberTypes;
13543 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 if (! VARIETY_ATOMIC(member->type)) {
13545 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013546 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013547 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013548 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013549 "member type '%s' of this item type is not atomic",
13550 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013552 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13553 }
13554 member = member->next;
13555 }
13556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557
13558 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013559 xmlSchemaFacetPtr facet;
13560 /*
13561 * This is the case if we have: <simpleType><list ..
13562 */
13563 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564 * 2.3.1
13565 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013566 * contain list.
13567 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013568 if (xmlSchemaTypeFinalContains(itemType,
13569 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13570 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013571 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013572 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013573 "The final of its item type '%s' must not contain 'list'",
13574 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013575 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013576 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13577 }
13578 /*
13579 * 2.3.1.2 The {facets} must only contain the whiteSpace
13580 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013581 * OPTIMIZE TODO: the S4S already disallows any facet
13582 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 */
13584 if (type->facets != NULL) {
13585 facet = type->facets;
13586 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013587 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013588 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013589 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013590 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13592 }
13593 facet = facet->next;
13594 } while (facet != NULL);
13595 }
13596 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013597 * MAYBE TODO: (Hmm, not really) Datatypes states:
13598 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13599 * whose ·lexical space· allows space (such as string or anyURI)or
13600 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 * ·lexical space· allows space.
13602 */
13603 } else {
13604 /*
13605 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013606 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013607 */
13608 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013609 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013610 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13611 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612 if (! VARIETY_LIST(type->baseType)) {
13613 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013614 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013615 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013616 "The base type '%s' must be a list type",
13617 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013618 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013619 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13620 }
13621 /*
13622 * 2.3.2.2 The {final} of the {base type definition} must not
13623 * contain restriction.
13624 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013626 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013627 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013628 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013630 "The 'final' of the base type '%s' must not contain 'restriction'",
13631 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013632 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013633 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13634 }
13635 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013636 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013637 * from the {base type definition}'s {item type definition} given
13638 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13639 */
13640 {
13641 xmlSchemaTypePtr baseItemType;
13642
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013643 baseItemType = type->baseType->subtypes;
13644 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13646 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013647 return (-1);
13648 }
13649 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013650 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13651 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013652 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013653 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013654 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013655 NULL, type, NULL,
13656 "The item type '%s' is not validly derived from "
13657 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013658 xmlSchemaGetComponentQName(&str, itemType),
13659 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13660 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013661
13662 FREE_AND_NULL(str)
13663 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013664 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13666 }
13667 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013668
Daniel Veillard01fa6152004-06-29 17:04:39 +000013669 if (type->facets != NULL) {
13670 xmlSchemaFacetPtr facet;
13671 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013672 /*
13673 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013674 * and enumeration facet components are allowed among the {facets}.
13675 */
13676 facet = type->facets;
13677 do {
13678 switch (facet->type) {
13679 case XML_SCHEMA_FACET_LENGTH:
13680 case XML_SCHEMA_FACET_MINLENGTH:
13681 case XML_SCHEMA_FACET_MAXLENGTH:
13682 case XML_SCHEMA_FACET_WHITESPACE:
13683 /*
13684 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013685 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013686 */
13687 case XML_SCHEMA_FACET_PATTERN:
13688 case XML_SCHEMA_FACET_ENUMERATION:
13689 break;
13690 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013691 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013692 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013693 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013695 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013696 * invalid facets.
13697 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013699 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013701 facet = facet->next;
13702 } while (facet != NULL);
13703 if (ok == 0)
13704 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13705 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013706 * SPEC (2.3.2.5) (same as 1.3.2)
13707 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013709 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013710 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013713 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013714 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 * atomic or list.
13717 */
13718 xmlSchemaTypeLinkPtr member;
13719
13720 member = type->memberTypes;
13721 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013722 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013723 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013725 if ((! VARIETY_ATOMIC(member->type)) &&
13726 (! VARIETY_LIST(member->type))) {
13727 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013728 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013729 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013730 "The member type '%s' is neither an atomic, nor a list type",
13731 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013732 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013733 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13734 }
13735 member = member->next;
13736 }
13737 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 * 3.3.1 If the {base type definition} is the ·simple ur-type
13739 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013740 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013741 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013742 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013743 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013744 * {final} which does not contain union.
13745 */
13746 member = type->memberTypes;
13747 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013751 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013752 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013753 "The 'final' of member type '%s' contains 'union'",
13754 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013755 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013756 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13757 }
13758 member = member->next;
13759 }
13760 /*
13761 * 3.3.1.2 The {facets} must be empty.
13762 */
13763 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013764 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013765 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013767 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13769 }
13770 } else {
13771 /*
13772 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013773 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013774 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013775 if (! VARIETY_UNION(type->baseType)) {
13776 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013777 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013778 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013779 "The base type '%s' is not a union type",
13780 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013781 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013782 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13783 }
13784 /*
13785 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13786 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013787 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013789 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013790 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013791 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013792 "The 'final' of its base type '%s' must not contain 'restriction'",
13793 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013794 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13796 }
13797 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013798 * 3.3.2.3 The {member type definitions}, in order, must be validly
13799 * derived from the corresponding type definitions in the {base
13800 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 * as defined in Type Derivation OK (Simple) (§3.14.6).
13802 */
13803 {
13804 xmlSchemaTypeLinkPtr baseMember;
13805
13806 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 * OPTIMIZE: if the type is restricting, it has no local defined
13808 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013809 * thus a check for equality can be skipped.
13810 */
13811 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013812 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013813 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013814 * types of it's base type. This check seems not necessary with
13815 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013816 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013817 */
13818 if (type->memberTypes != NULL) {
13819 member = type->memberTypes;
13820 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013821 if ((member == NULL) && (baseMember != NULL)) {
13822 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13823 "different number of member types in base");
13824 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013825 while (member != NULL) {
13826 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013827 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13828 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013829 }
13830 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013831 (xmlSchemaCheckCOSSTDerivedOK(
13832 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013833 xmlChar *strBMT = NULL, *strBT = NULL;
13834
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013835 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013836 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13837 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 "The member type %s is not validly "
13839 "derived from its corresponding member "
13840 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013841 xmlSchemaGetComponentQName(&str, member->type),
13842 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13843 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013844 FREE_AND_NULL(str)
13845 FREE_AND_NULL(strBMT)
13846 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013847 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013849 member = member->next;
13850 baseMember = baseMember->next;
13851 }
13852 }
13853 }
13854 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013855 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013856 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013857 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858 if (type->facets != NULL) {
13859 xmlSchemaFacetPtr facet;
13860 int ok = 1;
13861
13862 facet = type->facets;
13863 do {
13864 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13865 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013866 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013867 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013868 NULL, type, facet);
13869 ok = 0;
13870 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 facet = facet->next;
13872 } while (facet != NULL);
13873 if (ok == 0)
13874 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013875
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 }
13877 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013878 * SPEC (3.3.2.5) (same as 1.3.2)
13879 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013880 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013881 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013882 */
13883 }
13884 }
13885
13886 return (0);
13887}
13888
13889/**
13890 * xmlSchemaCheckSRCSimpleType:
13891 * @ctxt: the schema parser context
13892 * @type: the simple type definition
13893 *
13894 * Checks crc-simple-type constraints.
13895 *
13896 * Returns 0 if the constraints are satisfied,
13897 * if not a positive error code and -1 on internal
13898 * errors.
13899 */
13900static int
13901xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13902 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013903{
13904 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013905 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013906 * must satisfy the conditions set out in Constraints on Simple Type
13907 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013908 */
13909 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13910 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13911 /*
13912 * TODO: Removed this, since it got annoying to get an
13913 * extra error report, if anything failed until now.
13914 * Enable this if needed.
13915 */
13916 /*
13917 xmlSchemaPErr(ctxt, type->node,
13918 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013919 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013920 "on simple type definitions.\n",
13921 type->name, NULL);
13922 */
13923 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13924 }
13925
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013926 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013927 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013928 * src-simple-type.2 If the <restriction> alternative is chosen,
13929 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013930 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013931 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013932 /*
13933 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013934 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013935 */
13936 } else if (VARIETY_LIST(type)) {
13937 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13938 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013939 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013940 *
13941 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013942 */
13943 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013944 xmlSchemaTypeLinkPtr member;
13945 xmlSchemaTypePtr ancestor, anySimpleType;
13946
13947 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13948
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013949 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13950 * the <union> alternative is chosen, there must not be any entries
13951 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013952 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013953 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013954 member = type->memberTypes;
13955 while (member != NULL) {
13956 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013957 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013958 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013959 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013960 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013961 NULL, type, NULL,
13962 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013963 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013964 }
13965 if (IS_NOT_TYPEFIXED(ancestor))
13966 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013967 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013968 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013969 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013970 * type as item type, which in turn has a list ST as member
13971 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013972 * was not yet performed.
13973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013974 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013975
Daniel Veillard01fa6152004-06-29 17:04:39 +000013976 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013977 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013978 member = member->next;
13979 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013980 }
13981
13982 return (0);
13983}
13984
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013985static int
13986xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13987{
13988 if (ctxt->vctxt == NULL) {
13989 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13990 if (ctxt->vctxt == NULL) {
13991 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013992 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013993 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013994 "failed to create a temp. validation context.\n",
13995 NULL, NULL);
13996 return (-1);
13997 }
13998 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013999 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014000 }
14001 return (0);
14002}
14003
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014004static int
14005xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14006 xmlNodePtr node,
14007 xmlSchemaTypePtr type,
14008 const xmlChar *value,
14009 xmlSchemaValPtr *retVal,
14010 int fireErrors,
14011 int normalize,
14012 int isNormalized);
14013
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014014/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014015 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014016 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014017 * @type: the simple type definition
14018 * @value: the default value
14019 * @node: an optional node (the holder of the value)
14020 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014021 * Schema Component Constraint: Element Default Valid (Immediate)
14022 * (cos-valid-default)
14023 * This will be used by the parser only. For the validator there's
14024 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014025 *
14026 * Returns 0 if the constraints are satisfied,
14027 * if not, a positive error code and -1 on internal
14028 * errors.
14029 */
14030static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014031xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14032 xmlNodePtr node,
14033 xmlSchemaTypePtr type,
14034 const xmlChar *value,
14035 xmlSchemaValPtr *val)
14036{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014037 int ret = 0;
14038
14039 /*
14040 * cos-valid-default:
14041 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014042 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014043 * definition the appropriate case among the following must be true:
14044 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014045 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014046 /*
14047 * Complex type.
14048 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014049 * SPEC (2.1) "its {content type} must be a simple type definition
14050 * or mixed."
14051 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014052 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014053 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014054 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014055 if ((! HAS_SIMPLE_CONTENT(type)) &&
14056 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14057 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014058 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014059 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014060 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014061 "For a string to be a valid default, the type definition "
14062 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014063 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014064 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14065 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014066 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014067 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014068 * 1 If the type definition is a simple type definition, then the string
14069 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014070 * Valid (§3.14.4).
14071 *
14072 * AND
14073 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014074 * 2.2.1 If the {content type} is a simple type definition, then the
14075 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014076 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014077 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014078 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014079 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14080 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014081 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014082 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14083 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014084 else
14085 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014086
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014087 if (ret < 0) {
14088 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14089 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014091
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014092 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014093}
14094
14095/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014096 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014097 * @ctxt: the schema parser context
14098 * @type: the complex type definition
14099 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014100 *.(4.6) Constraints on Complex Type Definition Schema Components
14101 * Schema Component Constraint:
14102 * Complex Type Definition Properties Correct (ct-props-correct)
14103 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014104 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014105 * Returns 0 if the constraints are satisfied, a positive
14106 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014107 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014108static int
14109xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14110 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014111{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014112 /*
14113 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14114 *
14115 * SPEC (1) "The values of the properties of a complex type definition must
14116 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014117 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014118 * Sub-components (§5.3)."
14119 */
14120 if ((type->baseType != NULL) &&
14121 (IS_SIMPLE_TYPE(type->baseType)) &&
14122 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14123 /*
14124 * SPEC (2) "If the {base type definition} is a simple type definition,
14125 * the {derivation method} must be extension."
14126 */
14127 xmlSchemaPCustomErr(pctxt,
14128 XML_SCHEMAP_SRC_CT_1,
14129 NULL, type, NULL,
14130 "If the base type is a simple type, the derivation method must be "
14131 "'extension'", NULL);
14132 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014133 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014134 /*
14135 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14136 * definition·. That is, it must be possible to reach the ·ur-type
14137 * definition by repeatedly following the {base type definition}."
14138 *
14139 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14140 *
14141 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014142 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014143 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14144 * must not have {type definition}s which are or are derived from ID."
14145 *
14146 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14147 */
14148 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014149}
14150
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014151static int
14152xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14153 xmlSchemaTypePtr typeB)
14154{
14155 /*
14156 * TODO: This should implement component-identity
14157 * in the future.
14158 */
14159 if ((typeA == NULL) || (typeB == NULL))
14160 return (0);
14161 return (typeA == typeB);
14162}
14163
14164/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014165 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014166 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014167 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014168 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014169 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014170 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014171 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014172 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14173 *
14174 * STATUS: completed
14175 *
14176 * Returns 0 if the constraints are satisfied, or 1
14177 * if not.
14178 */
14179static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014180xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014181 xmlSchemaTypePtr baseType,
14182 int set)
14183{
14184 int equal = xmlSchemaAreEqualTypes(type, baseType);
14185 /* TODO: Error codes. */
14186 /*
14187 * SPEC "For a complex type definition (call it D, for derived)
14188 * to be validly derived from a type definition (call this
14189 * B, for base) given a subset of {extension, restriction}
14190 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014191 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014192 if (! equal) {
14193 /*
14194 * SPEC (1) "If B and D are not the same type definition, then the
14195 * {derivation method} of D must not be in the subset."
14196 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014197 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014198 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014199 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014200 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014201 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014202 } else {
14203 /*
14204 * SPEC (2.1) "B and D must be the same type definition."
14205 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014206 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014207 }
14208 /*
14209 * SPEC (2.2) "B must be D's {base type definition}."
14210 */
14211 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014212 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014213 /*
14214 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14215 * definition·."
14216 */
14217 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014218 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014219
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014220 if (IS_COMPLEX_TYPE(type->baseType)) {
14221 /*
14222 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14223 * must be validly derived from B given the subset as defined by this
14224 * constraint."
14225 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014226 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014227 baseType, set));
14228 } else {
14229 /*
14230 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14231 * must be validly derived from B given the subset as defined in Type
14232 * Derivation OK (Simple) (§3.14.6).
14233 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014234 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14235 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014236}
14237
14238/**
14239 * xmlSchemaCheckCOSDerivedOK:
14240 * @type: the derived simple type definition
14241 * @baseType: the base type definition
14242 *
14243 * Calls:
14244 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014245 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014246 * Checks wheter @type can be validly derived from @baseType.
14247 *
14248 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014249 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014250static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014251xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014252 xmlSchemaTypePtr baseType,
14253 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014254{
14255 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014256 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014257 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014258 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014259}
14260
William M. Brack2f2a6632004-08-20 23:09:47 +000014261/**
14262 * xmlSchemaCheckCOSCTExtends:
14263 * @ctxt: the schema parser context
14264 * @type: the complex type definition
14265 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014266 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014267 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014268 * Derivation Valid (Extension) (cos-ct-extends)
14269 *
14270 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014271 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014272 * (1.5)
14273 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014274 *
14275 * Returns 0 if the constraints are satisfied, a positive
14276 * error code if not and -1 if an internal error occured.
14277 */
14278static int
14279xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14280 xmlSchemaTypePtr type)
14281{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014282 xmlSchemaTypePtr base = type->baseType;
14283 /*
14284 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14285 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014286 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014287 /*
14288 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014289 * then all of the following must be true:"
14290 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014291 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14292 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014293 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014294 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014295 */
14296 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14297 xmlSchemaPCustomErr(ctxt,
14298 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14299 NULL, type, NULL,
14300 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014301 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014302 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14303 }
14304 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014305 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014306 * uses}
14307 * of the complex type definition itself, that is, for every attribute
14308 * use in the {attribute uses} of the {base type definition}, there
14309 * must be an attribute use in the {attribute uses} of the complex
14310 * type definition itself whose {attribute declaration} has the same
14311 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014312 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014313 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014314 * NOTE (1.2): This will be already satisfied by the way the attribute
14315 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14316 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014317 */
14318
14319 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014320 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14321 * definition must also have one, and the base type definition's
14322 * {attribute wildcard}'s {namespace constraint} must be a subset
14323 * of the complex type definition's {attribute wildcard}'s {namespace
14324 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014325 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014326 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014327 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014328 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014329 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014330 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014331 if ((type->contentTypeDef != NULL) &&
14332 (type->contentTypeDef == base->contentTypeDef)) {
14333 /*
14334 * SPEC (1.4.1) "The {content type} of the {base type definition}
14335 * and the {content type} of the complex type definition itself
14336 * must be the same simple type definition"
14337 * PASS
14338 */
14339 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14340 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14341 /*
14342 * SPEC (1.4.2) "The {content type} of both the {base type
14343 * definition} and the complex type definition itself must
14344 * be empty."
14345 * PASS
14346 */
14347 } else {
14348 /*
14349 * SPEC (1.4.3) "All of the following must be true:"
14350 */
14351 if (type->subtypes == NULL) {
14352 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014353 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014354 * definition itself must specify a particle.
14355 */
14356 xmlSchemaPCustomErr(ctxt,
14357 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14358 NULL, type, NULL,
14359 "The content type must specify a particle", NULL);
14360 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14361 }
14362 /*
14363 * SPEC (1.4.3.2) "One of the following must be true:"
14364 */
14365 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14366 /*
14367 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14368 * definition} must be empty.
14369 * PASS
14370 */
14371 } else {
14372 /*
14373 * SPEC (1.4.3.2.2) "All of the following must be true:"
14374 */
14375 if ((type->contentType != base->contentType) ||
14376 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14377 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14378 /*
14379 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14380 * or both must be element-only."
14381 */
14382 xmlSchemaPCustomErr(ctxt,
14383 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14384 NULL, type, NULL,
14385 "The content type of both, the type and its base "
14386 "type, must either 'mixed' or 'element-only'", NULL);
14387 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014388 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014389 /*
14390 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14391 * complex type definition must be a ·valid extension·
14392 * of the {base type definition}'s particle, as defined
14393 * in Particle Valid (Extension) (§3.9.6)."
14394 *
14395 * NOTE that we won't check "Particle Valid (Extension)",
14396 * since it is ensured by the derivation process in
14397 * xmlSchemaTypeFixup(). We need to implement this when heading
14398 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014399 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014400 }
14401 /*
14402 * TODO (1.5)
14403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014404 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014405 } else {
14406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014407 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014408 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014409 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014410 if (type->contentTypeDef != base) {
14411 /*
14412 * SPEC (2.1) "The {content type} must be the same simple type
14413 * definition."
14414 */
14415 xmlSchemaPCustomErr(ctxt,
14416 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14417 NULL, type, NULL,
14418 "The content type must be the simple base type", NULL);
14419 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14420 }
14421 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14422 /*
14423 * SPEC (2.2) "The {final} of the {base type definition} must not
14424 * contain extension"
14425 * NOTE that this is the same as (1.1).
14426 */
14427 xmlSchemaPCustomErr(ctxt,
14428 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14429 NULL, type, NULL,
14430 "The 'final' of the base type definition "
14431 "contains 'extension'", NULL);
14432 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014433 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014434 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014435 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014436}
14437
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014438/**
14439 * xmlSchemaCheckDerivationOKRestriction:
14440 * @ctxt: the schema parser context
14441 * @type: the complex type definition
14442 *
14443 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014444 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014445 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14446 *
14447 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014448 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014449 * (5.4.2), (5.2.2.1)
14450 *
14451 * Returns 0 if the constraints are satisfied, a positive
14452 * error code if not and -1 if an internal error occured.
14453 */
14454static int
14455xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14456 xmlSchemaTypePtr type)
14457{
14458 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014459
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014460 /*
14461 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14462 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014463 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014464 base = type->baseType;
14465 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14466 /*
14467 * SPEC (1) "The {base type definition} must be a complex type
14468 * definition whose {final} does not contain restriction."
14469 */
14470 xmlSchemaPCustomErr(ctxt,
14471 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14472 NULL, type, NULL,
14473 "The 'final' of the base type definition "
14474 "contains 'restriction'", NULL);
14475 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14476 }
14477 /*
14478 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14479 *
14480 * SPEC (5) "One of the following must be true:"
14481 */
14482 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14483 /*
14484 * SPEC (5.1) "The {base type definition} must be the
14485 * ·ur-type definition·."
14486 * PASS
14487 */
14488 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14489 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14490 /*
14491 * SPEC (5.2.1) "The {content type} of the complex type definition
14492 * must be a simple type definition"
14493 *
14494 * SPEC (5.2.2) "One of the following must be true:"
14495 */
14496 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14497 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14498 /*
14499 * SPEC (5.2.2.1) "The {content type} of the {base type
14500 * definition} must be a simple type definition from which
14501 * the {content type} is validly derived given the empty
14502 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14503 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014504 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014505 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14506 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014507 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014508 /*
14509 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14510 * and have a particle which is ·emptiable· as defined in
14511 * Particle Emptiable (§3.9.6)."
14512 * PASS
14513 */
14514 } else {
14515 xmlSchemaPCustomErr(ctxt,
14516 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14517 NULL, type, NULL,
14518 "The content type of the base type must be either "
14519 "a simple type or 'mixed' and an emptiable particle", NULL);
14520 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14521 }
14522 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14523 /*
14524 * SPEC (5.3.1) "The {content type} of the complex type itself must
14525 * be empty"
14526 */
14527 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14528 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014529 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014530 * definition} must also be empty."
14531 * PASS
14532 */
14533 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14534 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14535 xmlSchemaIsParticleEmptiable(
14536 (xmlSchemaParticlePtr) base->subtypes)) {
14537 /*
14538 * SPEC (5.3.2.2) "The {content type} of the {base type
14539 * definition} must be elementOnly or mixed and have a particle
14540 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14541 * PASS
14542 */
14543 } else {
14544 xmlSchemaPCustomErr(ctxt,
14545 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14546 NULL, type, NULL,
14547 "The content type of the base type must be either "
14548 "empty or 'mixed' (or 'elements-only') and an emptiable "
14549 "particle", NULL);
14550 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14551 }
14552 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014553 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014554 /*
14555 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14556 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014557 */
14558 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14559 /*
14560 * SPEC (5.4.1.2) "The {content type} of the complex type
14561 * definition itself and of the {base type definition} must be
14562 * mixed"
14563 */
14564 xmlSchemaPCustomErr(ctxt,
14565 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14566 NULL, type, NULL,
14567 "If the content type is 'mixed', then the content type of the "
14568 "base type must also be 'mixed'", NULL);
14569 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14570 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014571 /*
14572 * SPEC (5.4.2) "The particle of the complex type definition itself
14573 * must be a ·valid restriction· of the particle of the {content
14574 * type} of the {base type definition} as defined in Particle Valid
14575 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014576 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014577 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014578 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014579 } else {
14580 xmlSchemaPCustomErr(ctxt,
14581 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14582 NULL, type, NULL,
14583 "The type is not a valid restriction of its base type", NULL);
14584 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14585 }
14586 return (0);
14587}
14588
14589/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014590 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014591 * @ctxt: the schema parser context
14592 * @type: the complex type definition
14593 *
14594 * (3.4.6) Constraints on Complex Type Definition Schema Components
14595 *
14596 * Returns 0 if the constraints are satisfied, a positive
14597 * error code if not and -1 if an internal error occured.
14598 */
14599static int
14600xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14601 xmlSchemaTypePtr type)
14602{
14603 int ret;
14604 /*
14605 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014606 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014607 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14608 if (ret != 0)
14609 return (ret);
14610 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14611 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14612 else
14613 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14614 return (ret);
14615}
14616
14617/**
14618 * xmlSchemaCheckSRCCT:
14619 * @ctxt: the schema parser context
14620 * @type: the complex type definition
14621 *
14622 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014623 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014624 * Complex Type Definition Representation OK (src-ct)
14625 *
14626 * Returns 0 if the constraints are satisfied, a positive
14627 * error code if not and -1 if an internal error occured.
14628 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014629static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014630xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014631 xmlSchemaTypePtr type)
14632{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014633 xmlSchemaTypePtr base;
14634 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014635
14636 /*
14637 * TODO: Adjust the error codes here, as I used
14638 * XML_SCHEMAP_SRC_CT_1 only yet.
14639 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014640 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014641 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014642 /*
14643 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014644 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014645 * must be a complex type definition;
14646 */
14647 if (! IS_COMPLEX_TYPE(base)) {
14648 xmlChar *str = NULL;
14649 xmlSchemaPCustomErr(ctxt,
14650 XML_SCHEMAP_SRC_CT_1,
14651 NULL, type, type->node,
14652 "If using <complexContent>, the base type is expected to be "
14653 "a complex type. The base type '%s' is a simple type",
14654 xmlSchemaFormatQName(&str, base->targetNamespace,
14655 base->name));
14656 FREE_AND_NULL(str)
14657 return (XML_SCHEMAP_SRC_CT_1);
14658 }
14659 } else {
14660 /*
14661 * SPEC
14662 * 2 If the <simpleContent> alternative is chosen, all of the
14663 * following must be true:
14664 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14665 * base [attribute] must be one of the following:
14666 */
14667 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014669 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14670 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014671 /*
14672 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014673 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014674 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014675 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014676 xmlSchemaPCustomErr(ctxt,
14677 XML_SCHEMAP_SRC_CT_1,
14678 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014679 "If using <simpleContent> and <restriction>, the base "
14680 "type must be a complex type. The base type '%s' is "
14681 "a simple type",
14682 xmlSchemaFormatQName(&str, base->targetNamespace,
14683 base->name));
14684 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014685 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014686 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014687 } else {
14688 /* Base type is a complex type. */
14689 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14690 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14691 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014692 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014693 * simple type definition;
14694 * PASS
14695 */
14696 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014697 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014698 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014699 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014700 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014701 type->name);
14702 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014703 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014704 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14705 (type->flags &
14706 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014707
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014708 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014709 * 2.1.2 only if the <restriction> alternative is also
14710 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014711 * is mixed and a particle emptiable.
14712 */
14713 if (! xmlSchemaIsParticleEmptiable(
14714 (xmlSchemaParticlePtr) base->subtypes)) {
14715 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014716 } else
14717 /*
14718 * Attention: at this point the <simpleType> child is in
14719 * ->contentTypeDef (put there during parsing).
14720 */
14721 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014722 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014723 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014724 * 2.2 If clause 2.1.2 above is satisfied, then there
14725 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014726 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014728 /* TODO: Change error code to ..._SRC_CT_2_2. */
14729 xmlSchemaPCustomErr(ctxt,
14730 XML_SCHEMAP_SRC_CT_1,
14731 NULL, type, NULL,
14732 "A <simpleType> is expected among the children "
14733 "of <restriction>, if <simpleContent> is used and "
14734 "the base type '%s' is a complex type",
14735 xmlSchemaFormatQName(&str, base->targetNamespace,
14736 base->name));
14737 FREE_AND_NULL(str)
14738 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014739 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014740 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014741 ret = XML_SCHEMAP_SRC_CT_1;
14742 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014743 }
14744 if (ret > 0) {
14745 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 xmlSchemaPCustomErr(ctxt,
14748 XML_SCHEMAP_SRC_CT_1,
14749 NULL, type, NULL,
14750 "If <simpleContent> and <restriction> is used, the "
14751 "base type must be a simple type or a complex type with "
14752 "mixed content and particle emptiable. The base type "
14753 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014754 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014755 base->name));
14756 } else {
14757 xmlSchemaPCustomErr(ctxt,
14758 XML_SCHEMAP_SRC_CT_1,
14759 NULL, type, NULL,
14760 "If <simpleContent> and <extension> is used, the "
14761 "base type must be a simple type. The base type '%s' "
14762 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014763 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014764 base->name));
14765 }
14766 FREE_AND_NULL(str)
14767 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014768 }
14769 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770 * SPEC (3) "The corresponding complex type definition component must
14771 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014772 * Definition Schema Components (§3.4.6);"
14773 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014774 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 /*
14776 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014777 * above for {attribute wildcard} is satisfied, the intensional
14778 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014779 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014780 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014781 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014782 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014783}
William M. Brack2f2a6632004-08-20 23:09:47 +000014784
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014785#ifdef ENABLE_PARTICLE_RESTRICTION
14786/**
14787 * xmlSchemaCheckParticleRangeOK:
14788 * @ctxt: the schema parser context
14789 * @type: the complex type definition
14790 *
14791 * (3.9.6) Constraints on Particle Schema Components
14792 * Schema Component Constraint:
14793 * Occurrence Range OK (range-ok)
14794 *
14795 * STATUS: complete
14796 *
14797 * Returns 0 if the constraints are satisfied, a positive
14798 * error code if not and -1 if an internal error occured.
14799 */
14800static int
14801xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14802 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014803{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014804 if (rmin < bmin)
14805 return (1);
14806 if ((bmax != UNBOUNDED) &&
14807 (rmax > bmax))
14808 return (1);
14809 return (0);
14810}
14811
14812/**
14813 * xmlSchemaCheckRCaseNameAndTypeOK:
14814 * @ctxt: the schema parser context
14815 * @r: the restricting element declaration particle
14816 * @b: the base element declaration particle
14817 *
14818 * (3.9.6) Constraints on Particle Schema Components
14819 * Schema Component Constraint:
14820 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14821 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014822 *
14823 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014824 * MISSING (3.2.3)
14825 * CLARIFY: (3.2.2)
14826 *
14827 * Returns 0 if the constraints are satisfied, a positive
14828 * error code if not and -1 if an internal error occured.
14829 */
14830static int
14831xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14832 xmlSchemaParticlePtr r,
14833 xmlSchemaParticlePtr b)
14834{
14835 xmlSchemaElementPtr elemR, elemB;
14836
14837 /* TODO: Error codes (rcase-NameAndTypeOK). */
14838 elemR = (xmlSchemaElementPtr) r->children;
14839 elemB = (xmlSchemaElementPtr) b->children;
14840 /*
14841 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14842 * the same."
14843 */
14844 if ((elemR != elemB) &&
14845 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14846 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14847 return (1);
14848 /*
14849 * SPEC (2) "R's occurrence range is a valid restriction of B's
14850 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14851 */
14852 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14853 b->minOccurs, b->maxOccurs) != 0)
14854 return (1);
14855 /*
14856 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14857 * {scope} are global."
14858 */
14859 if (elemR == elemB)
14860 return (0);
14861 /*
14862 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14863 */
14864 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14865 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14866 return (1);
14867 /*
14868 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14869 * or is not fixed, or R's declaration's {value constraint} is fixed
14870 * with the same value."
14871 */
14872 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14873 ((elemR->value == NULL) ||
14874 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14875 /* TODO: Equality of the initial value or normalized or canonical? */
14876 (! xmlStrEqual(elemR->value, elemB->value))))
14877 return (1);
14878 /*
14879 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14880 * definitions} is a subset of B's declaration's {identity-constraint
14881 * definitions}, if any."
14882 */
14883 if (elemB->idcs != NULL) {
14884 /* TODO */
14885 }
14886 /*
14887 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14888 * superset of B's declaration's {disallowed substitutions}."
14889 */
14890 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14891 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14892 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14893 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14894 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14895 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14896 return (1);
14897 /*
14898 * SPEC (3.2.5) "R's {type definition} is validly derived given
14899 * {extension, list, union} from B's {type definition}"
14900 *
14901 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14902 * set, if the corresponding constraints handle "restriction" and
14903 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014904 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014905 */
14906 {
14907 int set = 0;
14908
14909 set |= SUBSET_EXTENSION;
14910 set |= SUBSET_LIST;
14911 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014912 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014913 elemB->subtypes, set) != 0)
14914 return (1);
14915 }
14916 return (0);
14917}
14918
14919/**
14920 * xmlSchemaCheckRCaseNSCompat:
14921 * @ctxt: the schema parser context
14922 * @r: the restricting element declaration particle
14923 * @b: the base wildcard particle
14924 *
14925 * (3.9.6) Constraints on Particle Schema Components
14926 * Schema Component Constraint:
14927 * Particle Derivation OK (Elt:Any -- NSCompat)
14928 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014929 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014930 * STATUS: complete
14931 *
14932 * Returns 0 if the constraints are satisfied, a positive
14933 * error code if not and -1 if an internal error occured.
14934 */
14935static int
14936xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14937 xmlSchemaParticlePtr r,
14938 xmlSchemaParticlePtr b)
14939{
14940 /* TODO:Error codes (rcase-NSCompat). */
14941 /*
14942 * SPEC "For an element declaration particle to be a ·valid restriction·
14943 * of a wildcard particle all of the following must be true:"
14944 *
14945 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14946 * with respect to the wildcard's {namespace constraint} as defined by
14947 * Wildcard allows Namespace Name (§3.10.4)."
14948 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014949 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014950 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14951 return (1);
14952 /*
14953 * SPEC (2) "R's occurrence range is a valid restriction of B's
14954 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14955 */
14956 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14957 b->minOccurs, b->maxOccurs) != 0)
14958 return (1);
14959
14960 return (0);
14961}
14962
14963/**
14964 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14965 * @ctxt: the schema parser context
14966 * @r: the restricting element declaration particle
14967 * @b: the base model group particle
14968 *
14969 * (3.9.6) Constraints on Particle Schema Components
14970 * Schema Component Constraint:
14971 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14972 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014973 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014974 * STATUS: TODO
14975 *
14976 * Returns 0 if the constraints are satisfied, a positive
14977 * error code if not and -1 if an internal error occured.
14978 */
14979static int
14980xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
14981 xmlSchemaParticlePtr r,
14982 xmlSchemaParticlePtr b)
14983{
14984 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
14985 TODO
14986 return (0);
14987}
14988
14989/**
14990 * xmlSchemaCheckRCaseNSSubset:
14991 * @ctxt: the schema parser context
14992 * @r: the restricting wildcard particle
14993 * @b: the base wildcard particle
14994 *
14995 * (3.9.6) Constraints on Particle Schema Components
14996 * Schema Component Constraint:
14997 * Particle Derivation OK (Any:Any -- NSSubset)
14998 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014999 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015000 * STATUS: complete
15001 *
15002 * Returns 0 if the constraints are satisfied, a positive
15003 * error code if not and -1 if an internal error occured.
15004 */
15005static int
15006xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15007 xmlSchemaParticlePtr r,
15008 xmlSchemaParticlePtr b,
15009 int isAnyTypeBase)
15010{
15011 /* TODO: Error codes (rcase-NSSubset). */
15012 /*
15013 * SPEC (1) "R's occurrence range is a valid restriction of B's
15014 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15015 */
15016 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15017 b->minOccurs, b->maxOccurs))
15018 return (1);
15019 /*
15020 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15021 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15022 */
15023 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15024 (xmlSchemaWildcardPtr) b->children))
15025 return (1);
15026 /*
15027 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15028 * definition·, R's {process contents} must be identical to or stronger
15029 * than B's {process contents}, where strict is stronger than lax is
15030 * stronger than skip."
15031 */
15032 if (! isAnyTypeBase) {
15033 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15034 ((xmlSchemaWildcardPtr) b->children)->processContents)
15035 return (1);
15036 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015037
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015038 return (0);
15039}
15040
15041/**
15042 * xmlSchemaCheckCOSParticleRestrict:
15043 * @ctxt: the schema parser context
15044 * @type: the complex type definition
15045 *
15046 * (3.9.6) Constraints on Particle Schema Components
15047 * Schema Component Constraint:
15048 * Particle Valid (Restriction) (cos-particle-restrict)
15049 *
15050 * STATUS: TODO
15051 *
15052 * Returns 0 if the constraints are satisfied, a positive
15053 * error code if not and -1 if an internal error occured.
15054 */
15055static int
15056xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15057 xmlSchemaParticlePtr r,
15058 xmlSchemaParticlePtr b)
15059{
15060 int ret = 0;
15061
15062 /*part = GET_PARTICLE(type);
15063 basePart = GET_PARTICLE(base);
15064 */
15065
15066 TODO
15067
15068 /*
15069 * SPEC (1) "They are the same particle."
15070 */
15071 if (r == b)
15072 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015073
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015074
15075 return (0);
15076}
15077
15078/**
15079 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15080 * @ctxt: the schema parser context
15081 * @r: the model group particle
15082 * @b: the base wildcard particle
15083 *
15084 * (3.9.6) Constraints on Particle Schema Components
15085 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015086 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015087 * NSRecurseCheckCardinality)
15088 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015089 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015090 * STATUS: TODO: subst-groups
15091 *
15092 * Returns 0 if the constraints are satisfied, a positive
15093 * error code if not and -1 if an internal error occured.
15094 */
15095static int
15096xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15097 xmlSchemaParticlePtr r,
15098 xmlSchemaParticlePtr b)
15099{
15100 xmlSchemaParticlePtr part;
15101 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15102 if ((r->children == NULL) || (r->children->children == NULL))
15103 return (-1);
15104 /*
15105 * SPEC "For a group particle to be a ·valid restriction· of a
15106 * wildcard particle..."
15107 *
15108 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015109 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015110 * Particle Valid (Restriction) (§3.9.6)."
15111 */
15112 part = (xmlSchemaParticlePtr) r->children->children;
15113 do {
15114 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15115 return (1);
15116 part = (xmlSchemaParticlePtr) part->next;
15117 } while (part != NULL);
15118 /*
15119 * SPEC (2) "The effective total range of the group [...] is a
15120 * valid restriction of B's occurrence range as defined by
15121 * Occurrence Range OK (§3.9.6)."
15122 */
15123 if (xmlSchemaCheckParticleRangeOK(
15124 xmlSchemaGetParticleTotalRangeMin(r),
15125 xmlSchemaGetParticleTotalRangeMax(r),
15126 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015127 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015128 return (0);
15129}
15130
15131/**
15132 * xmlSchemaCheckRCaseRecurse:
15133 * @ctxt: the schema parser context
15134 * @r: the <all> or <sequence> model group particle
15135 * @b: the base <all> or <sequence> model group particle
15136 *
15137 * (3.9.6) Constraints on Particle Schema Components
15138 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015139 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015140 Recurse)
15141 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015142 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015143 * STATUS: ?
15144 * TODO: subst-groups
15145 *
15146 * Returns 0 if the constraints are satisfied, a positive
15147 * error code if not and -1 if an internal error occured.
15148 */
15149static int
15150xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15151 xmlSchemaParticlePtr r,
15152 xmlSchemaParticlePtr b)
15153{
15154 /* xmlSchemaParticlePtr part; */
15155 /* TODO: Error codes (rcase-Recurse). */
15156 if ((r->children == NULL) || (b->children == NULL) ||
15157 (r->children->type != b->children->type))
15158 return (-1);
15159 /*
15160 * SPEC "For an all or sequence group particle to be a ·valid
15161 * restriction· of another group particle with the same {compositor}..."
15162 *
15163 * SPEC (1) "R's occurrence range is a valid restriction of B's
15164 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15165 */
15166 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15167 b->minOccurs, b->maxOccurs))
15168 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015169
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015170
15171 return (0);
15172}
15173
15174#endif
15175
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015176#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15177 xmlSchemaPCustomErrExt(pctxt, \
15178 XML_SCHEMAP_INVALID_FACET_VALUE, \
15179 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15180 "It is an error for both '%s' and '%s' to be specified on the "\
15181 "same type definition", \
15182 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15183 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15184
15185#define FACET_RESTR_ERR(fac1, msg) \
15186 xmlSchemaPCustomErr(pctxt, \
15187 XML_SCHEMAP_INVALID_FACET_VALUE, \
15188 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015189 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015190
15191#define FACET_RESTR_FIXED_ERR(fac) \
15192 xmlSchemaPCustomErr(pctxt, \
15193 XML_SCHEMAP_INVALID_FACET_VALUE, \
15194 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15195 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015196 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015197
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015198static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015199xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15200 xmlSchemaFacetPtr facet1,
15201 xmlSchemaFacetPtr facet2,
15202 int lessGreater,
15203 int orEqual,
15204 int ofBase)
15205{
15206 xmlChar *msg = NULL;
15207
15208 msg = xmlStrdup(BAD_CAST "'");
15209 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15210 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15211 if (lessGreater == 0)
15212 msg = xmlStrcat(msg, BAD_CAST " equal to");
15213 if (lessGreater == 1)
15214 msg = xmlStrcat(msg, BAD_CAST " greater than");
15215 else
15216 msg = xmlStrcat(msg, BAD_CAST " less than");
15217
15218 if (orEqual)
15219 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15220 msg = xmlStrcat(msg, BAD_CAST " '");
15221 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15222 if (ofBase)
15223 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15224 else
15225 msg = xmlStrcat(msg, BAD_CAST "'");
15226
15227 xmlSchemaPCustomErr(pctxt,
15228 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015229 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015230 (const char *) msg, NULL);
15231
15232 if (msg != NULL)
15233 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015234}
15235
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015236static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015237xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15238 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015239{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015240 xmlSchemaTypePtr base = type->baseType;
15241 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015242 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015243 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15244 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15245 fmininc = NULL, fmaxinc = NULL,
15246 fminexc = NULL, fmaxexc = NULL,
15247 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15248 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15249 bfmininc = NULL, bfmaxinc = NULL,
15250 bfminexc = NULL, bfmaxexc = NULL;
15251 int res, err = 0, fixedErr;
15252 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015253 * 3 The {facets} of R are the union of S and the {facets}
15254 * of B, eliminating duplicates. To eliminate duplicates,
15255 * when a facet of the same kind occurs in both S and the
15256 * {facets} of B, the one in the {facets} of B is not
15257 * included, with the exception of enumeration and pattern
15258 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015259 * are allowed.
15260 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015261
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015262 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15263 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015264
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015265 last = type->facetSet;
15266 if (last != NULL)
15267 while (last->next != NULL)
15268 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015269
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015270 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15271 facet = cur->facet;
15272 switch (facet->type) {
15273 case XML_SCHEMA_FACET_LENGTH:
15274 flength = facet; break;
15275 case XML_SCHEMA_FACET_MINLENGTH:
15276 fminlen = facet; break;
15277 case XML_SCHEMA_FACET_MININCLUSIVE:
15278 fmininc = facet; break;
15279 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15280 fminexc = facet; break;
15281 case XML_SCHEMA_FACET_MAXLENGTH:
15282 fmaxlen = facet; break;
15283 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15284 fmaxinc = facet; break;
15285 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15286 fmaxexc = facet; break;
15287 case XML_SCHEMA_FACET_TOTALDIGITS:
15288 ftotdig = facet; break;
15289 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15290 ffracdig = facet; break;
15291 default:
15292 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015293 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015294 }
15295 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15296 facet = cur->facet;
15297 switch (facet->type) {
15298 case XML_SCHEMA_FACET_LENGTH:
15299 bflength = facet; break;
15300 case XML_SCHEMA_FACET_MINLENGTH:
15301 bfminlen = facet; break;
15302 case XML_SCHEMA_FACET_MININCLUSIVE:
15303 bfmininc = facet; break;
15304 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15305 bfminexc = facet; break;
15306 case XML_SCHEMA_FACET_MAXLENGTH:
15307 bfmaxlen = facet; break;
15308 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15309 bfmaxinc = facet; break;
15310 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15311 bfmaxexc = facet; break;
15312 case XML_SCHEMA_FACET_TOTALDIGITS:
15313 bftotdig = facet; break;
15314 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15315 bffracdig = facet; break;
15316 default:
15317 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015318 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015319 }
15320 err = 0;
15321 /*
15322 * length and minLength or maxLength (2.2) + (3.2)
15323 */
15324 if (flength && (fminlen || fmaxlen)) {
15325 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15326 "either of 'minLength' or 'maxLength' to be specified on "
15327 "the same type definition")
15328 }
15329 /*
15330 * Mutual exclusions in the same derivation step.
15331 */
15332 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015333 /*
15334 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015335 */
15336 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15337 }
15338 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015339 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015340 * SCC "minInclusive and minExclusive"
15341 */
15342 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015343 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015344
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015345 if (flength && bflength) {
15346 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015348 * The values have to be equal.
15349 */
15350 res = xmlSchemaCompareValues(flength->val, bflength->val);
15351 if (res == -2)
15352 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015353 if (res != 0)
15354 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15355 if ((res != 0) && (bflength->fixed)) {
15356 FACET_RESTR_FIXED_ERR(flength)
15357 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015358
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015359 }
15360 if (fminlen && bfminlen) {
15361 /*
15362 * SCC "minLength valid restriction"
15363 * minLength >= BASE minLength
15364 */
15365 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15366 if (res == -2)
15367 goto internal_error;
15368 if (res == -1)
15369 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15370 if ((res != 0) && (bfminlen->fixed)) {
15371 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015372 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015373 }
15374 if (fmaxlen && bfmaxlen) {
15375 /*
15376 * SCC "maxLength valid restriction"
15377 * maxLength <= BASE minLength
15378 */
15379 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15380 if (res == -2)
15381 goto internal_error;
15382 if (res == 1)
15383 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15384 if ((res != 0) && (bfmaxlen->fixed)) {
15385 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015387 }
15388 /*
15389 * SCC "length and minLength or maxLength"
15390 */
15391 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015392 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015393 if (flength) {
15394 if (! fminlen)
15395 flength = bflength;
15396 if (fminlen) {
15397 /* (1.1) length >= minLength */
15398 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15399 if (res == -2)
15400 goto internal_error;
15401 if (res == -1)
15402 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15403 }
15404 if (! fmaxlen)
15405 fmaxlen = bfmaxlen;
15406 if (fmaxlen) {
15407 /* (2.1) length <= maxLength */
15408 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15409 if (res == -2)
15410 goto internal_error;
15411 if (res == 1)
15412 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15413 }
15414 }
15415 if (fmaxinc) {
15416 /*
15417 * "maxInclusive"
15418 */
15419 if (fmininc) {
15420 /* SCC "maxInclusive >= minInclusive" */
15421 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15422 if (res == -2)
15423 goto internal_error;
15424 if (res == -1) {
15425 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15426 }
15427 }
15428 /*
15429 * SCC "maxInclusive valid restriction"
15430 */
15431 if (bfmaxinc) {
15432 /* maxInclusive <= BASE maxInclusive */
15433 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15434 if (res == -2)
15435 goto internal_error;
15436 if (res == 1)
15437 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15438 if ((res != 0) && (bfmaxinc->fixed)) {
15439 FACET_RESTR_FIXED_ERR(fmaxinc)
15440 }
15441 }
15442 if (bfmaxexc) {
15443 /* maxInclusive < BASE maxExclusive */
15444 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15445 if (res == -2)
15446 goto internal_error;
15447 if (res != -1) {
15448 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15449 }
15450 }
15451 if (bfmininc) {
15452 /* maxInclusive >= BASE minInclusive */
15453 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15454 if (res == -2)
15455 goto internal_error;
15456 if (res == -1) {
15457 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15458 }
15459 }
15460 if (bfminexc) {
15461 /* maxInclusive > BASE minExclusive */
15462 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15463 if (res == -2)
15464 goto internal_error;
15465 if (res != 1) {
15466 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15467 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015468 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015469 }
15470 if (fmaxexc) {
15471 /*
15472 * "maxExclusive >= minExclusive"
15473 */
15474 if (fminexc) {
15475 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15476 if (res == -2)
15477 goto internal_error;
15478 if (res == -1) {
15479 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15480 }
15481 }
15482 /*
15483 * "maxExclusive valid restriction"
15484 */
15485 if (bfmaxexc) {
15486 /* maxExclusive <= BASE maxExclusive */
15487 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15488 if (res == -2)
15489 goto internal_error;
15490 if (res == 1) {
15491 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15492 }
15493 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015494 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015495 }
15496 }
15497 if (bfmaxinc) {
15498 /* maxExclusive <= BASE maxInclusive */
15499 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15500 if (res == -2)
15501 goto internal_error;
15502 if (res == 1) {
15503 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15504 }
15505 }
15506 if (bfmininc) {
15507 /* maxExclusive > BASE minInclusive */
15508 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15509 if (res == -2)
15510 goto internal_error;
15511 if (res != 1) {
15512 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15513 }
15514 }
15515 if (bfminexc) {
15516 /* maxExclusive > BASE minExclusive */
15517 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15518 if (res == -2)
15519 goto internal_error;
15520 if (res != 1) {
15521 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15522 }
15523 }
15524 }
15525 if (fminexc) {
15526 /*
15527 * "minExclusive < maxInclusive"
15528 */
15529 if (fmaxinc) {
15530 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15531 if (res == -2)
15532 goto internal_error;
15533 if (res != -1) {
15534 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15535 }
15536 }
15537 /*
15538 * "minExclusive valid restriction"
15539 */
15540 if (bfminexc) {
15541 /* minExclusive >= BASE minExclusive */
15542 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15543 if (res == -2)
15544 goto internal_error;
15545 if (res == -1) {
15546 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15547 }
15548 if ((res != 0) && (bfminexc->fixed)) {
15549 FACET_RESTR_FIXED_ERR(fminexc)
15550 }
15551 }
15552 if (bfmaxinc) {
15553 /* minExclusive <= BASE maxInclusive */
15554 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15555 if (res == -2)
15556 goto internal_error;
15557 if (res == 1) {
15558 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15559 }
15560 }
15561 if (bfmininc) {
15562 /* minExclusive >= BASE minInclusive */
15563 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15564 if (res == -2)
15565 goto internal_error;
15566 if (res == -1) {
15567 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15568 }
15569 }
15570 if (bfmaxexc) {
15571 /* minExclusive < BASE maxExclusive */
15572 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15573 if (res == -2)
15574 goto internal_error;
15575 if (res != -1) {
15576 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015578 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015579 }
15580 if (fmininc) {
15581 /*
15582 * "minInclusive < maxExclusive"
15583 */
15584 if (fmaxexc) {
15585 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15586 if (res == -2)
15587 goto internal_error;
15588 if (res != -1) {
15589 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15590 }
15591 }
15592 /*
15593 * "minExclusive valid restriction"
15594 */
15595 if (bfmininc) {
15596 /* minInclusive >= BASE minInclusive */
15597 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15598 if (res == -2)
15599 goto internal_error;
15600 if (res == -1) {
15601 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15602 }
15603 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015604 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015605 }
15606 }
15607 if (bfmaxinc) {
15608 /* minInclusive <= BASE maxInclusive */
15609 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15610 if (res == -2)
15611 goto internal_error;
15612 if (res == -1) {
15613 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15614 }
15615 }
15616 if (bfminexc) {
15617 /* minInclusive > BASE minExclusive */
15618 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15619 if (res == -2)
15620 goto internal_error;
15621 if (res != 1)
15622 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15623 }
15624 if (bfmaxexc) {
15625 /* minInclusive < BASE maxExclusive */
15626 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15627 if (res == -2)
15628 goto internal_error;
15629 if (res != -1)
15630 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15631 }
15632 }
15633 if (ftotdig && bftotdig) {
15634 /*
15635 * SCC " totalDigits valid restriction"
15636 * totalDigits <= BASE totalDigits
15637 */
15638 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15639 if (res == -2)
15640 goto internal_error;
15641 if (res == 1)
15642 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15643 -1, 1, 1);
15644 if ((res != 0) && (bftotdig->fixed)) {
15645 FACET_RESTR_FIXED_ERR(ftotdig)
15646 }
15647 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015648 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015649 /*
15650 * SCC "fractionDigits valid restriction"
15651 * fractionDigits <= BASE fractionDigits
15652 */
15653 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15654 if (res == -2)
15655 goto internal_error;
15656 if (res == 1)
15657 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15658 -1, 1, 1);
15659 if ((res != 0) && (bffracdig->fixed)) {
15660 FACET_RESTR_FIXED_ERR(ffracdig)
15661 }
15662 }
15663 /*
15664 * SCC "fractionDigits less than or equal to totalDigits"
15665 */
15666 if (! ftotdig)
15667 ftotdig = bftotdig;
15668 if (! ffracdig)
15669 ffracdig = bffracdig;
15670 if (ftotdig && ffracdig) {
15671 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15672 if (res == -2)
15673 goto internal_error;
15674 if (res == 1)
15675 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15676 -1, 1, 0);
15677 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015678 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015679 * *Enumerations* won' be added here, since only the first set
15680 * of enumerations in the ancestor-or-self axis is used
15681 * for validation, plus we need to use the base type of those
15682 * enumerations for whitespace.
15683 *
15684 * *Patterns*: won't be add here, since they are ORed at
15685 * type level and ANDed at ancestor level. This will
15686 * happed during validation by walking the base axis
15687 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015688 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015689 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15690 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015691 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015692 * Special handling of enumerations and patterns.
15693 * TODO: hmm, they should not appear in the set, so remove this.
15694 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015695 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015696 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015697 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015698 /*
15699 * Search for a duplicate facet in the current type.
15700 */
15701 link = type->facetSet;
15702 err = 0;
15703 fixedErr = 0;
15704 while (link != NULL) {
15705 facet = link->facet;
15706 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015707 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015708 case XML_SCHEMA_FACET_WHITESPACE:
15709 /*
15710 * The whitespace must be stronger.
15711 */
15712 if (facet->whitespace < bfacet->whitespace) {
15713 FACET_RESTR_ERR(flength,
15714 "The 'whitespace' value has to be equal to "
15715 "or stronger than the 'whitespace' value of "
15716 "the base type")
15717 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015718 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015719 (facet->whitespace != bfacet->whitespace)) {
15720 FACET_RESTR_FIXED_ERR(facet)
15721 }
15722 break;
15723 default:
15724 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015725 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015726 /* Duplicate found. */
15727 break;
15728 }
15729 link = link->next;
15730 }
15731 /*
15732 * If no duplicate was found: add the base types's facet
15733 * to the set.
15734 */
15735 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015736 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015737 xmlMalloc(sizeof(xmlSchemaFacetLink));
15738 if (link == NULL) {
15739 xmlSchemaPErrMemory(pctxt,
15740 "deriving facets, creating a facet link", NULL);
15741 return (-1);
15742 }
15743 link->facet = cur->facet;
15744 link->next = NULL;
15745 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015746 type->facetSet = link;
15747 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015748 last->next = link;
15749 last = link;
15750 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015751
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015752 }
15753
15754 return (0);
15755internal_error:
15756 xmlSchemaPCustomErr(pctxt,
15757 XML_SCHEMAP_INVALID_FACET_VALUE,
15758 NULL, type, NULL,
15759 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15760 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015761}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015762
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015763static int
15764xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15765 xmlSchemaTypePtr type)
15766{
15767 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15768 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015769 * The actual value is then formed by replacing any union type
15770 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015771 * {member type definitions}, in order.
15772 */
15773 link = type->memberTypes;
15774 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015775
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015776 if (IS_NOT_TYPEFIXED(link->type))
15777 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15778
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015779 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015780 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015781 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015782 link->type = subLink->type;
15783 if (subLink->next != NULL) {
15784 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015785 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015786 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015787 while (subLink != NULL) {
15788 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015789 xmlMalloc(sizeof(xmlSchemaTypeLink));
15790 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015791 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015792 NULL);
15793 return (-1);
15794 }
15795 newLink->type = subLink->type;
15796 prevLink->next = newLink;
15797 prevLink = newLink;
15798 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015799
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015800 subLink = subLink->next;
15801 }
15802 }
15803 }
15804 }
15805 link = link->next;
15806 }
15807 return (0);
15808}
15809
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015810static void
15811xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15812{
15813 int has = 0, needVal = 0, normVal = 0;
15814
15815 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15816 if (has) {
15817 needVal = (type->baseType->flags &
15818 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15819 normVal = (type->baseType->flags &
15820 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15821 }
15822 if (type->facets != NULL) {
15823 xmlSchemaFacetPtr fac;
15824
15825 for (fac = type->facets; fac != NULL; fac = fac->next) {
15826 switch (fac->type) {
15827 case XML_SCHEMA_FACET_WHITESPACE:
15828 break;
15829 case XML_SCHEMA_FACET_PATTERN:
15830 normVal = 1;
15831 has = 1;
15832 break;
15833 case XML_SCHEMA_FACET_ENUMERATION:
15834 needVal = 1;
15835 normVal = 1;
15836 has = 1;
15837 break;
15838 default:
15839 has = 1;
15840 break;
15841 }
15842 }
15843 }
15844 if (normVal)
15845 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15846 if (needVal)
15847 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15848 if (has)
15849 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15850
15851 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15852 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15853 /*
15854 * OPTIMIZE VAL TODO: Some facets need a computed value.
15855 */
15856 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15857 (prim->builtInType != XML_SCHEMAS_STRING)) {
15858 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15859 }
15860 }
15861}
15862
15863static int
15864xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15865{
15866
15867
15868 /*
15869 * Evaluate the whitespace-facet value.
15870 */
15871 if (VARIETY_LIST(type)) {
15872 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15873 return (0);
15874 } else if (VARIETY_UNION(type))
15875 return (0);
15876
15877 if (type->facetSet != NULL) {
15878 xmlSchemaFacetLinkPtr lin;
15879
15880 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15881 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15882 switch (lin->facet->whitespace) {
15883 case XML_SCHEMAS_FACET_PRESERVE:
15884 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15885 break;
15886 case XML_SCHEMAS_FACET_REPLACE:
15887 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15888 break;
15889 case XML_SCHEMAS_FACET_COLLAPSE:
15890 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15891 break;
15892 default:
15893 return (-1);
15894 }
15895 return (0);
15896 }
15897 }
15898 }
15899 /*
15900 * For all ·atomic· datatypes other than string (and types ·derived·
15901 * by ·restriction· from it) the value of whiteSpace is fixed to
15902 * collapse
15903 */
15904 {
15905 xmlSchemaTypePtr anc;
15906
15907 for (anc = type->baseType; anc != NULL &&
15908 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15909 anc = anc->baseType) {
15910
15911 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15912 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15913 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15914
15915 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15916 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15917 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15918
15919 } else
15920 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15921 break;
15922 }
15923 }
15924 return (0);
15925 }
15926 return (0);
15927}
15928
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015929/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015930 * xmlSchemaTypeFixup:
15931 * @typeDecl: the schema type definition
15932 * @ctxt: the schema parser context
15933 *
15934 * Fixes the content model of the type.
15935 */
15936static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015937xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015938 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015939{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015940 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015941 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015942 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15943 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015944 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015945 if (! IS_NOT_TYPEFIXED(type))
15946 return;
15947 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015948 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015949 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015950
15951 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015952 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015953 XML_SCHEMAP_INTERNAL,
15954 NULL, type, NULL,
15955 "Internal error: xmlSchemaTypeFixup, "
15956 "baseType is missing on '%s'", type->name);
15957 return;
15958 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015959
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015960 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015961 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015962
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015963 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015964 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015965 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015966 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015967 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015968 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15969 /*
15970 * Skip fixup if the base type is invalid.
15971 * TODO: Generate a warning!
15972 */
15973 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015974 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015975 /*
15976 * This basically checks if the base type can be derived.
15977 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015978 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015979 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15980 return;
15981 }
15982 /*
15983 * Fixup the content type.
15984 */
15985 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15986 /*
15987 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015988 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015989 if ((IS_COMPLEX_TYPE(baseType)) &&
15990 (baseType->contentTypeDef != NULL) &&
15991 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015992 xmlSchemaTypePtr contentBase, content;
15993 char buf[30];
15994 const xmlChar *tmpname;
15995 /*
15996 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015997 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015998 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015999 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016000 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016001 * SPEC (1.1) "the simple type definition corresponding to the
16002 * <simpleType> among the [children] of <restriction> if there
16003 * is one;"
16004 * Note that this "<simpleType> among the [children]" was put
16005 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016007 contentBase = type->contentTypeDef;
16008 type->contentTypeDef = NULL;
16009 } else {
16010 /*
16011 * (1.2) "...otherwise (<restriction> has no <simpleType>
16012 * among its [children]), the simple type definition which
16013 * is the {content type} of the ... base type."
16014 */
16015 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016016 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016017 /*
16018 * SPEC
16019 * "... a simple type definition which restricts the simple
16020 * type definition identified in clause 1.1 or clause 1.2
16021 * with a set of facet components"
16022 *
16023 * Create the anonymous simple type, which will be the content
16024 * type of the complex type.
16025 */
16026 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16027 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16028 content = xmlSchemaAddType(pctxt,
16029 pctxt->schema, tmpname, tmpname, type->node);
16030 if (content == NULL)
16031 return;
16032 /*
16033 * We will use the same node as for the <complexType>
16034 * to have it somehow anchored in the schema doc.
16035 */
16036 content->node = type->node;
16037 content->type = XML_SCHEMA_TYPE_SIMPLE;
16038 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16039 content->baseType = contentBase;
16040 /*
16041 * Move the facets, previously anchored on the complexType.
16042 */
16043 content->facets = type->facets;
16044 type->facets = NULL;
16045 content->facetSet = type->facetSet;
16046 type->facetSet = NULL;
16047
16048 type->contentTypeDef = content;
16049 if (IS_NOT_TYPEFIXED(contentBase))
16050 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16051 xmlSchemaTypeFixup(content, pctxt, NULL);
16052
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016053 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16054 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16055 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16056 /*
16057 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16058 * an emptiable particle, then a simple type definition which
16059 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016060 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016061 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016062 (type->contentTypeDef->baseType == NULL)) {
16063 /*
16064 * TODO: Check if this ever happens.
16065 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016066 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016067 XML_SCHEMAP_INTERNAL,
16068 NULL, type, NULL,
16069 "Internal error: xmlSchemaTypeFixup, "
16070 "complex type '%s': the <simpleContent><restriction> "
16071 "is missing a <simpleType> child, but was not catched "
16072 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016073 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016074 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16075 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16076 /*
16077 * SPEC (3) If <extension> + base is <complexType> with
16078 * <simpleType> content, "...then the {content type} of that
16079 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016080 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016081 if (baseType->contentTypeDef == NULL) {
16082 /*
16083 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16084 * should have catched this already.
16085 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016086 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016087 XML_SCHEMAP_INTERNAL,
16088 NULL, type, NULL,
16089 "Internal error: xmlSchemaTypeFixup, "
16090 "complex type '%s': the <extension>ed base type is "
16091 "a complex type with no simple content type",
16092 type->name);
16093 }
16094 type->contentTypeDef = baseType->contentTypeDef;
16095 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16096 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16097 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016098 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016099 * "... then that simple type definition"
16100 */
16101 type->contentTypeDef = baseType;
16102 } else {
16103 /*
16104 * TODO: Check if this ever happens.
16105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016106 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016107 XML_SCHEMAP_INTERNAL,
16108 NULL, type, NULL,
16109 "Internal error: xmlSchemaTypeFixup, "
16110 "complex type '%s' with <simpleContent>: unhandled "
16111 "derivation case", type->name);
16112 }
16113 } else {
16114 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016115 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016116 (xmlSchemaParticlePtr) type->subtypes;
16117 /*
16118 * Corresponds to <complexType><complexContent>...
16119 *
16120 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016121 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016122 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016123 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016124 * Compute the "effective content":
16125 * (2.1.1) + (2.1.2) + (2.1.3)
16126 */
16127 if ((particle == NULL) ||
16128 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16129 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16130 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16131 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16132 (particle->minOccurs == 0))) &&
16133 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016134 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016135 /*
16136 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16137 * a particle whose properties are as follows:..."
16138 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016139 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016140 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16141 * NOTE that we sill assign it the <complexType> node to
16142 * somehow anchor it in the doc.
16143 */
16144 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016145 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016146 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016147 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016148 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016149 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 type->node, 1, 1);
16151 if (particle == NULL)
16152 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016153 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016154 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016155 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016156 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016157 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016158 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16159 if (particle->children == NULL)
16160 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016161
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016162 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016163 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 dummySequence = 1;
16165 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16166 } else {
16167 /*
16168 * SPEC (2.1.5) "otherwise empty"
16169 */
16170 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016171 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016172 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016173 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016174 * SPEC (2.2) "otherwise the particle corresponding to the
16175 * <all>, <choice>, <group> or <sequence> among the
16176 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016177 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016178 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16179 }
16180 /*
16181 * Compute the "content type".
16182 */
16183 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016184 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016185 * SPEC (3.1) "If <restriction>..."
16186 * (3.1.1) + (3.1.2) */
16187 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16188 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16189 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16190 }
16191 } else {
16192 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016193 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016194 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16196 /*
16197 * SPEC (3.2.1)
16198 */
16199 type->contentType = baseType->contentType;
16200 type->subtypes = baseType->subtypes;
16201 /*
16202 * NOTE that the effective mixed is ignored here.
16203 */
16204 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16205 /*
16206 * SPEC (3.2.2)
16207 */
16208 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16209 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16210 } else {
16211 /*
16212 * SPEC (3.2.3)
16213 */
16214 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16215 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16216 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016217 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016218 * {particles} are..."
16219 */
16220 if (! dummySequence) {
16221 xmlSchemaTreeItemPtr effectiveContent =
16222 (xmlSchemaTreeItemPtr) type->subtypes;
16223 /*
16224 * Create the particle.
16225 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016226 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016227 type->node, 1, 1);
16228 if (particle == NULL)
16229 return;
16230 /*
16231 * Create the "sequence" model group.
16232 */
16233 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016234 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016235 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16236 if (particle->children == NULL)
16237 return;
16238 type->subtypes = (xmlSchemaTypePtr) particle;
16239 /*
16240 * SPEC "the particle of the {content type} of
16241 * the ... base ..."
16242 * Create a duplicate of the base type's particle
16243 * and assign its "term" to it.
16244 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016245 particle->children->children =
16246 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16247 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016248 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016249 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016250 if (particle->children->children == NULL)
16251 return;
16252 particle = (xmlSchemaParticlePtr)
16253 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016254 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016255 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16256 /*
16257 * SPEC "followed by the ·effective content·."
16258 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016259 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 } else {
16261 /*
16262 * This is the case when there is already an empty
16263 * <sequence> with minOccurs==maxOccurs==1.
16264 * Just add the base types's content type.
16265 * NOTE that, although we miss to add an intermediate
16266 * <sequence>, this should produce no difference to
16267 * neither the regex compilation of the content model,
16268 * nor to the complex type contraints.
16269 */
16270 particle->children->children =
16271 (xmlSchemaTreeItemPtr) baseType->subtypes;
16272 }
16273 }
16274 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016275 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016276 /*
16277 * Apply the complex type component constraints; this will not
16278 * check attributes, since this is done in
16279 * xmlSchemaBuildAttributeValidation().
16280 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016281 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16282 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016283 /*
16284 * Inherit & check constraints for attributes.
16285 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016286 xmlSchemaBuildAttributeValidation(pctxt, type);
16287 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016288 /*
16289 * Simple Type Definition Schema Component
16290 */
16291 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016292 if (VARIETY_LIST(type)) {
16293 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016294 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016295 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016296 if (type->subtypes == NULL) {
16297 /*
16298 * This one is really needed, so get out.
16299 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016300 PERROR_INT("xmlSchemaTypeFixup",
16301 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016302 return;
16303 }
16304 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016305 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16306 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016307 /*
16308 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016309 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016310 if (type->memberTypes == NULL) {
16311 /*
16312 * This one is really needed, so get out.
16313 */
16314 return;
16315 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016316 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016317 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016318 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016319 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016320 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016321 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016322 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016323 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016324 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16325 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016326 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016327 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016328 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016329 */
16330 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016331 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016332 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016333 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16334 /*
16335 * Inherit the itemType.
16336 */
16337 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016338 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016339 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16340 /*
16341 * NOTE that we won't assign the memberTypes of the base,
16342 * since this will make trouble when freeing them; we will
16343 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016344 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016345 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016346 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016347 /*
16348 * Check constraints.
16349 *
16350 * TODO: Split this somehow, we need to know first if we can derive
16351 * from the base type at all!
16352 */
16353 if (type->baseType != NULL) {
16354 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016355 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016356 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016357 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 * applied beforehand.
16359 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016360 xmlSchemaCheckSRCSimpleType(pctxt, type);
16361 xmlSchemaCheckFacetValues(type, pctxt);
16362 if ((type->facetSet != NULL) ||
16363 (type->baseType->facetSet != NULL))
16364 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16365 /*
16366 * Whitespace value.
16367 */
16368 xmlSchemaTypeFixupWhitespace(type);
16369 xmlSchemaTypeFixupOptimFacets(type);
16370 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016371 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016372
Daniel Veillard8651f532002-04-17 09:06:27 +000016373#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016374 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016375 xmlGenericError(xmlGenericErrorContext,
16376 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 type->node->doc->URL,
16378 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016379 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016380 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016381 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16383 switch (type->contentType) {
16384 case XML_SCHEMA_CONTENT_SIMPLE:
16385 xmlGenericError(xmlGenericErrorContext, "simple\n");
16386 break;
16387 case XML_SCHEMA_CONTENT_ELEMENTS:
16388 xmlGenericError(xmlGenericErrorContext, "elements\n");
16389 break;
16390 case XML_SCHEMA_CONTENT_UNKNOWN:
16391 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16392 break;
16393 case XML_SCHEMA_CONTENT_EMPTY:
16394 xmlGenericError(xmlGenericErrorContext, "empty\n");
16395 break;
16396 case XML_SCHEMA_CONTENT_MIXED:
16397 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016398 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016399 xmlGenericError(xmlGenericErrorContext,
16400 "mixed as emptiable particle\n");
16401 else
16402 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16403 break;
16404 /* Removed, since not used. */
16405 /*
16406 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16407 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16408 break;
16409 */
16410 case XML_SCHEMA_CONTENT_BASIC:
16411 xmlGenericError(xmlGenericErrorContext, "basic\n");
16412 break;
16413 default:
16414 xmlGenericError(xmlGenericErrorContext,
16415 "not registered !!!\n");
16416 break;
16417 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016418 }
16419#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016420}
16421
16422/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016423 * xmlSchemaCheckFacet:
16424 * @facet: the facet
16425 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016426 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016427 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016428 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016429 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016430 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016431 * Returns 0 if valid, a positive error code if not valid and
16432 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016433 */
16434int
16435xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016436 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016437 xmlSchemaParserCtxtPtr pctxt,
16438 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016439{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016440 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016441
Daniel Veillardce682bc2004-11-05 17:22:25 +000016442 if ((facet == NULL) || (typeDecl == NULL))
16443 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016444 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016445 * TODO: will the parser context be given if used from
16446 * the relaxNG module?
16447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016448 if (pctxt == NULL)
16449 ctxtGiven = 0;
16450 else
16451 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016452
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016453 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016454 case XML_SCHEMA_FACET_MININCLUSIVE:
16455 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16456 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016457 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16458 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016459 /*
16460 * Okay we need to validate the value
16461 * at that point.
16462 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016463 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016464
16465 /* 4.3.5.5 Constraints on enumeration Schema Components
16466 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016467 * It is an ·error· if any member of {value} is not in the
16468 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016469 *
16470 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016471 * The value ·must· be in the
16472 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016473 */
16474 /*
16475 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016476 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016477 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016478 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016479 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016480 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016481 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016482 */
16483 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16484 base = typeDecl->baseType;
16485 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016486 PERROR_INT("xmlSchemaCheckFacet",
16487 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016488 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016489 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016490 } else
16491 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016492
16493 if (! ctxtGiven) {
16494 /*
16495 * A context is needed if called from RelaxNG.
16496 */
16497 pctxt = xmlSchemaNewParserCtxt("*");
16498 if (pctxt == NULL)
16499 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016500 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016501 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016502 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016503 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016504 * facet->node is just the node holding the facet
16505 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016506 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016507 */
16508 ret = xmlSchemaVCheckCVCSimpleType(
16509 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16510 facet->value, &(facet->val), 1, 1, 0);
16511 if (ret != 0) {
16512 if (ret < 0) {
16513 /* No error message for RelaxNG. */
16514 if (ctxtGiven) {
16515 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16516 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16517 "Internal error: xmlSchemaCheckFacet, "
16518 "failed to validate the value '%s' of the "
16519 "facet '%s' against the base type",
16520 facet->value, xmlSchemaFacetTypeToString(facet->type));
16521 }
16522 goto internal_error;
16523 }
16524 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16525 /* No error message for RelaxNG. */
16526 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016527 xmlChar *str = NULL;
16528
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016529 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16530 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016531 "The value '%s' of the facet does not validate "
16532 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016533 facet->value,
16534 xmlSchemaFormatQName(&str,
16535 base->targetNamespace, base->name));
16536 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016537 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016538 goto exit;
16539 } else if (facet->val == NULL) {
16540 if (ctxtGiven) {
16541 PERROR_INT("xmlSchemaCheckFacet",
16542 "value was not computed");
16543 }
16544 TODO
16545 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016546 break;
16547 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016548 case XML_SCHEMA_FACET_PATTERN:
16549 facet->regexp = xmlRegexpCompile(facet->value);
16550 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016551 ret = XML_SCHEMAP_REGEXP_INVALID;
16552 /* No error message for RelaxNG. */
16553 if (ctxtGiven) {
16554 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16555 ret, facet->node, typeDecl,
16556 "The value '%s' of the facet 'pattern' is not a "
16557 "valid regular expression",
16558 facet->value, NULL);
16559 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016560 }
16561 break;
16562 case XML_SCHEMA_FACET_TOTALDIGITS:
16563 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16564 case XML_SCHEMA_FACET_LENGTH:
16565 case XML_SCHEMA_FACET_MAXLENGTH:
16566 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016567 ret = xmlSchemaValidatePredefinedType(
16568 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16569 facet->value, &(facet->val));
16570 if (ret != 0) {
16571 if (ret < 0) {
16572 /* No error message for RelaxNG. */
16573 if (ctxtGiven) {
16574 PERROR_INT("xmlSchemaCheckFacet",
16575 "validating facet value");
16576 }
16577 goto internal_error;
16578 }
16579 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16580 /* No error message for RelaxNG. */
16581 if (ctxtGiven) {
16582 /* error code */
16583 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16584 ret, facet->node, typeDecl,
16585 "The value '%s' of the facet '%s' is not a valid "
16586 "'nonNegativeInteger'",
16587 facet->value,
16588 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016589 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016590 }
16591 break;
16592 }
16593 case XML_SCHEMA_FACET_WHITESPACE:{
16594 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16595 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16596 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16597 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16598 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16599 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16600 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016601 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16602 /* No error message for RelaxNG. */
16603 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016604 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016605 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16606 ret, facet->node, typeDecl,
16607 "The value '%s' of the facet 'whitespace' is not "
16608 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016609 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016610 }
16611 }
16612 default:
16613 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016615exit:
16616 if ((! ctxtGiven) && (pctxt != NULL))
16617 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016618 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016619internal_error:
16620 if ((! ctxtGiven) && (pctxt != NULL))
16621 xmlSchemaFreeParserCtxt(pctxt);
16622 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016623}
16624
16625/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016626 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016627 * @typeDecl: the schema type definition
16628 * @ctxt: the schema parser context
16629 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016630 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016631 */
16632static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016633xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16634 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016635{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016636 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016637 /*
16638 * NOTE: It is intended to use the facets list, instead
16639 * of facetSet.
16640 */
16641 if (typeDecl->facets != NULL) {
16642 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016643
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016644 /*
16645 * Temporarily assign the "schema" to the validation context
16646 * of the parser context. This is needed for NOTATION validation.
16647 */
16648 if (ctxt->vctxt == NULL) {
16649 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16650 return;
16651 }
16652 ctxt->vctxt->schema = ctxt->schema;
16653
Daniel Veillard01fa6152004-06-29 17:04:39 +000016654 while (facet != NULL) {
16655 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16656 facet = facet->next;
16657 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016658
16659 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016660 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016661}
16662
16663/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016664 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016665 * @ctxtMGroup: the searched model group
16666 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016667 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016668 *
16669 * This one is intended to be used by
16670 * xmlSchemaCheckGroupDefCircular only.
16671 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016672 * Returns the particle with the circular model group definition reference,
16673 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016674 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016675static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016676xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016677 xmlSchemaTreeItemPtr particle)
16678{
16679 xmlSchemaTreeItemPtr circ = NULL;
16680 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016681 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016682
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016683 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016684 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016685 if (term == NULL)
16686 continue;
16687 switch (term->type) {
16688 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016689 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016690 if (gdef == groupDef)
16691 return (particle);
16692 /*
16693 * Mark this model group definition to avoid infinite
16694 * recursion on circular references not yet examined.
16695 */
16696 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16697 continue;
16698 if (gdef->children != NULL) {
16699 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16700 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16701 gdef->children->children);
16702 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16703 if (circ != NULL)
16704 return (circ);
16705 }
16706 break;
16707 case XML_SCHEMA_TYPE_SEQUENCE:
16708 case XML_SCHEMA_TYPE_CHOICE:
16709 case XML_SCHEMA_TYPE_ALL:
16710 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16711 if (circ != NULL)
16712 return (circ);
16713 break;
16714 default:
16715 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016716 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016717 }
16718 return (NULL);
16719}
16720
16721/**
16722 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016723 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016724 * @ctxt: the parser context
16725 * @name: the name
16726 *
16727 * Checks for circular references to model group definitions.
16728 */
16729static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016730xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016731 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016732 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016733{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016734 /*
16735 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016736 * 2 Circular groups are disallowed. That is, within the {particles}
16737 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016738 * is the group itself.
16739 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016740 if ((item == NULL) ||
16741 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16742 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016743 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016744 {
16745 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016746
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016747 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016748 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016749 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016750 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016751 * TODO: The error report is not adequate: this constraint
16752 * is defined for model groups but not definitions, but since
16753 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016754 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016755 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016756 */
16757 xmlSchemaPCustomErr(ctxt,
16758 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016759 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016760 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016761 "defined", xmlSchemaFormatQName(&str,
16762 item->targetNamespace, item->name));
16763 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016764 /*
16765 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016766 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016767 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016768 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016769 }
16770 }
16771}
16772
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016773/**
16774 * xmlSchemaGroupDefTermFixup:
16775 * @item: the particle with a model group definition as term
16776 * @ctxt: the parser context
16777 * @name: the name
16778 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016779 * Checks cos-all-limited.
16780 *
16781 * Assigns the model group of model group definitions to the "term"
16782 * of the referencing particle.
16783 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16784 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016785 */
16786static void
16787xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016788 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016789 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016790{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016791 if ((item == NULL) ||
16792 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16793 (item->children == NULL) ||
16794 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16795 (item->children->children == NULL))
16796 return;
16797 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016798 /*
16799 * TODO: Not nice, but we will anchor cos-all-limited here.
16800 */
16801 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16802 (item->maxOccurs != 1)) {
16803 /*
16804 * SPEC (1.2) "the {term} property of a particle with
16805 * {max occurs}=1which is part of a pair which constitutes the
16806 * {content type} of a complex type definition."
16807 */
16808 xmlSchemaPCustomErr(ctxt,
16809 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16810 NULL, (xmlSchemaTypePtr) item, item->node,
16811 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16812 "group is its term", NULL);
16813 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016814}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016815
16816/**
16817 * xmlSchemaGetCircAttrGrRef:
16818 * @ctxtGr: the searched attribute group
16819 * @attr: the current attribute list to be processed
16820 *
16821 * This one is intended to be used by
16822 * xmlSchemaCheckSRCAttributeGroupCircular only.
16823 *
16824 * Returns the circular attribute grou reference, otherwise NULL.
16825 */
16826static xmlSchemaAttributeGroupPtr
16827xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16828 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016829{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016830 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16831 int marked;
16832 /*
16833 * We will search for an attribute group reference which
16834 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016835 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016836 while (attr != NULL) {
16837 marked = 0;
16838 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16839 gr = (xmlSchemaAttributeGroupPtr) attr;
16840 if (gr->refItem != NULL) {
16841 if (gr->refItem == ctxtGr)
16842 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016843 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016844 XML_SCHEMAS_ATTRGROUP_MARKED) {
16845 attr = attr->next;
16846 continue;
16847 } else {
16848 /*
16849 * Mark as visited to avoid infinite recursion on
16850 * circular references not yet examined.
16851 */
16852 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16853 marked = 1;
16854 }
16855 }
16856 if (gr->attributes != NULL)
16857 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16858 /*
16859 * Unmark the visited group's attributes.
16860 */
16861 if (marked)
16862 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16863 if (circ != NULL)
16864 return (circ);
16865 }
16866 attr = attr->next;
16867 }
16868 return (NULL);
16869}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016870
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016871/**
16872 * xmlSchemaCheckSRCAttributeGroupCircular:
16873 * attrGr: the attribute group definition
16874 * @ctxt: the parser context
16875 * @name: the name
16876 *
16877 * Checks for circular references of attribute groups.
16878 */
16879static void
16880xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016881 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016882 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016883{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016884 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016885 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016886 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016887 * 3 Circular group reference is disallowed outside <redefine>.
16888 * That is, unless this element information item's parent is
16889 * <redefine>, then among the [children], if any, there must
16890 * not be an <attributeGroup> with ref [attribute] which resolves
16891 * to the component corresponding to this <attributeGroup>. Indirect
16892 * circularity is also ruled out. That is, when QName resolution
16893 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16894 * any <attributeGroup>s with a ref [attribute] among the [children],
16895 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016896 * which resolves to the component corresponding to this <attributeGroup>.
16897 */
16898 /*
16899 * Only global components can be referenced.
16900 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016901 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016902 (attrGr->attributes == NULL))
16903 return;
16904 else {
16905 xmlSchemaAttributeGroupPtr circ;
16906
16907 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16908 if (circ != NULL) {
16909 /*
16910 * TODO: Report the referenced attr group as QName.
16911 */
16912 xmlSchemaPCustomErr(ctxt,
16913 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16914 NULL, NULL, circ->node,
16915 "Circular reference to the attribute group '%s' "
16916 "defined", attrGr->name);
16917 /*
16918 * NOTE: We will cut the reference to avoid further
16919 * confusion of the processor.
16920 * BADSPEC: The spec should define how to process in this case.
16921 */
16922 circ->attributes = NULL;
16923 circ->refItem = NULL;
16924 }
16925 }
16926}
16927
16928/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016929 * xmlSchemaAttrGrpFixup:
16930 * @attrgrpDecl: the schema attribute definition
16931 * @ctxt: the schema parser context
16932 * @name: the attribute name
16933 *
16934 * Fixes finish doing the computations on the attributes definitions
16935 */
16936static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016937xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016938 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016939{
16940 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016941 name = attrgrp->name;
16942 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016943 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016944 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016945 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016946
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016947 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016948 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016949 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016950 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016951 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016952 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16953 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016954 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016955 return;
16956 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016957 attrgrp->refItem = ref;
16958 /*
16959 * Check for self reference!
16960 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016961 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016962 attrgrp->attributes = ref->attributes;
16963 attrgrp->attributeWildcard = ref->attributeWildcard;
16964 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016965}
16966
16967/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016968 * xmlSchemaAttrCheckValConstr:
16969 * @item: an schema attribute declaration/use
16970 * @ctxt: a schema parser context
16971 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016972 *
16973 *
16974 * Schema Component Constraint: Attribute Declaration Properties Correct
16975 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016976 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016977 *
16978 * Fixes finish doing the computations on the attributes definitions
16979 */
16980static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016981xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016982 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016983 const xmlChar * name ATTRIBUTE_UNUSED)
16984{
16985
16986 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016987 * 2 if there is a {value constraint}, the canonical lexical
16988 * representation of its value must be ·valid· with respect
16989 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016990 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016991 if (item->defValue != NULL) {
16992 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016993
16994 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016995 PERROR_INT("xmlSchemaCheckAttrValConstr",
16996 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016997 return;
16998 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016999 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17000 item->node, item->subtypes, item->defValue, &(item->defVal),
17001 1, 1, 0);
17002 if (ret != 0) {
17003 if (ret < 0) {
17004 PERROR_INT("xmlSchemaAttrCheckValConstr",
17005 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017006 return;
17007 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017008 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17009 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17010 ret, item->node, (xmlSchemaTypePtr) item,
17011 "The value of the value constraint is not valid", NULL, NULL);
17012 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017013 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017014 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017015}
17016
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017017static xmlSchemaElementPtr
17018xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17019 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017020{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017021 xmlSchemaElementPtr ret;
17022
17023 if (SUBST_GROUP_AFF(ancestor) == NULL)
17024 return (NULL);
17025 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17026 return (ancestor);
17027
17028 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17029 return (NULL);
17030 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17031 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17032 SUBST_GROUP_AFF(ancestor));
17033 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17034
17035 return (ret);
17036}
17037
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017038/**
17039 * xmlSchemaCheckElemPropsCorrect:
17040 * @ctxt: a schema parser context
17041 * @decl: the element declaration
17042 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017043 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017044 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017045 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017046 *
17047 * STATUS:
17048 * missing: (6)
17049 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017050static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017051xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17052 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017053{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017054 int ret = 0;
17055 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017056 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017057 * SPEC (1) "The values of the properties of an element declaration
17058 * must be as described in the property tableau in The Element
17059 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17060 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017061 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017062 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017063 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017064
17065 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017066 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017067 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017068 * affiliation}, then {scope} must be global."
17069 */
17070 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17071 xmlSchemaPCustomErr(pctxt,
17072 XML_SCHEMAP_E_PROPS_CORRECT_3,
17073 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17074 "Only global element declarations can have a "
17075 "substitution group affiliation", NULL);
17076 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017077 }
17078 /*
17079 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17080 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017081 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017082 * property."
17083 */
17084 if (head == elemDecl)
17085 circ = head;
17086 else if (SUBST_GROUP_AFF(head) != NULL)
17087 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17088 else
17089 circ = NULL;
17090 if (circ != NULL) {
17091 xmlChar *strA = NULL, *strB = NULL;
17092
17093 xmlSchemaPCustomErrExt(pctxt,
17094 XML_SCHEMAP_E_PROPS_CORRECT_6,
17095 NULL, (xmlSchemaTypePtr) circ, circ->node,
17096 "The element declaration '%s' defines a circular "
17097 "substitution group to element declaration '%s'",
17098 xmlSchemaGetComponentQName(&strA, circ),
17099 xmlSchemaGetComponentQName(&strB, head),
17100 NULL);
17101 FREE_AND_NULL(strA)
17102 FREE_AND_NULL(strB)
17103 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17104 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017105 /*
17106 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017107 * the {type definition}
17108 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017109 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017110 * of the {substitution group exclusions} of the {substitution group
17111 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17112 * (if the {type definition} is complex) or as defined in
17113 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017114 * simple)."
17115 *
17116 * NOTE: {substitution group exclusions} means the values of the
17117 * attribute "final".
17118 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017120 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017121 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017122
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017123 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17124 set |= SUBSET_EXTENSION;
17125 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17126 set |= SUBSET_RESTRICTION;
17127
17128 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17129 ELEM_TYPE(head), set) != 0) {
17130 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17131
17132 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017133 xmlSchemaPCustomErrExt(pctxt,
17134 XML_SCHEMAP_E_PROPS_CORRECT_4,
17135 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017136 "The type definition '%s' was "
17137 "either rejected by the substitution group "
17138 "affiliation '%s', or not validly derived from its type "
17139 "definition '%s'",
17140 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017141 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017142 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017143 FREE_AND_NULL(strA)
17144 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017145 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017146 }
17147 }
17148 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017149 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017150 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017151 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017152 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017153 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017154 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017155 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017157 ((IS_SIMPLE_TYPE(typeDef) &&
17158 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017159 (IS_COMPLEX_TYPE(typeDef) &&
17160 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017161 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17162 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017163
17164 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17165 xmlSchemaPCustomErr(pctxt,
17166 XML_SCHEMAP_E_PROPS_CORRECT_5,
17167 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17168 "The type definition (or type definition's content type) is or "
17169 "is derived from ID; value constraints are not allowed in "
17170 "conjunction with such a type definition", NULL);
17171 } else if (elemDecl->value != NULL) {
17172 int vcret;
17173 xmlNodePtr node = NULL;
17174
17175 /*
17176 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17177 * representation of its value must be ·valid· with respect to the
17178 * {type definition} as defined in Element Default Valid (Immediate)
17179 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017180 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017181 if (typeDef == NULL) {
17182 xmlSchemaPErr(pctxt, elemDecl->node,
17183 XML_SCHEMAP_INTERNAL,
17184 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17185 "type is missing... skipping validation of "
17186 "the value constraint", NULL, NULL);
17187 return (-1);
17188 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017189 if (elemDecl->node != NULL) {
17190 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17191 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17192 BAD_CAST "fixed");
17193 else
17194 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17195 BAD_CAST "default");
17196 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017197 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17198 typeDef, elemDecl->value, &(elemDecl->defVal));
17199 if (vcret != 0) {
17200 if (vcret < 0) {
17201 PERROR_INT("xmlSchemaElemCheckValConstr",
17202 "failed to validate the value constraint of an "
17203 "element declaration");
17204 return (-1);
17205 }
17206 return (vcret);
17207 }
17208 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017209
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017210 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017211}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017212
17213/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017214 * xmlSchemaCheckElemSubstGroup:
17215 * @ctxt: a schema parser context
17216 * @decl: the element declaration
17217 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017218 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017219 * Schema Component Constraint:
17220 * Substitution Group (cos-equiv-class)
17221 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017222 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017223 * a list will be built for each subst. group head, holding all direct
17224 * referents to this head.
17225 * NOTE that this function needs:
17226 * 1. circular subst. groups to be checked beforehand
17227 * 2. the declaration's type to be derived from the head's type
17228 *
17229 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017230 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017231 */
17232static void
17233xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17234 xmlSchemaElementPtr elemDecl)
17235{
17236 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17237 /* SPEC (1) "Its {abstract} is false." */
17238 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17239 return;
17240 {
17241 xmlSchemaElementPtr head;
17242 xmlSchemaTypePtr headType, type;
17243 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017244 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017245 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17246 * {disallowed substitutions} as the blocking constraint, as defined in
17247 * Substitution Group OK (Transitive) (§3.3.6)."
17248 */
17249 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17250 head = SUBST_GROUP_AFF(head)) {
17251 set = 0;
17252 methSet = 0;
17253 /*
17254 * The blocking constraints.
17255 */
17256 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17257 continue;
17258 headType = head->subtypes;
17259 type = elemDecl->subtypes;
17260 if (headType == type)
17261 goto add_member;
17262 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17263 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17264 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17265 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17266 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017267 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017268 * "The set of all {derivation method}s involved in the
17269 * derivation of D's {type definition} from C's {type definition}
17270 * does not intersect with the union of the blocking constraint,
17271 * C's {prohibited substitutions} (if C is complex, otherwise the
17272 * empty set) and the {prohibited substitutions} (respectively the
17273 * empty set) of any intermediate {type definition}s in the
17274 * derivation of D's {type definition} from C's {type definition}."
17275 */
17276 /*
17277 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17278 * subst.head axis, the methSet does not need to be computed for
17279 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017280 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017281 /*
17282 * The set of all {derivation method}s involved in the derivation
17283 */
17284 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017285 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017286 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17287 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17288 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017289
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017290 if ((type->flags &
17291 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17292 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17293 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17294
17295 type = type->baseType;
17296 }
17297 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017298 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017299 * the head's type.
17300 */
17301 type = elemDecl->subtypes->baseType;
17302 while (type != NULL) {
17303 if (IS_COMPLEX_TYPE(type)) {
17304 if ((type->flags &
17305 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17306 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17307 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17308 if ((type->flags &
17309 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17310 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17311 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17312 } else
17313 break;
17314 if (type == headType)
17315 break;
17316 type = type->baseType;
17317 }
17318 if ((set != 0) &&
17319 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17320 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17321 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17322 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17323 continue;
17324 }
17325add_member:
17326 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17327 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17328 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17329 }
17330 }
17331}
17332
17333/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017334 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017335 * @item: an schema element declaration/particle
17336 * @ctxt: a schema parser context
17337 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017338 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017339 * Validates the value constraints of an element declaration.
17340 *
17341 * Fixes finish doing the computations on the element declarations.
17342 */
17343static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017344xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017345 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017346 const xmlChar * name ATTRIBUTE_UNUSED)
17347{
17348 if (elemDecl == NULL)
17349 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017350 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17351 return;
17352 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017353 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17354 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017355}
17356
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017357/**
17358 * xmlSchemaMiscRefFixup:
17359 * @item: an schema component
17360 * @ctxt: a schema parser context
17361 * @name: the internal name of the component
17362 *
17363 * Resolves references of misc. schema components.
17364 */
17365static void
17366xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017367 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017368 const xmlChar * name ATTRIBUTE_UNUSED)
17369{
17370 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017371 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017372 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17373 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17374 xmlSchemaTreeItemPtr refItem;
17375 /*
17376 * Resolve the reference.
17377 */
17378 item->children = NULL;
17379 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17380 ref->itemType, ref->name, ref->targetNamespace);
17381 if (refItem == NULL) {
17382 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017383 NULL, GET_NODE(item), "ref", ref->name,
17384 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017385 } else {
17386 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17387 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017388 * NOTE that we will assign the model group definition
17389 * itself to the "term" of the particle. This will ease
17390 * the check for circular model group definitions. After
17391 * that the "term" will be assigned the model group of the
17392 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017393 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017394 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017395 } else
17396 item->children = refItem;
17397 }
17398 }
17399 }
17400}
17401
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017402static int
17403xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17404 xmlSchemaValPtr y)
17405{
17406 xmlSchemaTypePtr tx, ty, ptx, pty;
17407 int ret;
17408
17409 while (x != NULL) {
17410 /* Same types. */
17411 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17412 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17413 ptx = xmlSchemaGetPrimitiveType(tx);
17414 pty = xmlSchemaGetPrimitiveType(ty);
17415 /*
17416 * (1) if a datatype T' is ·derived· by ·restriction· from an
17417 * atomic datatype T then the ·value space· of T' is a subset of
17418 * the ·value space· of T. */
17419 /*
17420 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17421 * from a common atomic ancestor T then the ·value space·s of T'
17422 * and T'' may overlap.
17423 */
17424 if (ptx != pty)
17425 return(0);
17426 /*
17427 * We assume computed values to be normalized, so do a fast
17428 * string comparison for string based types.
17429 */
17430 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17431 IS_ANY_SIMPLE_TYPE(ptx)) {
17432 if (! xmlStrEqual(
17433 xmlSchemaValueGetAsString(x),
17434 xmlSchemaValueGetAsString(y)))
17435 return (0);
17436 } else {
17437 ret = xmlSchemaCompareValuesWhtsp(
17438 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17439 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17440 if (ret == -2)
17441 return(-1);
17442 if (ret != 0)
17443 return(0);
17444 }
17445 /*
17446 * Lists.
17447 */
17448 x = xmlSchemaValueGetNext(x);
17449 if (x != NULL) {
17450 y = xmlSchemaValueGetNext(y);
17451 if (y == NULL)
17452 return (0);
17453 } else if (xmlSchemaValueGetNext(y) != NULL)
17454 return (0);
17455 else
17456 return (1);
17457 }
17458 return (0);
17459}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017460
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017461/**
17462 * xmlSchemaAttrFixup:
17463 * @item: an schema attribute declaration/use.
17464 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017465 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017466 *
17467 * Fixes finish doing the computations on attribute declarations/uses.
17468 */
17469static void
17470xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017471 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017472 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017473{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017474 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017475 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017476 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017477 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017478 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017479 * The simple type definition corresponding to the <simpleType> element
17480 * information item in the [children], if present, otherwise the simple
17481 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017482 * [attribute], if present, otherwise the ·simple ur-type definition·.
17483 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017484 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017485 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017486 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17487 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017488 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017489 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017490 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017491
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017492 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17493 item->typeNs);
17494 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017495 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017496 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017497 (xmlSchemaTypePtr) item, item->node,
17498 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017499 XML_SCHEMA_TYPE_SIMPLE, NULL);
17500 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017501 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017502
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017503 } else if (item->ref != NULL) {
17504 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017505
Daniel Veillardc0826a72004-08-10 14:17:33 +000017506 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017507 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017508 * attribute declaration.
17509 */
17510 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017511 * TODO: Evaluate, what errors could occur if the declaration is not
17512 * found. It might be possible that the "typefixup" might crash if
17513 * no ref declaration was found.
17514 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017515 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017516 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017517 xmlSchemaPResCompAttrErr(ctxt,
17518 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017519 (xmlSchemaTypePtr) item, item->node,
17520 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017521 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017522 return;
17523 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017524 item->refDecl = decl;
17525 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017526 item->subtypes = decl->subtypes;
17527 /*
17528 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017529 * au-props-correct.2: If the {attribute declaration} has a fixed
17530 * {value constraint}, then if the attribute use itself has a
17531 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017532 * that of the {attribute declaration}'s {value constraint}.
17533 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017534 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017535 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017536 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017537 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017538 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17539 NULL, NULL, item->node,
17540 "The attribute declaration has a 'fixed' value constraint "
17541 ", thus it must be 'fixed' in attribute use as well",
17542 NULL);
17543 } else {
17544 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17545 xmlSchemaPCustomErr(ctxt,
17546 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17547 NULL, NULL, item->node,
17548 "The 'fixed' value constraint of the attribute use "
17549 "must match the attribute declaration's value "
17550 "constraint '%s'",
17551 decl->defValue);
17552 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017553 }
17554 /*
17555 * FUTURE: One should change the values of the attr. use
17556 * if ever validation should be attempted even if the
17557 * schema itself was not fully valid.
17558 */
17559 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017560 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017561 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17562 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017563}
17564
17565/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017566 * xmlSchemaResolveIDCKeyRef:
17567 * @idc: the identity-constraint definition
17568 * @ctxt: the schema parser context
17569 * @name: the attribute name
17570 *
17571 * Resolve keyRef references to key/unique IDCs.
17572 */
17573static void
17574xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017575 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017576 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017577{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017578 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17579 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017580 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017581 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017582 ctxt->schema->idcDef,
17583 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017584 idc->ref->targetNamespace);
17585 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017586 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017587 * TODO: It is actually not an error to fail to resolve.
17588 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589 xmlSchemaPResCompAttrErr(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017590 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017591 (xmlSchemaTypePtr) idc, idc->node,
17592 "refer", idc->ref->name,
17593 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017594 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17595 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017596 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017597 }
17598}
17599
17600/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017601 * xmlSchemaParse:
17602 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017603 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017604 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017605 * XML Shema struture which can be used to validate instances.
17606 * *WARNING* this interface is highly subject to change
17607 *
17608 * Returns the internal XML Schema structure built from the resource or
17609 * NULL in case of error
17610 */
17611xmlSchemaPtr
17612xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17613{
17614 xmlSchemaPtr ret = NULL;
17615 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017616 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017617 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017618
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017619 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017620 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017621 * the API; i.e. not automatically by the validated instance document.
17622 */
17623
Daniel Veillard4255d502002-04-16 15:50:10 +000017624 xmlSchemaInitTypes();
17625
Daniel Veillard6045c902002-10-09 21:13:59 +000017626 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017627 return (NULL);
17628
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017629 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017630 ctxt->counter = 0;
17631 ctxt->container = NULL;
17632
17633 /*
17634 * First step is to parse the input document into an DOM/Infoset
17635 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017636 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017638 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017639 if (doc == NULL) {
17640 xmlSchemaPErr(ctxt, NULL,
17641 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017642 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017643 ctxt->URL, NULL);
17644 return (NULL);
17645 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017646 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017647 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17648 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017649 if (doc == NULL) {
17650 xmlSchemaPErr(ctxt, NULL,
17651 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017652 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017653 NULL, NULL);
17654 return (NULL);
17655 }
17656 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017657 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017658 } else if (ctxt->doc != NULL) {
17659 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017660 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017661 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017662 xmlSchemaPErr(ctxt, NULL,
17663 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017664 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017665 NULL, NULL);
17666 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017667 }
17668
17669 /*
17670 * Then extract the root and Schema parse it
17671 */
17672 root = xmlDocGetRootElement(doc);
17673 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017674 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17675 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017676 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017677 if (!preserve) {
17678 xmlFreeDoc(doc);
17679 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017680 return (NULL);
17681 }
17682
17683 /*
17684 * Remove all the blank text nodes
17685 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017686 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017687
17688 /*
17689 * Then do the parsing for good
17690 */
17691 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017692 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017693 if (!preserve) {
17694 xmlFreeDoc(doc);
17695 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017696 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017697 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017698 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017699 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017700 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017701 ctxt->ctxtType = NULL;
17702 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017704 /*
17705 * Resolve base types of simple/complex types.
17706 */
17707 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017708
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017709 if (ctxt->nberrors != 0)
17710 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017711
17712 if (ret->volatiles != NULL) {
17713 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17714 int i;
17715 xmlSchemaTreeItemPtr item;
17716
17717 for (i = 0; i < list->nbItems; i++) {
17718 item = (xmlSchemaTreeItemPtr) list->items[i];
17719 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17720 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017722 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017723 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017724 * Then fixup all attributes declarations
17725 */
17726 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017727 /*
17728 * Then fixup all attributes group declarations
17729 */
17730 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17731 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017732 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017733 * Resolve identity-constraint keyRefs.
17734 */
17735 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017736 /*
17737 * Check type defnitions for circular references.
17738 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017739 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017740 xmlSchemaCheckTypeDefCircular, ctxt);
17741 /*
17742 * Check model groups defnitions for circular references.
17743 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017744 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017745 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017746 /*
17747 * Set the "term" of particles pointing to model group definitions
17748 * to the contained model group.
17749 */
17750 if (ret->volatiles != NULL) {
17751 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17752 int i;
17753 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017754
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017755 for (i = 0; i < list->nbItems; i++) {
17756 item = (xmlSchemaParticlePtr) list->items[i];
17757 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17758 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17759 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017760 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017761 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017762 * Check attribute groups for circular references.
17763 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017764 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17765 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017766 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017767 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017768 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017769 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017770 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017771 /*
17772 * We will stop here if the schema was not valid to avoid internal errors
17773 * on missing sub-components. This is not conforming to the spec, since it
17774 * allows missing components, but it might make further processing crash.
17775 * So see it as a very strict handling, which might be made more lax in the
17776 * future.
17777 */
17778 if (ctxt->nberrors != 0)
17779 goto exit;
17780 /*
17781 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017782 */
17783 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017784 /*
17785 * Validate the value constraint of attribute declarations/uses.
17786 */
17787 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017788 /*
17789 * Validate the value constraint of element declarations.
17790 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017791 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017792
17793 if (ctxt->nberrors != 0)
17794 goto exit;
17795
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017797 * TODO: cos-element-consistent, cos-all-limited
17798 *
17799 * Then build the content model for all complex types
17800 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017801 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017802 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017803
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017804exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017805 if (ctxt->nberrors != 0) {
17806 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017807 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017808 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017809 return (ret);
17810}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017811
Daniel Veillard4255d502002-04-16 15:50:10 +000017812/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017813 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017814 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017815 * @err: the error callback
17816 * @warn: the warning callback
17817 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017818 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017819 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017820 */
17821void
17822xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017823 xmlSchemaValidityErrorFunc err,
17824 xmlSchemaValidityWarningFunc warn, void *ctx)
17825{
Daniel Veillard4255d502002-04-16 15:50:10 +000017826 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017827 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017828 ctxt->error = err;
17829 ctxt->warning = warn;
17830 ctxt->userData = ctx;
17831}
17832
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017833/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017834 * xmlSchemaGetParserErrors:
17835 * @ctxt: a XMl-Schema parser context
17836 * @err: the error callback result
17837 * @warn: the warning callback result
17838 * @ctx: contextual data for the callbacks result
17839 *
17840 * Get the callback information used to handle errors for a parser context
17841 *
17842 * Returns -1 in case of failure, 0 otherwise
17843 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017844int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017845xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17846 xmlSchemaValidityErrorFunc * err,
17847 xmlSchemaValidityWarningFunc * warn, void **ctx)
17848{
17849 if (ctxt == NULL)
17850 return(-1);
17851 if (err != NULL)
17852 *err = ctxt->error;
17853 if (warn != NULL)
17854 *warn = ctxt->warning;
17855 if (ctx != NULL)
17856 *ctx = ctxt->userData;
17857 return(0);
17858}
17859
17860/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017861 * xmlSchemaFacetTypeToString:
17862 * @type: the facet type
17863 *
17864 * Convert the xmlSchemaTypeType to a char string.
17865 *
17866 * Returns the char string representation of the facet type if the
17867 * type is a facet and an "Internal Error" string otherwise.
17868 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017869static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017870xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17871{
17872 switch (type) {
17873 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017874 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017875 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017876 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017877 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017878 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017879 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017880 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017881 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017882 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017883 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017884 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017885 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017886 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017887 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017888 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017889 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017890 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017891 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017892 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017893 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017894 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017895 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017896 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017897 default:
17898 break;
17899 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017900 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017901}
17902
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017903static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017904xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17905{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017906 /*
17907 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017908 * from xsd:string.
17909 */
17910 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017911 /*
17912 * Note that we assume a whitespace of preserve for anySimpleType.
17913 */
17914 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17915 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17916 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017917 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017918 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017919 else {
17920 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017921 * For all ·atomic· datatypes other than string (and types ·derived·
17922 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017923 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017924 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017926 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017927 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017928 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017929 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017930 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017931 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017932 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17933 } else if (VARIETY_UNION(type)) {
17934 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17935 } else if (VARIETY_ATOMIC(type)) {
17936 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17937 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17938 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17939 return (XML_SCHEMA_WHITESPACE_REPLACE);
17940 else
17941 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017942 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017943 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017944}
17945
Daniel Veillard4255d502002-04-16 15:50:10 +000017946/************************************************************************
17947 * *
17948 * Simple type validation *
17949 * *
17950 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017951
Daniel Veillard4255d502002-04-16 15:50:10 +000017952
17953/************************************************************************
17954 * *
17955 * DOM Validation code *
17956 * *
17957 ************************************************************************/
17958
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017959static void
17960xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17961{
17962 int i, nbItems;
17963 xmlSchemaTypePtr item, *items;
17964
17965
17966 /*
17967 * During the Assemble of the schema ctxt->curItems has
17968 * been filled with the relevant new items. Fix those up.
17969 */
17970 nbItems = ctxt->assemble->nbItems;
17971 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017972
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017973 for (i = 0; i < nbItems; i++) {
17974 item = items[i];
17975 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017976 case XML_SCHEMA_TYPE_COMPLEX:
17977 case XML_SCHEMA_TYPE_SIMPLE:
17978 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
17979 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017980 case XML_SCHEMA_TYPE_ATTRIBUTE:
17981 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17982 break;
17983 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017984 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017985 NULL, NULL, NULL);
17986 break;
17987 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017988 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017989 ctxt, NULL);
17990 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017991 case XML_SCHEMA_TYPE_PARTICLE:
17992 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017993 default:
17994 break;
17995 }
17996 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017997 if (ctxt->nberrors != 0)
17998 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017999 /*
18000 * Circularity checks.
18001 */
18002 for (i = 0; i < nbItems; i++) {
18003 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018004 switch (item->type) {
18005 case XML_SCHEMA_TYPE_COMPLEX:
18006 case XML_SCHEMA_TYPE_SIMPLE:
18007 xmlSchemaCheckTypeDefCircular(
18008 (xmlSchemaTypePtr) item, ctxt, NULL);
18009 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018010 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018011 xmlSchemaCheckGroupDefCircular(
18012 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018013 break;
18014 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18015 xmlSchemaCheckAttributeGroupCircular(
18016 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18017 break;
18018 default:
18019 break;
18020 }
18021 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018022 if (ctxt->nberrors != 0)
18023 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018024 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018025 * Set the "term" of particles pointing to model group definitions
18026 * to the contained model group.
18027 */
18028 for (i = 0; i < nbItems; i++) {
18029 item = items[i];
18030 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18031 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018032 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018033 XML_SCHEMA_TYPE_GROUP)) {
18034 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18035 ctxt, NULL);
18036 }
18037 }
18038 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018039 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018040 */
18041 for (i = 0; i < nbItems; i++) {
18042 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018043 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018044 case XML_SCHEMA_TYPE_SIMPLE:
18045 case XML_SCHEMA_TYPE_COMPLEX:
18046 xmlSchemaTypeFixup(item, ctxt, NULL);
18047 break;
18048 default:
18049 break;
18050 }
18051 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018052 if (ctxt->nberrors != 0)
18053 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018054 /*
18055 * Validate value contraint values.
18056 */
18057 for (i = 0; i < nbItems; i++) {
18058 item = items[i];
18059 switch (item->type) {
18060 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018061 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18062 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018063 break;
18064 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018065 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018066 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018067 break;
18068 default:
18069 break;
18070 }
18071 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018072 if (ctxt->nberrors != 0)
18073 return;
18074 /*
18075 * Build the content model for complex types.
18076 */
18077 for (i = 0; i < nbItems; i++) {
18078 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018079 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018080 case XML_SCHEMA_TYPE_COMPLEX:
18081 xmlSchemaBuildContentModel(item, ctxt, NULL);
18082 break;
18083 default:
18084 break;
18085 }
18086 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018087}
18088
18089/**
18090 * xmlSchemaAssembleByLocation:
18091 * @pctxt: a schema parser context
18092 * @vctxt: a schema validation context
18093 * @schema: the existing schema
18094 * @node: the node that fired the assembling
18095 * @nsName: the namespace name of the new schema
18096 * @location: the location of the schema
18097 *
18098 * Expands an existing schema by an additional schema.
18099 *
18100 * Returns 0 if the new schema is correct, a positive error code
18101 * number otherwise and -1 in case of an internal or API error.
18102 */
18103static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018104xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018105 xmlSchemaPtr schema,
18106 xmlNodePtr node,
18107 const xmlChar *nsName,
18108 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018109{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018110 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018111 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018112 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018113 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018114 xmlSchemaParserCtxtPtr pctxt;
18115
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018116 /*
18117 * This should be used:
18118 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018119 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018120 * 3. if requested via the API
18121 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018122 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018123 return (-1);
18124 /*
18125 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018126 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018127 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018128 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18129 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018130 pctxt = vctxt->pctxt;
18131 /*
18132 * Set the counter to produce unique names for anonymous items.
18133 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018134 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018135 /*
18136 * Acquire the schema document.
18137 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018138 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18139 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018140 if (ret != 0) {
18141 if (doc != NULL)
18142 xmlFreeDoc(doc);
18143 } else if (doc != NULL) {
18144 docElem = xmlDocGetRootElement(doc);
18145 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018146 * Create new assemble info.
18147 */
18148 if (pctxt->assemble == NULL) {
18149 pctxt->assemble = xmlSchemaNewAssemble();
18150 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018151 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018152 "Memory error: xmlSchemaAssembleByLocation, "
18153 "allocating assemble info", NULL);
18154 xmlFreeDoc(doc);
18155 return (-1);
18156 }
18157 }
18158 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018159 * Save and reset the context & schema.
18160 */
18161 oldflags = schema->flags;
18162 oldtns = schema->targetNamespace;
18163 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018164 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018165
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018166 xmlSchemaClearSchemaDefaults(schema);
18167 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018168 if ((targetNs != NULL) &&
18169 xmlStrEqual(targetNs, xmlSchemaNs)) {
18170 /*
18171 * We are parsing the schema for schema!
18172 */
18173 vctxt->pctxt->isS4S = 1;
18174 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018175 /* schema->nbCurItems = 0; */
18176 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018177 pctxt->ctxtType = NULL;
18178 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018179
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018180 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18181 if (pctxt->nberrors != 0) {
18182 vctxt->nberrors += pctxt->nberrors;
18183 goto finally;
18184 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018185 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018186 if (pctxt->nberrors != 0) {
18187 vctxt->nberrors += pctxt->nberrors;
18188 goto finally;
18189 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018190 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018191 if (pctxt->nberrors != 0)
18192 vctxt->nberrors += pctxt->nberrors;
18193finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018194 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018195 * Set the counter of items.
18196 */
18197 schema->counter = pctxt->counter;
18198 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018199 * Free the list of assembled components.
18200 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018201 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018202 /*
18203 * Restore the context & schema.
18204 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018205 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018206 schema->flags = oldflags;
18207 schema->targetNamespace = oldtns;
18208 schema->doc = olddoc;
18209 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018210 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018211 return (ret);
18212}
18213
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018214static xmlSchemaAttrInfoPtr
18215xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18216 int metaType)
18217{
18218 if (vctxt->nbAttrInfos == 0)
18219 return (NULL);
18220 {
18221 int i;
18222 xmlSchemaAttrInfoPtr iattr;
18223
18224 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18225 iattr = vctxt->attrInfos[i];
18226 if (iattr->metaType == metaType)
18227 return (iattr);
18228 }
18229
18230 }
18231 return (NULL);
18232}
18233
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018234/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018235 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018236 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018237 *
18238 * Expands an existing schema by an additional schema using
18239 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18240 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18241 * must be set to 1.
18242 *
18243 * Returns 0 if the new schema is correct, a positive error code
18244 * number otherwise and -1 in case of an internal or API error.
18245 */
18246static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018247xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018248{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 const xmlChar *cur, *end;
18250 const xmlChar *nsname = NULL, *location;
18251 int count = 0;
18252 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018253 xmlSchemaAttrInfoPtr iattr;
18254
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018255 /*
18256 * Parse the value; we will assume an even number of values
18257 * to be given (this is how Xerces and XSV work).
18258 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018259 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18260 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18261 if (iattr == NULL)
18262 xmlSchemaGetMetaAttrInfo(vctxt,
18263 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18264 if (iattr == NULL)
18265 return (0);
18266 cur = iattr->value;
18267 do {
18268 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018269 /*
18270 * Get the namespace name.
18271 */
18272 while (IS_BLANK_CH(*cur))
18273 cur++;
18274 end = cur;
18275 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18276 end++;
18277 if (end == cur)
18278 break;
18279 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018280 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018281 cur = end;
18282 }
18283 /*
18284 * Get the URI.
18285 */
18286 while (IS_BLANK_CH(*cur))
18287 cur++;
18288 end = cur;
18289 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18290 end++;
18291 if (end == cur)
18292 break;
18293 count++;
18294 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018295 cur = end;
18296 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18297 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018298 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018299 VERROR_INT("xmlSchemaAssembleByXSI",
18300 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018301 return (-1);
18302 }
18303 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018304 return (ret);
18305}
18306
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018307#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018308
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018309static const xmlChar *
18310xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18311 const xmlChar *prefix)
18312{
18313 if (vctxt->sax != NULL) {
18314 int i, j;
18315 xmlSchemaNodeInfoPtr inode;
18316
18317 for (i = vctxt->depth; i >= 0; i--) {
18318 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18319 inode = vctxt->elemInfos[i];
18320 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18321 if (((prefix == NULL) &&
18322 (inode->nsBindings[j] == NULL)) ||
18323 ((prefix != NULL) && xmlStrEqual(prefix,
18324 inode->nsBindings[j]))) {
18325
18326 /*
18327 * Note that the namespace bindings are already
18328 * in a string dict.
18329 */
18330 return (inode->nsBindings[j+1]);
18331 }
18332 }
18333 }
18334 }
18335 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018336#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018337 } else if (vctxt->reader != NULL) {
18338 xmlChar *nsName;
18339
18340 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18341 if (nsName != NULL) {
18342 const xmlChar *ret;
18343
18344 VAL_CREATE_DICT;
18345 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18346 xmlFree(nsName);
18347 return (ret);
18348 } else
18349 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018350#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018351 } else {
18352 xmlNsPtr ns;
18353
18354 if ((vctxt->inode->node == NULL) ||
18355 (vctxt->inode->node->doc == NULL)) {
18356 VERROR_INT("xmlSchemaLookupNamespace",
18357 "no node or node's doc avaliable");
18358 return (NULL);
18359 }
18360 ns = xmlSearchNs(vctxt->inode->node->doc,
18361 vctxt->inode->node, prefix);
18362 if (ns != NULL)
18363 return (ns->href);
18364 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018366}
18367
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018368/*
18369* This one works on the schema of the validation context.
18370*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018371static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018372xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18373 xmlSchemaPtr schema,
18374 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018375 const xmlChar *value,
18376 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018377 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018378{
18379 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018380
18381 if (vctxt && (vctxt->schema == NULL)) {
18382 VERROR_INT("xmlSchemaValidateNotation",
18383 "a schema is needed on the validation context");
18384 return (-1);
18385 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018386 ret = xmlValidateQName(value, 1);
18387 if (ret != 0)
18388 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018389 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018390 xmlChar *localName = NULL;
18391 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018392
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018393 localName = xmlSplitQName2(value, &prefix);
18394 if (prefix != NULL) {
18395 const xmlChar *nsName = NULL;
18396
18397 if (vctxt != NULL)
18398 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18399 else if (node != NULL) {
18400 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18401 if (ns != NULL)
18402 nsName = ns->href;
18403 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018404 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018405 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018406 return (1);
18407 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018408 if (nsName == NULL) {
18409 xmlFree(prefix);
18410 xmlFree(localName);
18411 return (1);
18412 }
18413 if (xmlHashLookup2(schema->notaDecl, localName,
18414 nsName) != NULL) {
18415 if (valNeeded && (val != NULL)) {
18416 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18417 BAD_CAST xmlStrdup(nsName));
18418 if (*val == NULL)
18419 ret = -1;
18420 }
18421 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018422 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018423 xmlFree(prefix);
18424 xmlFree(localName);
18425 } else {
18426 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18427 if (valNeeded && (val != NULL)) {
18428 (*val) = xmlSchemaNewNOTATIONValue(
18429 BAD_CAST xmlStrdup(value), NULL);
18430 if (*val == NULL)
18431 ret = -1;
18432 }
18433 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018434 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018435 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018436 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018437 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018438}
18439
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018440/************************************************************************
18441 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018442 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018443 * *
18444 ************************************************************************/
18445
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018446/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018447 * xmlSchemaAugmentIDC:
18448 * @idcDef: the IDC definition
18449 *
18450 * Creates an augmented IDC definition item.
18451 *
18452 * Returns the item, or NULL on internal errors.
18453 */
18454static void
18455xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18456 xmlSchemaValidCtxtPtr vctxt)
18457{
18458 xmlSchemaIDCAugPtr aidc;
18459
18460 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18461 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018462 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018463 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18464 NULL);
18465 return;
18466 }
18467 aidc->bubbleDepth = -1;
18468 aidc->def = idcDef;
18469 aidc->next = NULL;
18470 if (vctxt->aidcs == NULL)
18471 vctxt->aidcs = aidc;
18472 else {
18473 aidc->next = vctxt->aidcs;
18474 vctxt->aidcs = aidc;
18475 }
18476}
18477
18478/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018479 * xmlSchemaIDCNewBinding:
18480 * @idcDef: the IDC definition of this binding
18481 *
18482 * Creates a new IDC binding.
18483 *
18484 * Returns the new binding in case of succeeded, NULL on internal errors.
18485 */
18486static xmlSchemaPSVIIDCBindingPtr
18487xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18488{
18489 xmlSchemaPSVIIDCBindingPtr ret;
18490
18491 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18492 sizeof(xmlSchemaPSVIIDCBinding));
18493 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018494 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018495 "allocating a PSVI IDC binding item", NULL);
18496 return (NULL);
18497 }
18498 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18499 ret->definition = idcDef;
18500 return (ret);
18501}
18502
18503/**
18504 * xmlSchemaIDCStoreNodeTableItem:
18505 * @vctxt: the WXS validation context
18506 * @item: the IDC node table item
18507 *
18508 * The validation context is used to store an IDC node table items.
18509 * They are stored to avoid copying them if IDC node-tables are merged
18510 * with corresponding parent IDC node-tables (bubbling).
18511 *
18512 * Returns 0 if succeeded, -1 on internal errors.
18513 */
18514static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018515xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018516 xmlSchemaPSVIIDCNodePtr item)
18517{
18518 /*
18519 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520 */
18521 if (vctxt->idcNodes == NULL) {
18522 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018523 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18524 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018525 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018526 "allocating the IDC node table item list", NULL);
18527 return (-1);
18528 }
18529 vctxt->sizeIdcNodes = 20;
18530 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18531 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018532 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18533 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018534 sizeof(xmlSchemaPSVIIDCNodePtr));
18535 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018537 "re-allocating the IDC node table item list", NULL);
18538 return (-1);
18539 }
18540 }
18541 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018542
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018543 return (0);
18544}
18545
18546/**
18547 * xmlSchemaIDCStoreKey:
18548 * @vctxt: the WXS validation context
18549 * @item: the IDC key
18550 *
18551 * The validation context is used to store an IDC key.
18552 *
18553 * Returns 0 if succeeded, -1 on internal errors.
18554 */
18555static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018556xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018557 xmlSchemaPSVIIDCKeyPtr key)
18558{
18559 /*
18560 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018561 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018562 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018563 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018564 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18565 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018566 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018567 "allocating the IDC key storage list", NULL);
18568 return (-1);
18569 }
18570 vctxt->sizeIdcKeys = 40;
18571 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18572 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018573 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18574 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018575 sizeof(xmlSchemaPSVIIDCKeyPtr));
18576 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018577 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018578 "re-allocating the IDC key storage list", NULL);
18579 return (-1);
18580 }
18581 }
18582 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018583
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018584 return (0);
18585}
18586
18587/**
18588 * xmlSchemaIDCAppendNodeTableItem:
18589 * @bind: the IDC binding
18590 * @ntItem: the node-table item
18591 *
18592 * Appends the IDC node-table item to the binding.
18593 *
18594 * Returns 0 on success and -1 on internal errors.
18595 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018596static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018597xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18598 xmlSchemaPSVIIDCNodePtr ntItem)
18599{
18600 if (bind->nodeTable == NULL) {
18601 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018602 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018603 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18604 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018605 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018606 "allocating an array of IDC node-table items", NULL);
18607 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018608 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018609 } else if (bind->sizeNodes <= bind->nbNodes) {
18610 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18612 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018613 sizeof(xmlSchemaPSVIIDCNodePtr));
18614 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018615 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018616 "re-allocating an array of IDC node-table items", NULL);
18617 return(-1);
18618 }
18619 }
18620 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018621 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018622}
18623
18624/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018625 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018626 * @vctxt: the WXS validation context
18627 * @matcher: the IDC matcher
18628 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018629 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018630 * of the given matcher. If none found, a new one is created
18631 * and added to the IDC table.
18632 *
18633 * Returns an IDC binding or NULL on internal errors.
18634 */
18635static xmlSchemaPSVIIDCBindingPtr
18636xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18637 xmlSchemaIDCMatcherPtr matcher)
18638{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018639 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018640
18641 info = vctxt->elemInfos[matcher->depth];
18642
18643 if (info->idcTable == NULL) {
18644 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18645 if (info->idcTable == NULL)
18646 return (NULL);
18647 return(info->idcTable);
18648 } else {
18649 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018651 bind = info->idcTable;
18652 do {
18653 if (bind->definition == matcher->aidc->def)
18654 return(bind);
18655 if (bind->next == NULL) {
18656 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18657 if (bind->next == NULL)
18658 return (NULL);
18659 return(bind->next);
18660 }
18661 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018662 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018663 }
18664 return (NULL);
18665}
18666
18667/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018668 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018669 * @key: the IDC key
18670 *
18671 * Frees an IDC key together with its compiled value.
18672 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018673static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018674xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18675{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018676 if (key->val != NULL)
18677 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018678 xmlFree(key);
18679}
18680
18681/**
18682 * xmlSchemaIDCFreeBinding:
18683 *
18684 * Frees an IDC binding. Note that the node table-items
18685 * are not freed.
18686 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018687static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018688xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18689{
18690 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018691 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18692 int i;
18693 /*
18694 * Node-table items for keyrefs are not stored globally
18695 * to the validation context, since they are not bubbled.
18696 * We need to free them here.
18697 */
18698 for (i = 0; i < bind->nbNodes; i++) {
18699 xmlFree(bind->nodeTable[i]->keys);
18700 xmlFree(bind->nodeTable[i]);
18701 }
18702 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018703 xmlFree(bind->nodeTable);
18704 }
18705 xmlFree(bind);
18706}
18707
18708/**
18709 * xmlSchemaIDCFreeIDCTable:
18710 * @bind: the first IDC binding in the list
18711 *
18712 * Frees an IDC table, i.e. all the IDC bindings in the list.
18713 */
18714static void
18715xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18716{
18717 xmlSchemaPSVIIDCBindingPtr prev;
18718
18719 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018720 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018721 bind = bind->next;
18722 xmlSchemaIDCFreeBinding(prev);
18723 }
18724}
18725
18726/**
18727 * xmlSchemaIDCFreeMatcherList:
18728 * @matcher: the first IDC matcher in the list
18729 *
18730 * Frees a list of IDC matchers.
18731 */
18732static void
18733xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18734{
18735 xmlSchemaIDCMatcherPtr next;
18736
18737 while (matcher != NULL) {
18738 next = matcher->next;
18739 if (matcher->keySeqs != NULL) {
18740 int i;
18741 for (i = 0; i < matcher->sizeKeySeqs; i++)
18742 if (matcher->keySeqs[i] != NULL)
18743 xmlFree(matcher->keySeqs[i]);
18744 xmlFree(matcher->keySeqs);
18745 }
18746 xmlFree(matcher);
18747 matcher = next;
18748 }
18749}
18750
18751/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018752 * xmlSchemaIDCAddStateObject:
18753 * @vctxt: the WXS validation context
18754 * @matcher: the IDC matcher
18755 * @sel: the XPath information
18756 * @parent: the parent "selector" state object if any
18757 * @type: "selector" or "field"
18758 *
18759 * Creates/reuses and activates state objects for the given
18760 * XPath information; if the XPath expression consists of unions,
18761 * multiple state objects are created for every unioned expression.
18762 *
18763 * Returns 0 on success and -1 on internal errors.
18764 */
18765static int
18766xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18767 xmlSchemaIDCMatcherPtr matcher,
18768 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018769 int type)
18770{
18771 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018772
18773 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018774 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018775 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018776 if (vctxt->xpathStatePool != NULL) {
18777 sto = vctxt->xpathStatePool;
18778 vctxt->xpathStatePool = sto->next;
18779 sto->next = NULL;
18780 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018781 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018782 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018783 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018784 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18785 if (sto == NULL) {
18786 xmlSchemaVErrMemory(NULL,
18787 "allocating an IDC state object", NULL);
18788 return (-1);
18789 }
18790 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18791 }
18792 /*
18793 * Add to global list.
18794 */
18795 if (vctxt->xpathStates != NULL)
18796 sto->next = vctxt->xpathStates;
18797 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018798
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018799 /*
18800 * Free the old xpath validation context.
18801 */
18802 if (sto->xpathCtxt != NULL)
18803 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18804
18805 /*
18806 * Create a new XPath (pattern) validation context.
18807 */
18808 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18809 (xmlPatternPtr) sel->xpathComp);
18810 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018811 VERROR_INT("xmlSchemaIDCAddStateObject",
18812 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018813 return (-1);
18814 }
18815 sto->type = type;
18816 sto->depth = vctxt->depth;
18817 sto->matcher = matcher;
18818 sto->sel = sel;
18819 sto->nbHistory = 0;
18820
18821#if DEBUG_IDC
18822 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18823 sto->sel->xpath);
18824#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018825 return (0);
18826}
18827
18828/**
18829 * xmlSchemaXPathEvaluate:
18830 * @vctxt: the WXS validation context
18831 * @nodeType: the nodeType of the current node
18832 *
18833 * Evaluates all active XPath state objects.
18834 *
18835 * Returns the number of IC "field" state objects which resolved to
18836 * this node, 0 if none resolved and -1 on internal errors.
18837 */
18838static int
18839xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018840 xmlElementType nodeType)
18841{
18842 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018843 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018844
18845 if (vctxt->xpathStates == NULL)
18846 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018847
18848 if (nodeType == XML_ATTRIBUTE_NODE)
18849 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018850#if DEBUG_IDC
18851 {
18852 xmlChar *str = NULL;
18853 xmlGenericError(xmlGenericErrorContext,
18854 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018855 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18856 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018857 FREE_AND_NULL(str)
18858 }
18859#endif
18860 /*
18861 * Process all active XPath state objects.
18862 */
18863 first = vctxt->xpathStates;
18864 sto = first;
18865 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018866#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018867 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018868 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18869 sto->matcher->aidc->def->name, sto->sel->xpath);
18870 else
18871 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18872 sto->matcher->aidc->def->name, sto->sel->xpath);
18873#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018874 if (nodeType == XML_ELEMENT_NODE)
18875 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018876 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018877 else
18878 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018879 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018880
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018881 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018882 VERROR_INT("xmlSchemaXPathEvaluate",
18883 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018884 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018885 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018886 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018887 goto next_sto;
18888 /*
18889 * Full match.
18890 */
18891#if DEBUG_IDC
18892 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018893 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018894#endif
18895 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018896 * Register a match in the state object history.
18897 */
18898 if (sto->history == NULL) {
18899 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18900 if (sto->history == NULL) {
18901 xmlSchemaVErrMemory(NULL,
18902 "allocating the state object history", NULL);
18903 return(-1);
18904 }
18905 sto->sizeHistory = 10;
18906 } else if (sto->sizeHistory <= sto->nbHistory) {
18907 sto->sizeHistory *= 2;
18908 sto->history = (int *) xmlRealloc(sto->history,
18909 sto->sizeHistory * sizeof(int));
18910 if (sto->history == NULL) {
18911 xmlSchemaVErrMemory(NULL,
18912 "re-allocating the state object history", NULL);
18913 return(-1);
18914 }
18915 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018916 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018917
18918#ifdef DEBUG_IDC
18919 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18920 vctxt->depth);
18921#endif
18922
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018923 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18924 xmlSchemaIDCSelectPtr sel;
18925 /*
18926 * Activate state objects for the IDC fields of
18927 * the IDC selector.
18928 */
18929#if DEBUG_IDC
18930 xmlGenericError(xmlGenericErrorContext, "IDC: "
18931 "activating field states\n");
18932#endif
18933 sel = sto->matcher->aidc->def->fields;
18934 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018935 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18936 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18937 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018938 sel = sel->next;
18939 }
18940 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18941 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018942 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018943 */
18944#if DEBUG_IDC
18945 xmlGenericError(xmlGenericErrorContext,
18946 "IDC: key found\n");
18947#endif
18948 /*
18949 * Notify that the character value of this node is
18950 * needed.
18951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018952 if (resolved == 0) {
18953 if ((vctxt->inode->flags &
18954 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
18955 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
18956 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018957 resolved++;
18958 }
18959next_sto:
18960 if (sto->next == NULL) {
18961 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018962 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018963 */
18964 head = first;
18965 sto = vctxt->xpathStates;
18966 } else
18967 sto = sto->next;
18968 }
18969 return (resolved);
18970}
18971
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018972static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018973xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018974 xmlChar **buf,
18975 xmlSchemaPSVIIDCKeyPtr *seq,
18976 int count)
18977{
18978 int i, res;
18979 const xmlChar *value = NULL;
18980
18981 *buf = xmlStrdup(BAD_CAST "[");
18982 for (i = 0; i < count; i++) {
18983 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018984 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
18985 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018986 if (res == 0)
18987 *buf = xmlStrcat(*buf, value);
18988 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018989 VERROR_INT("xmlSchemaFormatIDCKeySequence",
18990 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000018991 *buf = xmlStrcat(*buf, BAD_CAST "???");
18992 }
18993 if (i < count -1)
18994 *buf = xmlStrcat(*buf, BAD_CAST "', ");
18995 else
18996 *buf = xmlStrcat(*buf, BAD_CAST "'");
18997 if (value != NULL) {
18998 xmlFree((xmlChar *) value);
18999 value = NULL;
19000 }
19001 }
19002 *buf = xmlStrcat(*buf, BAD_CAST "]");
19003
19004 return (BAD_CAST *buf);
19005}
19006
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019007/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019008 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019009 * @vctxt: the WXS validation context
19010 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019011 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019012 *
19013 * Processes and pops the history items of the IDC state objects.
19014 * IDC key-sequences are validated/created on IDC bindings.
19015 *
19016 * Returns 0 on success and -1 on internal errors.
19017 */
19018static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019019xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019020 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019021{
19022 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019023 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019024 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019025 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019026
19027 if (vctxt->xpathStates == NULL)
19028 return (0);
19029 sto = vctxt->xpathStates;
19030
19031#if DEBUG_IDC
19032 {
19033 xmlChar *str = NULL;
19034 xmlGenericError(xmlGenericErrorContext,
19035 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019036 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19037 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019038 FREE_AND_NULL(str)
19039 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019040#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019041 /*
19042 * Evaluate the state objects.
19043 */
19044 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019045 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19046 if (res == -1) {
19047 VERROR_INT("xmlSchemaXPathProcessHistory",
19048 "calling xmlStreamPop()");
19049 return (-1);
19050 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019051#if DEBUG_IDC
19052 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19053 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019054#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019055 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019056 goto deregister_check;
19057
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019058 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019059
19060 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019061 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019062 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019063 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019064 sto = sto->next;
19065 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019066 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019067 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19068 if (! IS_SIMPLE_TYPE(type)) {
19069 /*
19070 * Not qualified if the field resolves to a node of non
19071 * simple type.
19072 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019073 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19074 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019075 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19076 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019077 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019078
19079 sto->nbHistory--;
19080 goto deregister_check;
19081 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019082 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019083 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019084 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019085 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019086 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019087 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019088 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19089 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019090 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019091 sto->nbHistory--;
19092 goto deregister_check;
19093 } else {
19094 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19095 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019096 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019097
19098 /*
19099 * The key will be anchored on the matcher's list of
19100 * key-sequences. The position in this list is determined
19101 * by the target node's depth relative to the matcher's
19102 * depth of creation (i.e. the depth of the scope element).
19103 */
19104 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019105 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019106
19107 /*
19108 * Create/grow the array of key-sequences.
19109 */
19110 if (matcher->keySeqs == NULL) {
19111 if (pos > 9)
19112 matcher->sizeKeySeqs = pos * 2;
19113 else
19114 matcher->sizeKeySeqs = 10;
19115 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19116 xmlMalloc(matcher->sizeKeySeqs *
19117 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19118 if (matcher->keySeqs == NULL) {
19119 xmlSchemaVErrMemory(NULL,
19120 "allocating an array of key-sequences",
19121 NULL);
19122 return(-1);
19123 }
19124 memset(matcher->keySeqs, 0,
19125 matcher->sizeKeySeqs *
19126 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19127 } else if (pos >= matcher->sizeKeySeqs) {
19128 int i = matcher->sizeKeySeqs;
19129
19130 matcher->sizeKeySeqs *= 2;
19131 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19132 xmlRealloc(matcher->keySeqs,
19133 matcher->sizeKeySeqs *
19134 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019135 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019136 xmlSchemaVErrMemory(NULL,
19137 "reallocating an array of key-sequences",
19138 NULL);
19139 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019140 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019141 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019142 * The array needs to be NULLed.
19143 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019144 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019145 for (; i < matcher->sizeKeySeqs; i++)
19146 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019147 }
19148
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019149 /*
19150 * Get/create the key-sequence.
19151 */
19152 keySeq = matcher->keySeqs[pos];
19153 if (keySeq == NULL) {
19154 goto create_sequence;
19155 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019156 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019157 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019158 * cvc-identity-constraint:
19159 * 3 For each node in the ·target node set· all
19160 * of the {fields}, with that node as the context
19161 * node, evaluate to either an empty node-set or
19162 * a node-set with exactly one member, which must
19163 * have a simple type.
19164 *
19165 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019166 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019167 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19168 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019169 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019170 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019171 "with more than one member",
19172 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019173 sto->nbHistory--;
19174 goto deregister_check;
19175 } else {
19176 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019177 }
19178 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019179
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019180create_sequence:
19181 /*
19182 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019183 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019184 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19185 matcher->aidc->def->nbFields *
19186 sizeof(xmlSchemaPSVIIDCKeyPtr));
19187 if (keySeq == NULL) {
19188 xmlSchemaVErrMemory(NULL,
19189 "allocating an IDC key-sequence", NULL);
19190 return(-1);
19191 }
19192 memset(keySeq, 0, matcher->aidc->def->nbFields *
19193 sizeof(xmlSchemaPSVIIDCKeyPtr));
19194 matcher->keySeqs[pos] = keySeq;
19195create_key:
19196 /*
19197 * Created a key once per node only.
19198 */
19199 if (key == NULL) {
19200 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19201 sizeof(xmlSchemaPSVIIDCKey));
19202 if (key == NULL) {
19203 xmlSchemaVErrMemory(NULL,
19204 "allocating a IDC key", NULL);
19205 xmlFree(keySeq);
19206 matcher->keySeqs[pos] = NULL;
19207 return(-1);
19208 }
19209 /*
19210 * Consume the compiled value.
19211 */
19212 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019213 key->val = vctxt->inode->val;
19214 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019215 /*
19216 * Store the key in a global list.
19217 */
19218 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19219 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019220 return (-1);
19221 }
19222 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019223 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019224 }
19225 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019226
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019227 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19228 xmlSchemaPSVIIDCBindingPtr bind;
19229 xmlSchemaPSVIIDCNodePtr ntItem;
19230 xmlSchemaIDCMatcherPtr matcher;
19231 xmlSchemaIDCPtr idc;
19232 int pos, i, j, nbKeys;
19233 /*
19234 * Here we have the following scenario:
19235 * An IDC 'selector' state object resolved to a target node,
19236 * during the time this target node was in the
19237 * ancestor-or-self axis, the 'field' state object(s) looked
19238 * out for matching nodes to create a key-sequence for this
19239 * target node. Now we are back to this target node and need
19240 * to put the key-sequence, together with the target node
19241 * itself, into the node-table of the corresponding IDC
19242 * binding.
19243 */
19244 matcher = sto->matcher;
19245 idc = matcher->aidc->def;
19246 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019247 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019248 /*
19249 * Check if the matcher has any key-sequences at all, plus
19250 * if it has a key-sequence for the current target node.
19251 */
19252 if ((matcher->keySeqs == NULL) ||
19253 (matcher->sizeKeySeqs <= pos)) {
19254 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19255 goto selector_key_error;
19256 else
19257 goto selector_leave;
19258 }
19259
19260 keySeq = &(matcher->keySeqs[pos]);
19261 if (*keySeq == NULL) {
19262 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19263 goto selector_key_error;
19264 else
19265 goto selector_leave;
19266 }
19267
19268 for (i = 0; i < nbKeys; i++) {
19269 if ((*keySeq)[i] == NULL) {
19270 /*
19271 * Not qualified, if not all fields did resolve.
19272 */
19273 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19274 /*
19275 * All fields of a "key" IDC must resolve.
19276 */
19277 goto selector_key_error;
19278 }
19279 goto selector_leave;
19280 }
19281 }
19282 /*
19283 * All fields did resolve.
19284 */
19285
19286 /*
19287 * 4.1 If the {identity-constraint category} is unique(/key),
19288 * then no two members of the ·qualified node set· have
19289 * ·key-sequences· whose members are pairwise equal, as
19290 * defined by Equal in [XML Schemas: Datatypes].
19291 *
19292 * Get the IDC binding from the matcher and check for
19293 * duplicate key-sequences.
19294 */
19295 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19296 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19297 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019298 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019299
19300 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019301 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019302 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019303 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019304 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019305 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019306 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019307 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019308 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019309 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019310 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019311 if (res == -1) {
19312 return (-1);
19313 } else if (res == 0)
19314 break;
19315 }
19316 if (res == 1) {
19317 /*
19318 * Duplicate found.
19319 */
19320 break;
19321 }
19322 i++;
19323 } while (i < bind->nbNodes);
19324 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019325 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019326 /*
19327 * TODO: Try to report the key-sequence.
19328 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019329 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19330 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019331 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019332 "Duplicate key-sequence %s",
19333 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19334 (*keySeq), nbKeys), NULL);
19335 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019336 goto selector_leave;
19337 }
19338 }
19339 /*
19340 * Add a node-table item to the IDC binding.
19341 */
19342 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19343 sizeof(xmlSchemaPSVIIDCNode));
19344 if (ntItem == NULL) {
19345 xmlSchemaVErrMemory(NULL,
19346 "allocating an IDC node-table item", NULL);
19347 xmlFree(*keySeq);
19348 *keySeq = NULL;
19349 return(-1);
19350 }
19351 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19352
19353 /*
19354 * Store the node-table item on global list.
19355 */
19356 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19357 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19358 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019359 xmlFree(*keySeq);
19360 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019361 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019362 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019363 }
19364 /*
19365 * Init the node-table item. Consume the key-sequence.
19366 */
19367 ntItem->node = vctxt->node;
19368 ntItem->keys = *keySeq;
19369 *keySeq = NULL;
19370 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19371 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19372 /*
19373 * Free the item, since keyref items won't be
19374 * put on a global list.
19375 */
19376 xmlFree(ntItem->keys);
19377 xmlFree(ntItem);
19378 }
19379 return (-1);
19380 }
19381
19382 goto selector_leave;
19383selector_key_error:
19384 /*
19385 * 4.2.1 (KEY) The ·target node set· and the
19386 * ·qualified node set· are equal, that is, every
19387 * member of the ·target node set· is also a member
19388 * of the ·qualified node set· and vice versa.
19389 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019390 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19391 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019392selector_leave:
19393 /*
19394 * Free the key-sequence if not added to the IDC table.
19395 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019396 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019397 xmlFree(*keySeq);
19398 *keySeq = NULL;
19399 }
19400 } /* if selector */
19401
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019402 sto->nbHistory--;
19403
19404deregister_check:
19405 /*
19406 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019407 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019408 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019409#if DEBUG_IDC
19410 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19411 sto->sel->xpath);
19412#endif
19413 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019414 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019415 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019416 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019417 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019418 nextsto = sto->next;
19419 /*
19420 * Unlink from the list of active XPath state objects.
19421 */
19422 vctxt->xpathStates = sto->next;
19423 sto->next = vctxt->xpathStatePool;
19424 /*
19425 * Link it to the pool of reusable state objects.
19426 */
19427 vctxt->xpathStatePool = sto;
19428 sto = nextsto;
19429 } else
19430 sto = sto->next;
19431 } /* while (sto != NULL) */
19432 return (0);
19433}
19434
19435/**
19436 * xmlSchemaIDCRegisterMatchers:
19437 * @vctxt: the WXS validation context
19438 * @elemDecl: the element declaration
19439 *
19440 * Creates helper objects to evaluate IDC selectors/fields
19441 * successively.
19442 *
19443 * Returns 0 if OK and -1 on internal errors.
19444 */
19445static int
19446xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19447 xmlSchemaElementPtr elemDecl)
19448{
19449 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19450 xmlSchemaIDCPtr idc, refIdc;
19451 xmlSchemaIDCAugPtr aidc;
19452
19453 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19454 if (idc == NULL)
19455 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019456
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019457#if DEBUG_IDC
19458 {
19459 xmlChar *str = NULL;
19460 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019461 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019462 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19463 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019464 FREE_AND_NULL(str)
19465 }
19466#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019467 if (vctxt->inode->idcMatchers != NULL) {
19468 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19469 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019470 return (-1);
19471 }
19472 do {
19473 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19474 /*
19475 * Since IDCs bubbles are expensive we need to know the
19476 * depth at which the bubbles should stop; this will be
19477 * the depth of the top-most keyref IDC. If no keyref
19478 * references a key/unique IDC, the bubbleDepth will
19479 * be -1, indicating that no bubbles are needed.
19480 */
19481 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19482 if (refIdc != NULL) {
19483 /*
19484 * Lookup the augmented IDC.
19485 */
19486 aidc = vctxt->aidcs;
19487 while (aidc != NULL) {
19488 if (aidc->def == refIdc)
19489 break;
19490 aidc = aidc->next;
19491 }
19492 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019493 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019494 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019495 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019496 return (-1);
19497 }
19498 if ((aidc->bubbleDepth == -1) ||
19499 (vctxt->depth < aidc->bubbleDepth))
19500 aidc->bubbleDepth = vctxt->depth;
19501 }
19502 }
19503 /*
19504 * Lookup the augmented IDC item for the IDC definition.
19505 */
19506 aidc = vctxt->aidcs;
19507 while (aidc != NULL) {
19508 if (aidc->def == idc)
19509 break;
19510 aidc = aidc->next;
19511 }
19512 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019513 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19514 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019515 return (-1);
19516 }
19517 /*
19518 * Create an IDC matcher for every IDC definition.
19519 */
19520 matcher = (xmlSchemaIDCMatcherPtr)
19521 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19522 if (matcher == NULL) {
19523 xmlSchemaVErrMemory(vctxt,
19524 "allocating an IDC matcher", NULL);
19525 return (-1);
19526 }
19527 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19528 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019529 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019530 else
19531 last->next = matcher;
19532 last = matcher;
19533
19534 matcher->type = IDC_MATCHER;
19535 matcher->depth = vctxt->depth;
19536 matcher->aidc = aidc;
19537#if DEBUG_IDC
19538 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19539#endif
19540 /*
19541 * Init the automaton state object.
19542 */
19543 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019544 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019545 return (-1);
19546
19547 idc = idc->next;
19548 } while (idc != NULL);
19549 return (0);
19550}
19551
19552/**
19553 * xmlSchemaBubbleIDCNodeTables:
19554 * @depth: the current tree depth
19555 *
19556 * Merges IDC bindings of an element at @depth into the corresponding IDC
19557 * bindings of its parent element. If a duplicate note-table entry is found,
19558 * both, the parent node-table entry and child entry are discarded from the
19559 * node-table of the parent.
19560 *
19561 * Returns 0 if OK and -1 on internal errors.
19562 */
19563static int
19564xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19565{
19566 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019567 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19568 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019569 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19570 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019571 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019572 int duplTop;
19573
19574 /*
19575 * The node table has the following sections:
19576 *
19577 * O --> old node-table entries (first)
19578 * O
19579 * + --> new node-table entries
19580 * +
19581 * % --> new duplicate node-table entries
19582 * %
19583 * # --> old duplicate node-table entries
19584 * # (last)
19585 *
19586 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019587 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019588 if (bind == NULL) {
19589 /* Fine, no table, no bubbles. */
19590 return (0);
19591 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019592
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019593 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19594 /*
19595 * Walk all bindings; create new or add to existing bindings.
19596 * Remove duplicate key-sequences.
19597 */
19598start_binding:
19599 while (bind != NULL) {
19600 /*
19601 * Skip keyref IDCs.
19602 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019603 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19604 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019605 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019606 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019607 /*
19608 * Check if the key/unique IDC table needs to be bubbled.
19609 */
19610 aidc = vctxt->aidcs;
19611 do {
19612 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019613 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019614 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019615 bind = bind->next;
19616 goto start_binding;
19617 }
19618 break;
19619 }
19620 aidc = aidc->next;
19621 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019622
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019623 if (parTable != NULL)
19624 parBind = *parTable;
19625 while (parBind != NULL) {
19626 /*
19627 * Search a matching parent binding for the
19628 * IDC definition.
19629 */
19630 if (parBind->definition == bind->definition) {
19631
19632 /*
19633 * Compare every node-table entry of the child node,
19634 * i.e. the key-sequence within, ...
19635 */
19636 oldNum = parBind->nbNodes; /* Skip newly added items. */
19637 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019638 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019639
19640 for (i = 0; i < bind->nbNodes; i++) {
19641 node = bind->nodeTable[i];
19642 if (node == NULL)
19643 continue;
19644 /*
19645 * ...with every key-sequence of the parent node, already
19646 * evaluated to be a duplicate key-sequence.
19647 */
19648 if (parBind->nbDupls != 0) {
19649 j = bind->nbNodes + newDupls;
19650 while (j < duplTop) {
19651 parNode = parBind->nodeTable[j];
19652 for (k = 0; k < bind->definition->nbFields; k++) {
19653 key = node->keys[k];
19654 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019655 ret = xmlSchemaAreValuesEqual(key->val,
19656 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019657 if (ret == -1) {
19658 /* TODO: Internal error */
19659 return(-1);
19660 } else if (ret == 0)
19661 break;
19662
19663 }
19664 if (ret == 1)
19665 /* Duplicate found. */
19666 break;
19667 j++;
19668 }
19669 if (j != duplTop) {
19670 /* Duplicate found. */
19671 continue;
19672 }
19673 }
19674 /*
19675 * ... and with every key-sequence of the parent node.
19676 */
19677 j = 0;
19678 while (j < oldNum) {
19679 parNode = parBind->nodeTable[j];
19680 /*
19681 * Compare key by key.
19682 */
19683 for (k = 0; k < parBind->definition->nbFields; k++) {
19684 key = node->keys[k];
19685 parKey = parNode->keys[k];
19686
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019687 ret = xmlSchemaAreValuesEqual(key->val,
19688 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019689 if (ret == -1) {
19690 /* TODO: Internal error */
19691 } else if (ret == 0)
19692 break;
19693
19694 }
19695 if (ret == 1)
19696 /*
19697 * The key-sequences are equal.
19698 */
19699 break;
19700 j++;
19701 }
19702 if (j != oldNum) {
19703 /*
19704 * Handle duplicates.
19705 */
19706 newDupls++;
19707 oldNum--;
19708 parBind->nbNodes--;
19709 /*
19710 * Move last old item to pos of duplicate.
19711 */
19712 parBind->nodeTable[j] =
19713 parBind->nodeTable[oldNum];
19714
19715 if (parBind->nbNodes != oldNum) {
19716 /*
19717 * If new items exist, move last new item to
19718 * last of old items.
19719 */
19720 parBind->nodeTable[oldNum] =
19721 parBind->nodeTable[parBind->nbNodes];
19722 }
19723 /*
19724 * Move duplicate to last pos of new/old items.
19725 */
19726 parBind->nodeTable[parBind->nbNodes] = parNode;
19727
19728 } else {
19729 /*
19730 * Add the node-table entry (node and key-sequence) of
19731 * the child node to the node table of the parent node.
19732 */
19733 if (parBind->nodeTable == NULL) {
19734 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019735 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019736 if (parBind->nodeTable == NULL) {
19737 xmlSchemaVErrMemory(NULL,
19738 "allocating IDC list of node-table items", NULL);
19739 return(-1);
19740 }
19741 parBind->sizeNodes = 1;
19742 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019743 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019744 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19745 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19746 sizeof(xmlSchemaPSVIIDCNodePtr));
19747 if (parBind->nodeTable == NULL) {
19748 xmlSchemaVErrMemory(NULL,
19749 "re-allocating IDC list of node-table items", NULL);
19750 return(-1);
19751 }
19752 }
19753
19754 /*
19755 * Move first old duplicate to last position
19756 * of old duplicates +1.
19757 */
19758 if (parBind->nbDupls != 0) {
19759 parBind->nodeTable[duplTop] =
19760 parBind->nodeTable[parBind->nbNodes + newDupls];
19761 }
19762 /*
19763 * Move first new duplicate to last position of
19764 * new duplicates +1.
19765 */
19766 if (newDupls != 0) {
19767 parBind->nodeTable[parBind->nbNodes + newDupls] =
19768 parBind->nodeTable[parBind->nbNodes];
19769 }
19770 /*
19771 * Append the new node-table entry to the 'new node-table
19772 * entries' section.
19773 */
19774 parBind->nodeTable[parBind->nbNodes] = node;
19775 parBind->nbNodes++;
19776 duplTop++;
19777 }
19778 }
19779 parBind->nbDupls += newDupls;
19780 break;
19781 }
19782 if (parBind->next == NULL)
19783 lastParBind = parBind;
19784 parBind = parBind->next;
19785 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019786 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019787 /*
19788 * No binding for the IDC was found: create a new one and
19789 * copy all node-tables.
19790 */
19791 parBind = xmlSchemaIDCNewBinding(bind->definition);
19792 if (parBind == NULL)
19793 return(-1);
19794
19795 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19796 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19797 if (parBind->nodeTable == NULL) {
19798 xmlSchemaVErrMemory(NULL,
19799 "allocating an array of IDC node-table items", NULL);
19800 xmlSchemaIDCFreeBinding(parBind);
19801 return(-1);
19802 }
19803 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019804 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019805 memcpy(parBind->nodeTable, bind->nodeTable,
19806 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019807 if (*parTable == NULL)
19808 *parTable = parBind;
19809 else
19810 lastParBind->next = parBind;
19811 }
19812 bind = bind->next;
19813 }
19814 return (0);
19815}
19816
19817/**
19818 * xmlSchemaCheckCVCIDCKeyRef:
19819 * @vctxt: the WXS validation context
19820 * @elemDecl: the element declaration
19821 *
19822 * Check the cvc-idc-keyref constraints.
19823 */
19824static int
19825xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19826{
19827 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19828
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019829 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019830 /*
19831 * Find a keyref.
19832 */
19833 while (refbind != NULL) {
19834 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19835 int i, j, k, res;
19836 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19837 xmlSchemaPSVIIDCKeyPtr refKey, key;
19838
19839 /*
19840 * Find the referred key/unique.
19841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019842 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019843 do {
19844 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19845 bind->definition)
19846 break;
19847 bind = bind->next;
19848 } while (bind != NULL);
19849
19850 /*
19851 * Search for a matching key-sequences.
19852 */
19853 for (i = 0; i < refbind->nbNodes; i++) {
19854 res = 0;
19855 if (bind != NULL) {
19856 refKeys = refbind->nodeTable[i]->keys;
19857 for (j = 0; j < bind->nbNodes; j++) {
19858 keys = bind->nodeTable[j]->keys;
19859 for (k = 0; k < bind->definition->nbFields; k++) {
19860 refKey = refKeys[k];
19861 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019862 res = xmlSchemaAreValuesEqual(key->val,
19863 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019864 if (res == 0)
19865 break;
19866 else if (res == -1) {
19867 return (-1);
19868 }
19869 }
19870 if (res == 1) {
19871 /*
19872 * Match found.
19873 */
19874 break;
19875 }
19876 }
19877 }
19878 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019879 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019880 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019881 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19882 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019883 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019884 "No match found for key-sequence %s of key "
19885 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019886 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019887 refbind->nodeTable[i]->keys,
19888 refbind->definition->nbFields),
19889 xmlSchemaFormatQName(&strB,
19890 refbind->definition->targetNamespace,
19891 refbind->definition->name));
19892 FREE_AND_NULL(str);
19893 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019894 }
19895 }
19896 }
19897 refbind = refbind->next;
19898 }
19899 return (0);
19900}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019901
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019902/************************************************************************
19903 * *
19904 * XML Reader validation code *
19905 * *
19906 ************************************************************************/
19907
19908static xmlSchemaAttrInfoPtr
19909xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019910{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019911 xmlSchemaAttrInfoPtr iattr;
19912 /*
19913 * Grow/create list of attribute infos.
19914 */
19915 if (vctxt->attrInfos == NULL) {
19916 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19917 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19918 vctxt->sizeAttrInfos = 1;
19919 if (vctxt->attrInfos == NULL) {
19920 xmlSchemaVErrMemory(vctxt,
19921 "allocating attribute info list", NULL);
19922 return (NULL);
19923 }
19924 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19925 vctxt->sizeAttrInfos++;
19926 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19927 xmlRealloc(vctxt->attrInfos,
19928 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19929 if (vctxt->attrInfos == NULL) {
19930 xmlSchemaVErrMemory(vctxt,
19931 "re-allocating attribute info list", NULL);
19932 return (NULL);
19933 }
19934 } else {
19935 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19936 if (iattr->localName != NULL) {
19937 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19938 "attr info not cleared");
19939 return (NULL);
19940 }
19941 iattr->nodeType = XML_ATTRIBUTE_NODE;
19942 return (iattr);
19943 }
19944 /*
19945 * Create an attribute info.
19946 */
19947 iattr = (xmlSchemaAttrInfoPtr)
19948 xmlMalloc(sizeof(xmlSchemaAttrInfo));
19949 if (iattr == NULL) {
19950 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
19951 return (NULL);
19952 }
19953 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
19954 iattr->nodeType = XML_ATTRIBUTE_NODE;
19955 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
19956
19957 return (iattr);
19958}
19959
19960static int
19961xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
19962 xmlNodePtr attrNode,
19963 const xmlChar *localName,
19964 const xmlChar *nsName,
19965 int ownedNames,
19966 xmlChar *value,
19967 int ownedValue)
19968{
19969 xmlSchemaAttrInfoPtr attr;
19970
19971 attr = xmlSchemaGetFreshAttrInfo(vctxt);
19972 if (attr == NULL) {
19973 VERROR_INT("xmlSchemaPushAttribute",
19974 "calling xmlSchemaGetFreshAttrInfo()");
19975 return (-1);
19976 }
19977 attr->node = attrNode;
19978 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
19979 attr->localName = localName;
19980 attr->nsName = nsName;
19981 if (ownedNames)
19982 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
19983 /*
19984 * Evaluate if it's an XSI attribute.
19985 */
19986 if (nsName != NULL) {
19987 if (xmlStrEqual(localName, BAD_CAST "nil")) {
19988 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19989 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
19990 }
19991 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
19992 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19993 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
19994 }
19995 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
19996 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
19997 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
19998 }
19999 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20000 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20001 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20002 }
20003 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20004 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20005 }
20006 }
20007 attr->value = value;
20008 if (ownedValue)
20009 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20010 if (attr->metaType != 0)
20011 attr->state = XML_SCHEMAS_ATTR_META;
20012 return (0);
20013}
20014
20015static void
20016xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20017{
20018 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20019 FREE_AND_NULL(ielem->localName);
20020 FREE_AND_NULL(ielem->nsName);
20021 } else {
20022 ielem->localName = NULL;
20023 ielem->nsName = NULL;
20024 }
20025 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20026 FREE_AND_NULL(ielem->value);
20027 } else {
20028 ielem->value = NULL;
20029 }
20030 if (ielem->val != NULL) {
20031 xmlSchemaFreeValue(ielem->val);
20032 ielem->val = NULL;
20033 }
20034 if (ielem->idcMatchers != NULL) {
20035 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20036 ielem->idcMatchers = NULL;
20037 }
20038 if (ielem->idcTable != NULL) {
20039 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20040 ielem->idcTable = NULL;
20041 }
20042 if (ielem->regexCtxt != NULL) {
20043 xmlRegFreeExecCtxt(ielem->regexCtxt);
20044 ielem->regexCtxt = NULL;
20045 }
20046 if (ielem->nsBindings != NULL) {
20047 xmlFree((xmlChar **)ielem->nsBindings);
20048 ielem->nsBindings = NULL;
20049 ielem->nbNsBindings = 0;
20050 ielem->sizeNsBindings = 0;
20051 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020052}
20053
20054/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020055 * xmlSchemaGetFreshElemInfo:
20056 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020057 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020058 * Creates/reuses and initializes the element info item for
20059 * the currect tree depth.
20060 *
20061 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020063static xmlSchemaNodeInfoPtr
20064xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020065{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020066 xmlSchemaNodeInfoPtr info = NULL;
20067
20068 if (vctxt->depth > vctxt->sizeElemInfos) {
20069 VERROR_INT("xmlSchemaGetFreshElemInfo",
20070 "inconsistent depth encountered");
20071 return (NULL);
20072 }
20073 if (vctxt->elemInfos == NULL) {
20074 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20075 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20076 if (vctxt->elemInfos == NULL) {
20077 xmlSchemaVErrMemory(vctxt,
20078 "allocating the element info array", NULL);
20079 return (NULL);
20080 }
20081 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20082 vctxt->sizeElemInfos = 10;
20083 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20084 int i = vctxt->sizeElemInfos;
20085
20086 vctxt->sizeElemInfos *= 2;
20087 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20088 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20089 sizeof(xmlSchemaNodeInfoPtr));
20090 if (vctxt->elemInfos == NULL) {
20091 xmlSchemaVErrMemory(vctxt,
20092 "re-allocating the element info array", NULL);
20093 return (NULL);
20094 }
20095 /*
20096 * We need the new memory to be NULLed.
20097 * TODO: Use memset instead?
20098 */
20099 for (; i < vctxt->sizeElemInfos; i++)
20100 vctxt->elemInfos[i] = NULL;
20101 } else
20102 info = vctxt->elemInfos[vctxt->depth];
20103
20104 if (info == NULL) {
20105 info = (xmlSchemaNodeInfoPtr)
20106 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20107 if (info == NULL) {
20108 xmlSchemaVErrMemory(vctxt,
20109 "allocating an element info", NULL);
20110 return (NULL);
20111 }
20112 vctxt->elemInfos[vctxt->depth] = info;
20113 } else {
20114 if (info->localName != NULL) {
20115 VERROR_INT("xmlSchemaGetFreshElemInfo",
20116 "elem info has not been cleared");
20117 return (NULL);
20118 }
20119 }
20120 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20121 info->nodeType = XML_ELEMENT_NODE;
20122 info->depth = vctxt->depth;
20123
20124 return (info);
20125}
20126
20127#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20128#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20129#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20130
20131static int
20132xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20133 xmlNodePtr node,
20134 xmlSchemaTypePtr type,
20135 xmlSchemaValType valType,
20136 const xmlChar * value,
20137 xmlSchemaValPtr val,
20138 unsigned long length,
20139 int fireErrors)
20140{
20141 int ret, error = 0;
20142
20143 xmlSchemaTypePtr tmpType;
20144 xmlSchemaFacetLinkPtr facetLink;
20145 xmlSchemaFacetPtr facet;
20146 unsigned long len = 0;
20147 xmlSchemaWhitespaceValueType ws;
20148
20149 /*
20150 * In Libxml2, derived built-in types have currently no explicit facets.
20151 */
20152 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020153 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020154
20155 /*
20156 * NOTE: Do not jump away, if the facetSet of the given type is
20157 * empty: until now, "pattern" and "enumeration" facets of the
20158 * *base types* need to be checked as well.
20159 */
20160 if (type->facetSet == NULL)
20161 goto pattern_and_enum;
20162
20163 if (! VARIETY_ATOMIC(type)) {
20164 if (VARIETY_LIST(type))
20165 goto variety_list;
20166 else
20167 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020168 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020169 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020170 * Whitespace handling is only of importance for string-based
20171 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020172 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020173 tmpType = xmlSchemaGetPrimitiveType(type);
20174 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20175 IS_ANY_SIMPLE_TYPE(tmpType)) {
20176 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20177 } else
20178 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20179 /*
20180 * If the value was not computed (for string or
20181 * anySimpleType based types), then use the provided
20182 * type.
20183 */
20184 if (val == NULL)
20185 valType = valType;
20186 else
20187 valType = xmlSchemaGetValType(val);
20188
20189 ret = 0;
20190 for (facetLink = type->facetSet; facetLink != NULL;
20191 facetLink = facetLink->next) {
20192 /*
20193 * Skip the pattern "whiteSpace": it is used to
20194 * format the character content beforehand.
20195 */
20196 switch (facetLink->facet->type) {
20197 case XML_SCHEMA_FACET_WHITESPACE:
20198 case XML_SCHEMA_FACET_PATTERN:
20199 case XML_SCHEMA_FACET_ENUMERATION:
20200 continue;
20201 case XML_SCHEMA_FACET_LENGTH:
20202 case XML_SCHEMA_FACET_MINLENGTH:
20203 case XML_SCHEMA_FACET_MAXLENGTH:
20204 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20205 valType, value, val, &len, ws);
20206 break;
20207 default:
20208 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20209 valType, value, val, ws);
20210 break;
20211 }
20212 if (ret < 0) {
20213 AERROR_INT("xmlSchemaValidateFacets",
20214 "validating against a atomic type facet");
20215 return (-1);
20216 } else if (ret > 0) {
20217 if (fireErrors)
20218 xmlSchemaFacetErr(actxt, ret, node,
20219 value, len, type, facetLink->facet, NULL, NULL, NULL);
20220 else
20221 return (ret);
20222 if (error == 0)
20223 error = ret;
20224 }
20225 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020226 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020227
20228variety_list:
20229 if (! VARIETY_LIST(type))
20230 goto pattern_and_enum;
20231 /*
20232 * "length", "minLength" and "maxLength" of list types.
20233 */
20234 ret = 0;
20235 for (facetLink = type->facetSet; facetLink != NULL;
20236 facetLink = facetLink->next) {
20237
20238 switch (facetLink->facet->type) {
20239 case XML_SCHEMA_FACET_LENGTH:
20240 case XML_SCHEMA_FACET_MINLENGTH:
20241 case XML_SCHEMA_FACET_MAXLENGTH:
20242 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20243 value, length, NULL);
20244 break;
20245 default:
20246 continue;
20247 }
20248 if (ret < 0) {
20249 AERROR_INT("xmlSchemaValidateFacets",
20250 "validating against a list type facet");
20251 return (-1);
20252 } else if (ret > 0) {
20253 if (fireErrors)
20254 xmlSchemaFacetErr(actxt, ret, node,
20255 value, length, type, facetLink->facet, NULL, NULL, NULL);
20256 else
20257 return (ret);
20258 if (error == 0)
20259 error = ret;
20260 }
20261 ret = 0;
20262 }
20263
20264pattern_and_enum:
20265 if (error >= 0) {
20266 int found = 0;
20267 /*
20268 * Process enumerations. Facet values are in the value space
20269 * of the defining type's base type. This seems to be a bug in the
20270 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20271 * Only the first set of enumerations in the ancestor-or-self axis
20272 * is used for validation.
20273 */
20274 ret = 0;
20275 tmpType = type;
20276 do {
20277 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20278 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20279 continue;
20280 found = 1;
20281 ret = xmlSchemaAreValuesEqual(facet->val, val);
20282 if (ret == 1)
20283 break;
20284 else if (ret < 0) {
20285 AERROR_INT("xmlSchemaValidateFacets",
20286 "validating against an enumeration facet");
20287 return (-1);
20288 }
20289 }
20290 if (ret != 0)
20291 break;
20292 tmpType = tmpType->baseType;
20293 } while ((tmpType != NULL) &&
20294 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20295 if (found && (ret == 0)) {
20296 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20297 if (fireErrors) {
20298 xmlSchemaFacetErr(actxt, ret, node,
20299 value, 0, type, NULL, NULL, NULL, NULL);
20300 } else
20301 return (ret);
20302 if (error == 0)
20303 error = ret;
20304 }
20305 }
20306
20307 if (error >= 0) {
20308 int found;
20309 /*
20310 * Process patters. Pattern facets are ORed at type level
20311 * and ANDed if derived. Walk the base type axis.
20312 */
20313 tmpType = type;
20314 facet = NULL;
20315 do {
20316 found = 0;
20317 for (facetLink = tmpType->facetSet; facetLink != NULL;
20318 facetLink = facetLink->next) {
20319 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20320 continue;
20321 found = 1;
20322 /*
20323 * NOTE that for patterns, @value needs to be the
20324 * normalized vaule.
20325 */
20326 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20327 if (ret == 1)
20328 break;
20329 else if (ret < 0) {
20330 AERROR_INT("xmlSchemaValidateFacets",
20331 "validating against a pattern facet");
20332 return (-1);
20333 } else {
20334 /*
20335 * Save the last non-validating facet.
20336 */
20337 facet = facetLink->facet;
20338 }
20339 }
20340 if (found && (ret != 1)) {
20341 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20342 if (fireErrors) {
20343 xmlSchemaFacetErr(actxt, ret, node,
20344 value, 0, type, facet, NULL, NULL, NULL);
20345 } else
20346 return (ret);
20347 if (error == 0)
20348 error = ret;
20349 break;
20350 }
20351 tmpType = tmpType->baseType;
20352 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20353 }
20354
20355 return (error);
20356}
20357
20358static xmlChar *
20359xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20360 const xmlChar *value)
20361{
20362 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20363 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20364 return (xmlSchemaCollapseString(value));
20365 case XML_SCHEMA_WHITESPACE_REPLACE:
20366 return (xmlSchemaWhiteSpaceReplace(value));
20367 default:
20368 return (NULL);
20369 }
20370}
20371
20372static int
20373xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20374 const xmlChar *value,
20375 xmlSchemaValPtr *val,
20376 int valNeeded)
20377{
20378 int ret;
20379 const xmlChar *nsName;
20380 xmlChar *local, *prefix = NULL;
20381
20382 ret = xmlValidateQName(value, 1);
20383 if (ret != 0) {
20384 if (ret == -1) {
20385 VERROR_INT("xmlSchemaValidateQName",
20386 "calling xmlValidateQName()");
20387 return (-1);
20388 }
20389 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20390 }
20391 /*
20392 * NOTE: xmlSplitQName2 will always return a duplicated
20393 * strings.
20394 */
20395 local = xmlSplitQName2(value, &prefix);
20396 if (local == NULL)
20397 local = xmlStrdup(value);
20398 /*
20399 * OPTIMIZE TODO: Use flags for:
20400 * - is there any namespace binding?
20401 * - is there a default namespace?
20402 */
20403 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20404
20405 if (prefix != NULL) {
20406 xmlFree(prefix);
20407 /*
20408 * A namespace must be found if the prefix is
20409 * NOT NULL.
20410 */
20411 if (nsName == NULL) {
20412 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20413 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20414 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20415 "The QName value '%s' has no "
20416 "corresponding namespace declaration in "
20417 "scope", value, NULL);
20418 if (local != NULL)
20419 xmlFree(local);
20420 return (ret);
20421 }
20422 }
20423 if (valNeeded && val) {
20424 if (nsName != NULL)
20425 *val = xmlSchemaNewQNameValue(
20426 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20427 else
20428 *val = xmlSchemaNewQNameValue(NULL,
20429 BAD_CAST local);
20430 } else
20431 xmlFree(local);
20432 return (0);
20433}
20434
20435/*
20436* cvc-simple-type
20437*/
20438static int
20439xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20440 xmlNodePtr node,
20441 xmlSchemaTypePtr type,
20442 const xmlChar *value,
20443 xmlSchemaValPtr *retVal,
20444 int fireErrors,
20445 int normalize,
20446 int isNormalized)
20447{
20448 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20449 xmlSchemaValPtr val = NULL;
20450 xmlSchemaWhitespaceValueType ws;
20451 xmlChar *normValue = NULL;
20452
20453#define NORMALIZE(atype) \
20454 if ((! isNormalized) && \
20455 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20456 normValue = xmlSchemaNormalizeValue(atype, value); \
20457 if (normValue != NULL) \
20458 value = normValue; \
20459 isNormalized = 1; \
20460 }
20461
20462 if ((retVal != NULL) && (*retVal != NULL)) {
20463 xmlSchemaFreeValue(*retVal);
20464 *retVal = NULL;
20465 }
20466 /*
20467 * 3.14.4 Simple Type Definition Validation Rules
20468 * Validation Rule: String Valid
20469 */
20470 /*
20471 * 1 It is schema-valid with respect to that definition as defined
20472 * by Datatype Valid in [XML Schemas: Datatypes].
20473 */
20474 /*
20475 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20476 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20477 * the string must be a ·declared entity name·.
20478 */
20479 /*
20480 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20481 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20482 * then every whitespace-delimited substring of the string must be a ·declared
20483 * entity name·.
20484 */
20485 /*
20486 * 2.3 otherwise no further condition applies.
20487 */
20488 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20489 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020490 if (value == NULL)
20491 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020492 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20493 xmlSchemaTypePtr biType; /* The built-in type. */
20494 /*
20495 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20496 * a literal in the ·lexical space· of {base type definition}"
20497 */
20498 /*
20499 * Whitespace-normalize.
20500 */
20501 NORMALIZE(type);
20502 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20503 /*
20504 * Get the built-in type.
20505 */
20506 biType = type->baseType;
20507 while ((biType != NULL) &&
20508 (biType->type != XML_SCHEMA_TYPE_BASIC))
20509 biType = biType->baseType;
20510
20511 if (biType == NULL) {
20512 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20513 "could not get the built-in type");
20514 goto internal_error;
20515 }
20516 } else
20517 biType = type;
20518 /*
20519 * NOTATIONs need to be processed here, since they need
20520 * to lookup in the hashtable of NOTATION declarations of the schema.
20521 */
20522 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20523 switch (biType->builtInType) {
20524 case XML_SCHEMAS_NOTATION:
20525 ret = xmlSchemaValidateNotation(
20526 (xmlSchemaValidCtxtPtr) actxt,
20527 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20528 NULL, value, &val, valNeeded);
20529 break;
20530 case XML_SCHEMAS_QNAME:
20531 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20532 value, &val, valNeeded);
20533 break;
20534 default:
20535 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20536 if (valNeeded)
20537 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20538 value, &val, NULL);
20539 else
20540 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20541 value, NULL, NULL);
20542 break;
20543 }
20544 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20545 switch (biType->builtInType) {
20546 case XML_SCHEMAS_NOTATION:
20547 ret = xmlSchemaValidateNotation(NULL,
20548 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20549 value, &val, valNeeded);
20550 break;
20551 default:
20552 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20553 if (valNeeded)
20554 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20555 value, &val, node);
20556 else
20557 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20558 value, NULL, node);
20559 break;
20560 }
20561 } else {
20562 /*
20563 * Validation via a public API is not implemented yet.
20564 */
20565 TODO
20566 goto internal_error;
20567 }
20568 if (ret != 0) {
20569 if (ret < 0) {
20570 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20571 "validating against a built-in type");
20572 goto internal_error;
20573 }
20574 if (VARIETY_LIST(type))
20575 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20576 else
20577 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20578 }
20579 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20580 /*
20581 * Check facets.
20582 */
20583 ret = xmlSchemaValidateFacets(actxt, node, type,
20584 (xmlSchemaValType) biType->builtInType, value, val,
20585 0, fireErrors);
20586 if (ret != 0) {
20587 if (ret < 0) {
20588 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20589 "validating facets of atomic simple type");
20590 goto internal_error;
20591 }
20592 if (VARIETY_LIST(type))
20593 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20594 else
20595 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20596 }
20597 }
20598 if (fireErrors && (ret > 0))
20599 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20600 } else if (VARIETY_LIST(type)) {
20601
20602 xmlSchemaTypePtr itemType;
20603 const xmlChar *cur, *end;
20604 xmlChar *tmpValue = NULL;
20605 unsigned long len = 0;
20606 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20607 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20608 * of white space separated tokens, each of which ·match·es a literal
20609 * in the ·lexical space· of {item type definition}
20610 */
20611 /*
20612 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20613 * the list type has an enum or pattern facet.
20614 */
20615 NORMALIZE(type);
20616 /*
20617 * VAL TODO: Optimize validation of empty values.
20618 * VAL TODO: We do not have computed values for lists.
20619 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020620 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020621 cur = value;
20622 do {
20623 while (IS_BLANK_CH(*cur))
20624 cur++;
20625 end = cur;
20626 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20627 end++;
20628 if (end == cur)
20629 break;
20630 tmpValue = xmlStrndup(cur, end - cur);
20631 len++;
20632
20633 if (valNeeded)
20634 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20635 tmpValue, &curVal, fireErrors, 0, 1);
20636 else
20637 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20638 tmpValue, NULL, fireErrors, 0, 1);
20639 FREE_AND_NULL(tmpValue);
20640 if (curVal != NULL) {
20641 /*
20642 * Add to list of computed values.
20643 */
20644 if (val == NULL)
20645 val = curVal;
20646 else
20647 xmlSchemaValueAppend(prevVal, curVal);
20648 prevVal = curVal;
20649 curVal = NULL;
20650 }
20651 if (ret != 0) {
20652 if (ret < 0) {
20653 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20654 "validating an item of list simple type");
20655 goto internal_error;
20656 }
20657 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20658 break;
20659 }
20660 cur = end;
20661 } while (*cur != 0);
20662 FREE_AND_NULL(tmpValue);
20663 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20664 /*
20665 * Apply facets (pattern, enumeration).
20666 */
20667 ret = xmlSchemaValidateFacets(actxt, node, type,
20668 XML_SCHEMAS_UNKNOWN, value, val,
20669 len, fireErrors);
20670 if (ret != 0) {
20671 if (ret < 0) {
20672 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20673 "validating facets of list simple type");
20674 goto internal_error;
20675 }
20676 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20677 }
20678 }
20679 if (fireErrors && (ret > 0)) {
20680 /*
20681 * Report the normalized value.
20682 */
20683 normalize = 1;
20684 NORMALIZE(type);
20685 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20686 }
20687 } else if (VARIETY_UNION(type)) {
20688 xmlSchemaTypeLinkPtr memberLink;
20689 /*
20690 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20691 * not apply directly; however, the normalization behavior of ·union·
20692 * types is controlled by the value of whiteSpace on that one of the
20693 * ·memberTypes· against which the ·union· is successfully validated.
20694 *
20695 * This means that the value is normalized by the first validating
20696 * member type, then the facets of the union type are applied. This
20697 * needs changing of the value!
20698 */
20699
20700 /*
20701 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20702 * literal in the ·lexical space· of at least one member of
20703 * {member type definitions}
20704 */
20705 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20706 if (memberLink == NULL) {
20707 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20708 "union simple type has no member types");
20709 goto internal_error;
20710 }
20711 /*
20712 * Always normalize union type values, since we currently
20713 * cannot store the whitespace information with the value
20714 * itself; otherwise a later value-comparison would be
20715 * not possible.
20716 */
20717 while (memberLink != NULL) {
20718 if (valNeeded)
20719 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20720 memberLink->type, value, &val, 0, 1, 0);
20721 else
20722 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20723 memberLink->type, value, NULL, 0, 1, 0);
20724 if (ret <= 0)
20725 break;
20726 memberLink = memberLink->next;
20727 }
20728 if (ret != 0) {
20729 if (ret < 0) {
20730 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20731 "validating members of union simple type");
20732 goto internal_error;
20733 }
20734 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20735 }
20736 /*
20737 * Apply facets (pattern, enumeration).
20738 */
20739 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20740 /*
20741 * The normalization behavior of ·union· types is controlled by
20742 * the value of whiteSpace on that one of the ·memberTypes·
20743 * against which the ·union· is successfully validated.
20744 */
20745 NORMALIZE(memberLink->type);
20746 ret = xmlSchemaValidateFacets(actxt, node, type,
20747 XML_SCHEMAS_UNKNOWN, value, val,
20748 0, fireErrors);
20749 if (ret != 0) {
20750 if (ret < 0) {
20751 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20752 "validating facets of union simple type");
20753 goto internal_error;
20754 }
20755 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20756 }
20757 }
20758 if (fireErrors && (ret > 0))
20759 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20760 }
20761
20762 if (normValue != NULL)
20763 xmlFree(normValue);
20764 if (ret == 0) {
20765 if (retVal != NULL)
20766 *retVal = val;
20767 else if (val != NULL)
20768 xmlSchemaFreeValue(val);
20769 } else if (val != NULL)
20770 xmlSchemaFreeValue(val);
20771 return (ret);
20772internal_error:
20773 if (normValue != NULL)
20774 xmlFree(normValue);
20775 if (val != NULL)
20776 xmlSchemaFreeValue(val);
20777 return (-1);
20778}
20779
20780static int
20781xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20782 const xmlChar *value,
20783 const xmlChar **nsName,
20784 const xmlChar **localName)
20785{
20786 int ret = 0;
20787
20788 if ((nsName == NULL) || (localName == NULL))
20789 return (-1);
20790 *nsName = NULL;
20791 *localName = NULL;
20792
20793 ret = xmlValidateQName(value, 1);
20794 if (ret == -1)
20795 return (-1);
20796 if (ret > 0) {
20797 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20798 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20799 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20800 return (1);
20801 }
20802 {
20803 xmlChar *local = NULL;
20804 xmlChar *prefix;
20805
20806 /*
20807 * NOTE: xmlSplitQName2 will return a duplicated
20808 * string.
20809 */
20810 local = xmlSplitQName2(value, &prefix);
20811 VAL_CREATE_DICT;
20812 if (local == NULL)
20813 *localName = xmlDictLookup(vctxt->dict, value, -1);
20814 else {
20815 *localName = xmlDictLookup(vctxt->dict, local, -1);
20816 xmlFree(local);
20817 }
20818
20819 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20820
20821 if (prefix != NULL) {
20822 xmlFree(prefix);
20823 /*
20824 * A namespace must be found if the prefix is NOT NULL.
20825 */
20826 if (*nsName == NULL) {
20827 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20828 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20829 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20830 "The QName value '%s' has no "
20831 "corresponding namespace declaration in scope",
20832 value, NULL);
20833 return (2);
20834 }
20835 }
20836 }
20837 return (0);
20838}
20839
20840static int
20841xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20842 xmlSchemaAttrInfoPtr iattr,
20843 xmlSchemaTypePtr *localType,
20844 xmlSchemaElementPtr elemDecl)
20845{
20846 int ret = 0;
20847 /*
20848 * cvc-elt (3.3.4) : (4)
20849 * AND
20850 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20851 * (1.2.1.2.1) - (1.2.1.2.4)
20852 * Handle 'xsi:type'.
20853 */
20854 if (localType == NULL)
20855 return (-1);
20856 *localType = NULL;
20857 if (iattr == NULL)
20858 return (0);
20859 else {
20860 const xmlChar *nsName = NULL, *local = NULL;
20861 /*
20862 * TODO: We should report a *warning* that the type was overriden
20863 * by the instance.
20864 */
20865 ACTIVATE_ATTRIBUTE(iattr);
20866 /*
20867 * (cvc-elt) (3.3.4) : (4.1)
20868 * (cvc-assess-elt) (1.2.1.2.2)
20869 */
20870 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20871 &nsName, &local);
20872 if (ret != 0) {
20873 if (ret < 0) {
20874 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20875 "calling xmlSchemaQNameExpand() to validate the "
20876 "attribute 'xsi:type'");
20877 goto internal_error;
20878 }
20879 goto exit;
20880 }
20881 /*
20882 * (cvc-elt) (3.3.4) : (4.2)
20883 * (cvc-assess-elt) (1.2.1.2.3)
20884 */
20885 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20886 if (*localType == NULL) {
20887 xmlChar *str = NULL;
20888
20889 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20890 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20891 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20892 "The QName value '%s' of the xsi:type attribute does not "
20893 "resolve to a type definition",
20894 xmlSchemaFormatQName(&str, nsName, local), NULL);
20895 FREE_AND_NULL(str);
20896 ret = vctxt->err;
20897 goto exit;
20898 }
20899 if (elemDecl != NULL) {
20900 int set = 0;
20901
20902 /*
20903 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20904 * "The ·local type definition· must be validly
20905 * derived from the {type definition} given the union of
20906 * the {disallowed substitutions} and the {type definition}'s
20907 * {prohibited substitutions}, as defined in
20908 * Type Derivation OK (Complex) (§3.4.6)
20909 * (if it is a complex type definition),
20910 * or given {disallowed substitutions} as defined in Type
20911 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20912 * definition)."
20913 *
20914 * {disallowed substitutions}: the "block" on the element decl.
20915 * {prohibited substitutions}: the "block" on the type def.
20916 */
20917 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20918 (elemDecl->subtypes->flags &
20919 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20920 set |= SUBSET_EXTENSION;
20921
20922 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20923 (elemDecl->subtypes->flags &
20924 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20925 set |= SUBSET_RESTRICTION;
20926
20927 if (xmlSchemaCheckCOSDerivedOK(*localType,
20928 elemDecl->subtypes, set) != 0) {
20929 xmlChar *str = NULL;
20930
20931 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20932 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20933 "The type definition '%s', specified by xsi:type, is "
20934 "blocked or not validly derived from the type definition "
20935 "of the element declaration",
20936 xmlSchemaFormatQName(&str,
20937 (*localType)->targetNamespace,
20938 (*localType)->name),
20939 NULL);
20940 FREE_AND_NULL(str);
20941 ret = vctxt->err;
20942 *localType = NULL;
20943 }
20944 }
20945 }
20946exit:
20947 ACTIVATE_ELEM;
20948 return (ret);
20949internal_error:
20950 ACTIVATE_ELEM;
20951 return (-1);
20952}
20953
20954static int
20955xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
20956{
20957 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
20958 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
20959
20960 /*
20961 * cvc-elt (3.3.4) : 1
20962 */
20963 if (elemDecl == NULL) {
20964 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
20965 "No matching declaration available");
20966 return (vctxt->err);
20967 }
20968 /*
20969 * cvc-elt (3.3.4) : 2
20970 */
20971 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20972 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
20973 "The element declaration is abstract");
20974 return (vctxt->err);
20975 }
20976 if (actualType == NULL) {
20977 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
20978 "The type definition is absent");
20979 return (XML_SCHEMAV_CVC_TYPE_1);
20980 }
20981 if (vctxt->nbAttrInfos != 0) {
20982 int ret;
20983 xmlSchemaAttrInfoPtr iattr;
20984 /*
20985 * cvc-elt (3.3.4) : 3
20986 * Handle 'xsi:nil'.
20987 */
20988 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
20989 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
20990 if (iattr) {
20991 ACTIVATE_ATTRIBUTE(iattr);
20992 /*
20993 * Validate the value.
20994 */
20995 ret = xmlSchemaVCheckCVCSimpleType(
20996 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
20997 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20998 iattr->value, &(iattr->val), 1, 0, 0);
20999 ACTIVATE_ELEM;
21000 if (ret < 0) {
21001 VERROR_INT("xmlSchemaValidateElemDecl",
21002 "calling xmlSchemaVCheckCVCSimpleType() to "
21003 "validate the attribute 'xsi:nil'");
21004 return (-1);
21005 }
21006 if (ret == 0) {
21007 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21008 /*
21009 * cvc-elt (3.3.4) : 3.1
21010 */
21011 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21012 "The element is not 'nillable'");
21013 /* Does not return an error on purpose. */
21014 } else {
21015 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21016 /*
21017 * cvc-elt (3.3.4) : 3.2.2
21018 */
21019 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21020 (elemDecl->value != NULL)) {
21021 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21022 "The element cannot be 'nilled' because "
21023 "there is a fixed value constraint defined "
21024 "for it");
21025 /* Does not return an error on purpose. */
21026 } else
21027 vctxt->inode->flags |=
21028 XML_SCHEMA_ELEM_INFO_NILLED;
21029 }
21030 }
21031 }
21032 }
21033 /*
21034 * cvc-elt (3.3.4) : 4
21035 * Handle 'xsi:type'.
21036 */
21037 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21038 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21039 if (iattr) {
21040 xmlSchemaTypePtr localType = NULL;
21041
21042 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21043 elemDecl);
21044 if (ret != 0) {
21045 if (ret == -1) {
21046 VERROR_INT("xmlSchemaValidateElemDecl",
21047 "calling xmlSchemaProcessXSIType() to "
21048 "process the attribute 'xsi:type'");
21049 return (-1);
21050 }
21051 /* Does not return an error on purpose. */
21052 }
21053 if (localType != NULL) {
21054 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21055 actualType = localType;
21056 }
21057 }
21058 }
21059 /*
21060 * IDC: Register identity-constraint XPath matchers.
21061 */
21062 if ((elemDecl->idcs != NULL) &&
21063 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21064 return (-1);
21065 /*
21066 * No actual type definition.
21067 */
21068 if (actualType == NULL) {
21069 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21070 "The type definition is absent");
21071 return (XML_SCHEMAV_CVC_TYPE_1);
21072 }
21073 /*
21074 * Remember the actual type definition.
21075 */
21076 vctxt->inode->typeDef = actualType;
21077
21078 return (0);
21079}
21080
21081static int
21082xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21083{
21084 xmlSchemaAttrInfoPtr iattr;
21085 int ret = 0, i;
21086
21087 /*
21088 * SPEC cvc-type (3.1.1)
21089 * "The attributes of must be empty, excepting those whose namespace
21090 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21091 * whose local name is one of type, nil, schemaLocation or
21092 * noNamespaceSchemaLocation."
21093 */
21094 if (vctxt->nbAttrInfos == 0)
21095 return (0);
21096 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21097 iattr = vctxt->attrInfos[i];
21098 if (! iattr->metaType) {
21099 ACTIVATE_ATTRIBUTE(iattr)
21100 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21101 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21102 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21103 }
21104 }
21105 ACTIVATE_ELEM
21106 return (ret);
21107}
21108
21109/*
21110* Cleanup currently used attribute infos.
21111*/
21112static void
21113xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21114{
21115 int i;
21116 xmlSchemaAttrInfoPtr attr;
21117
21118 if (vctxt->nbAttrInfos == 0)
21119 return;
21120 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21121 attr = vctxt->attrInfos[i];
21122 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21123 if (attr->localName != NULL)
21124 xmlFree((xmlChar *) attr->localName);
21125 if (attr->nsName != NULL)
21126 xmlFree((xmlChar *) attr->nsName);
21127 }
21128 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21129 if (attr->value != NULL)
21130 xmlFree((xmlChar *) attr->value);
21131 }
21132 if (attr->val != NULL) {
21133 xmlSchemaFreeValue(attr->val);
21134 attr->val = NULL;
21135 }
21136 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21137 }
21138 vctxt->nbAttrInfos = 0;
21139}
21140
21141/*
21142* 3.4.4 Complex Type Definition Validation Rules
21143* Element Locally Valid (Complex Type) (cvc-complex-type)
21144* 3.2.4 Attribute Declaration Validation Rules
21145* Validation Rule: Attribute Locally Valid (cvc-attribute)
21146* Attribute Locally Valid (Use) (cvc-au)
21147*
21148* Only "assessed" attribute information items will be visible to
21149* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21150*/
21151static int
21152xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21153{
21154 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21155 xmlSchemaAttributeLinkPtr attrUseLink;
21156 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21157 xmlSchemaAttrInfoPtr attr, tmpAttr;
21158 int i, found, nbAttrs;
21159 int xpathRes = 0, res, wildIDs = 0, fixed;
21160
21161 /*
21162 * SPEC (cvc-attribute)
21163 * (1) "The declaration must not be ·absent· (see Missing
21164 * Sub-components (§5.3) for how this can fail to be
21165 * the case)."
21166 * (2) "Its {type definition} must not be absent."
21167 *
21168 * NOTE (1) + (2): This is not handled here, since we currently do not
21169 * allow validation against schemas which have missing sub-components.
21170 *
21171 * SPEC (cvc-complex-type)
21172 * (3) "For each attribute information item in the element information
21173 * item's [attributes] excepting those whose [namespace name] is
21174 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21175 * [local name] is one of type, nil, schemaLocation or
21176 * noNamespaceSchemaLocation, the appropriate case among the following
21177 * must be true:
21178 *
21179 */
21180 nbAttrs = vctxt->nbAttrInfos;
21181 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21182 attrUseLink = attrUseLink->next) {
21183
21184 found = 0;
21185 attrUse = attrUseLink->attr;
21186 /*
21187 * VAL TODO: Implement a real "attribute use" component.
21188 */
21189 if (attrUse->refDecl != NULL)
21190 attrDecl = attrUse->refDecl;
21191 else
21192 attrDecl = attrUse;
21193 for (i = 0; i < nbAttrs; i++) {
21194 attr = vctxt->attrInfos[i];
21195 /*
21196 * SPEC (cvc-complex-type) (3)
21197 * Skip meta attributes.
21198 */
21199 if (attr->metaType)
21200 continue;
21201 if (attr->localName[0] != attrDecl->name[0])
21202 continue;
21203 if (!xmlStrEqual(attr->localName, attrDecl->name))
21204 continue;
21205 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21206 continue;
21207 found = 1;
21208 /*
21209 * SPEC (cvc-complex-type)
21210 * (3.1) "If there is among the {attribute uses} an attribute
21211 * use with an {attribute declaration} whose {name} matches
21212 * the attribute information item's [local name] and whose
21213 * {target namespace} is identical to the attribute information
21214 * item's [namespace name] (where an ·absent· {target namespace}
21215 * is taken to be identical to a [namespace name] with no value),
21216 * then the attribute information must be ·valid· with respect
21217 * to that attribute use as per Attribute Locally Valid (Use)
21218 * (§3.5.4). In this case the {attribute declaration} of that
21219 * attribute use is the ·context-determined declaration· for the
21220 * attribute information item with respect to Schema-Validity
21221 * Assessment (Attribute) (§3.2.4) and
21222 * Assessment Outcome (Attribute) (§3.2.5).
21223 */
21224 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21225 attr->use = attrUse;
21226 /*
21227 * Context-determined declaration.
21228 */
21229 attr->decl = attrDecl;
21230 attr->typeDef = attrDecl->subtypes;
21231 break;
21232 }
21233
21234 if (found)
21235 continue;
21236
21237 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21238 /*
21239 * Handle non-existent, required attributes.
21240 *
21241 * SPEC (cvc-complex-type)
21242 * (4) "The {attribute declaration} of each attribute use in
21243 * the {attribute uses} whose {required} is true matches one
21244 * of the attribute information items in the element information
21245 * item's [attributes] as per clause 3.1 above."
21246 */
21247 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21248 if (tmpAttr == NULL) {
21249 VERROR_INT(
21250 "xmlSchemaVAttributesComplex",
21251 "calling xmlSchemaGetFreshAttrInfo()");
21252 return (-1);
21253 }
21254 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21255 tmpAttr->use = attrUse;
21256 tmpAttr->decl = attrDecl;
21257 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21258 ((attrUse->defValue != NULL) ||
21259 (attrDecl->defValue != NULL))) {
21260 /*
21261 * Handle non-existent, optional, default/fixed attributes.
21262 */
21263 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21264 if (tmpAttr == NULL) {
21265 VERROR_INT(
21266 "xmlSchemaVAttributesComplex",
21267 "calling xmlSchemaGetFreshAttrInfo()");
21268 return (-1);
21269 }
21270 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21271 tmpAttr->use = attrUse;
21272 tmpAttr->decl = attrDecl;
21273 tmpAttr->typeDef = attrDecl->subtypes;
21274 tmpAttr->localName = attrDecl->name;
21275 tmpAttr->nsName = attrDecl->targetNamespace;
21276 }
21277 }
21278 if (vctxt->nbAttrInfos == 0)
21279 return (0);
21280 /*
21281 * Validate against the wildcard.
21282 */
21283 if (type->attributeWildcard != NULL) {
21284 /*
21285 * SPEC (cvc-complex-type)
21286 * (3.2.1) "There must be an {attribute wildcard}."
21287 */
21288 for (i = 0; i < nbAttrs; i++) {
21289 attr = vctxt->attrInfos[i];
21290 /*
21291 * SPEC (cvc-complex-type) (3)
21292 * Skip meta attributes.
21293 */
21294 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21295 continue;
21296 /*
21297 * SPEC (cvc-complex-type)
21298 * (3.2.2) "The attribute information item must be ·valid· with
21299 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21300 *
21301 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21302 * "... its [namespace name] must be ·valid· with respect to
21303 * the wildcard constraint, as defined in Wildcard allows
21304 * Namespace Name (§3.10.4)."
21305 */
21306 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21307 attr->nsName)) {
21308 /*
21309 * Handle processContents.
21310 *
21311 * SPEC (cvc-wildcard):
21312 * processContents | context-determined declaration:
21313 * "strict" "mustFind"
21314 * "lax" "none"
21315 * "skip" "skip"
21316 */
21317 if (type->attributeWildcard->processContents ==
21318 XML_SCHEMAS_ANY_SKIP) {
21319 /*
21320 * context-determined declaration = "skip"
21321 *
21322 * SPEC PSVI Assessment Outcome (Attribute)
21323 * [validity] = "notKnown"
21324 * [validation attempted] = "none"
21325 */
21326 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21327 continue;
21328 }
21329 /*
21330 * Find an attribute declaration.
21331 */
21332 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21333 attr->localName, attr->nsName);
21334 if (attr->decl != NULL) {
21335 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21336 /*
21337 * SPEC (cvc-complex-type)
21338 * (5) "Let [Definition:] the wild IDs be the set of
21339 * all attribute information item to which clause 3.2
21340 * applied and whose ·validation· resulted in a
21341 * ·context-determined declaration· of mustFind or no
21342 * ·context-determined declaration· at all, and whose
21343 * [local name] and [namespace name] resolve (as
21344 * defined by QName resolution (Instance) (§3.15.4)) to
21345 * an attribute declaration whose {type definition} is
21346 * or is derived from ID. Then all of the following
21347 * must be true:"
21348 */
21349 attr->typeDef = attr->decl->subtypes;
21350 if (xmlSchemaIsDerivedFromBuiltInType(
21351 attr->typeDef, XML_SCHEMAS_ID)) {
21352 /*
21353 * SPEC (5.1) "There must be no more than one
21354 * item in ·wild IDs·."
21355 */
21356 if (wildIDs != 0) {
21357 /* VAL TODO */
21358 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21359 TODO
21360 continue;
21361 }
21362 wildIDs++;
21363 /*
21364 * SPEC (cvc-complex-type)
21365 * (5.2) "If ·wild IDs· is non-empty, there must not
21366 * be any attribute uses among the {attribute uses}
21367 * whose {attribute declaration}'s {type definition}
21368 * is or is derived from ID."
21369 */
21370 for (attrUseLink = type->attributeUses;
21371 attrUseLink != NULL;
21372 attrUseLink = attrUseLink->next) {
21373 if (xmlSchemaIsDerivedFromBuiltInType(
21374 attrUseLink->attr->subtypes,
21375 XML_SCHEMAS_ID)) {
21376 /* VAL TODO */
21377 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21378 TODO
21379 }
21380 }
21381 }
21382 } else if (type->attributeWildcard->processContents ==
21383 XML_SCHEMAS_ANY_LAX) {
21384 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21385 /*
21386 * SPEC PSVI Assessment Outcome (Attribute)
21387 * [validity] = "notKnown"
21388 * [validation attempted] = "none"
21389 */
21390 } else {
21391 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21392 }
21393 }
21394 }
21395 }
21396
21397
21398 if (vctxt->nbAttrInfos == 0)
21399 return (0);
21400
21401 /*
21402 * Validate values, create default attributes, evaluate IDCs.
21403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021404 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21405 attr = vctxt->attrInfos[i];
21406 /*
21407 * VAL TODO: Note that we won't try to resolve IDCs to
21408 * "lax" and "skip" validated attributes. Check what to
21409 * do in this case.
21410 */
21411 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21412 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21413 continue;
21414 /*
21415 * VAL TODO: What to do if the type definition is missing?
21416 */
21417 if (attr->typeDef == NULL) {
21418 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21419 continue;
21420 }
21421
21422 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021423 fixed = 0;
21424 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021425
21426 if (vctxt->xpathStates != NULL) {
21427 /*
21428 * Evaluate IDCs.
21429 */
21430 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21431 XML_ATTRIBUTE_NODE);
21432 if (xpathRes == -1) {
21433 VERROR_INT("xmlSchemaVAttributesComplex",
21434 "calling xmlSchemaXPathEvaluate()");
21435 goto internal_error;
21436 }
21437 }
21438
21439 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21440 /*
21441 * Default/fixed attributes.
21442 */
21443 if (xpathRes) {
21444 if (attr->use->defValue == NULL) {
21445 attr->value = (xmlChar *) attr->use->defValue;
21446 attr->val = attr->use->defVal;
21447 } else {
21448 attr->value = (xmlChar *) attr->decl->defValue;
21449 attr->val = attr->decl->defVal;
21450 }
21451 /*
21452 * IDCs will consume the precomputed default value,
21453 * so we need to clone it.
21454 */
21455 if (attr->val == NULL) {
21456 VERROR_INT("xmlSchemaVAttributesComplex",
21457 "default/fixed value on an attribute use was "
21458 "not precomputed");
21459 goto internal_error;
21460 }
21461 attr->val = xmlSchemaCopyValue(attr->val);
21462 if (attr->val == NULL) {
21463 VERROR_INT("xmlSchemaVAttributesComplex",
21464 "calling xmlSchemaCopyValue()");
21465 goto internal_error;
21466 }
21467 }
21468 /*
21469 * PSVI: Add the default attribute to the current element.
21470 * VAL TODO: Should we use the *normalized* value? This currently
21471 * uses the *initial* value.
21472 */
21473 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21474 (attr->node != NULL) && (attr->node->doc != NULL)) {
21475 xmlChar *normValue;
21476 const xmlChar *value;
21477
21478 value = attr->value;
21479 /*
21480 * Normalize the value.
21481 */
21482 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21483 attr->value);
21484 if (normValue != NULL)
21485 value = BAD_CAST normValue;
21486
21487 if (attr->nsName == NULL) {
21488 if (xmlNewProp(attr->node->parent,
21489 attr->localName, value) == NULL) {
21490 VERROR_INT("xmlSchemaVAttributesComplex",
21491 "callling xmlNewProp()");
21492 if (normValue != NULL)
21493 xmlFree(normValue);
21494 goto internal_error;
21495 }
21496 } else {
21497 xmlNsPtr ns;
21498
21499 ns = xmlSearchNsByHref(attr->node->doc,
21500 attr->node->parent, attr->nsName);
21501 if (ns == NULL) {
21502 xmlChar prefix[12];
21503 int counter = 0;
21504
21505 /*
21506 * Create a namespace declaration on the validation
21507 * root node if no namespace declaration is in scope.
21508 */
21509 do {
21510 snprintf((char *) prefix, 12, "p%d", counter++);
21511 ns = xmlSearchNs(attr->node->doc,
21512 attr->node->parent, BAD_CAST prefix);
21513 if (counter > 1000) {
21514 VERROR_INT(
21515 "xmlSchemaVAttributesComplex",
21516 "could not compute a ns prefix for a "
21517 "default/fixed attribute");
21518 if (normValue != NULL)
21519 xmlFree(normValue);
21520 goto internal_error;
21521 }
21522 } while (ns != NULL);
21523 ns = xmlNewNs(vctxt->validationRoot,
21524 attr->nsName, BAD_CAST prefix);
21525 }
21526 xmlNewNsProp(attr->node->parent, ns,
21527 attr->localName, value);
21528 }
21529 if (normValue != NULL)
21530 xmlFree(normValue);
21531 }
21532 /*
21533 * Go directly to IDC evaluation.
21534 */
21535 goto eval_idcs;
21536 }
21537 /*
21538 * Validate the value.
21539 */
21540 if (vctxt->value != NULL) {
21541 /*
21542 * Free last computed value; just for safety reasons.
21543 */
21544 xmlSchemaFreeValue(vctxt->value);
21545 vctxt->value = NULL;
21546 }
21547 /*
21548 * Note that the attribute *use* can be unavailable, if
21549 * the attribute was a wild attribute.
21550 */
21551 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21552 ((attr->use != NULL) &&
21553 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21554 fixed = 1;
21555 else
21556 fixed = 0;
21557 /*
21558 * SPEC (cvc-attribute)
21559 * (3) "The item's ·normalized value· must be locally ·valid·
21560 * with respect to that {type definition} as per
21561 * String Valid (§3.14.4)."
21562 *
21563 * VAL TODO: Do we already have the
21564 * "normalized attribute value" here?
21565 */
21566 if (xpathRes || fixed) {
21567 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21568 /*
21569 * Request a computed value.
21570 */
21571 res = xmlSchemaVCheckCVCSimpleType(
21572 (xmlSchemaAbstractCtxtPtr) vctxt,
21573 attr->node, attr->typeDef, attr->value, &(attr->val),
21574 1, 1, 0);
21575 } else {
21576 res = xmlSchemaVCheckCVCSimpleType(
21577 (xmlSchemaAbstractCtxtPtr) vctxt,
21578 attr->node, attr->typeDef, attr->value, NULL,
21579 1, 0, 0);
21580 }
21581
21582 if (res != 0) {
21583 if (res == -1) {
21584 VERROR_INT("xmlSchemaVAttributesComplex",
21585 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21586 goto internal_error;
21587 }
21588 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21589 /*
21590 * SPEC PSVI Assessment Outcome (Attribute)
21591 * [validity] = "invalid"
21592 */
21593 goto eval_idcs;
21594 }
21595
21596 if (fixed) {
21597 int ws;
21598 /*
21599 * SPEC Attribute Locally Valid (Use) (cvc-au)
21600 * "For an attribute information item to be·valid·
21601 * with respect to an attribute use its *normalized*
21602 * value· must match the *canonical* lexical
21603 * representation of the attribute use's {value
21604 * constraint}value, if it is present and fixed."
21605 *
21606 * VAL TODO: The requirement for the *canonical* value
21607 * will be removed in XML Schema 1.1.
21608 */
21609 /*
21610 * SPEC Attribute Locally Valid (cvc-attribute)
21611 * (4) "The item's *actual* value· must match the *value* of
21612 * the {value constraint}, if it is present and fixed."
21613 */
21614 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21615 if (attr->val == NULL) {
21616 /* VAL TODO: A value was not precomputed. */
21617 TODO
21618 goto eval_idcs;
21619 }
21620 if ((attr->use != NULL) &&
21621 (attr->use->defValue != NULL)) {
21622 if (attr->use->defVal == NULL) {
21623 /* VAL TODO: A default value was not precomputed. */
21624 TODO
21625 goto eval_idcs;
21626 }
21627 attr->vcValue = attr->use->defValue;
21628 /*
21629 if (xmlSchemaCompareValuesWhtsp(attr->val,
21630 (xmlSchemaWhitespaceValueType) ws,
21631 attr->use->defVal,
21632 (xmlSchemaWhitespaceValueType) ws) != 0) {
21633 */
21634 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21635 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21636 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021637 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021638 /* VAL TODO: A default value was not precomputed. */
21639 TODO
21640 goto eval_idcs;
21641 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021642 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021643 /*
21644 if (xmlSchemaCompareValuesWhtsp(attr->val,
21645 (xmlSchemaWhitespaceValueType) ws,
21646 attrDecl->defVal,
21647 (xmlSchemaWhitespaceValueType) ws) != 0) {
21648 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021649 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021650 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21651 }
21652 /*
21653 * [validity] = "valid"
21654 */
21655 }
21656eval_idcs:
21657 /*
21658 * Evaluate IDCs.
21659 */
21660 if (xpathRes) {
21661 if (xmlSchemaXPathProcessHistory(vctxt,
21662 vctxt->depth +1) == -1) {
21663 VERROR_INT("xmlSchemaVAttributesComplex",
21664 "calling xmlSchemaXPathEvaluate()");
21665 goto internal_error;
21666 }
21667 }
21668 }
21669
21670 /*
21671 * Report errors.
21672 */
21673 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21674 attr = vctxt->attrInfos[i];
21675 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21676 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21677 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21678 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21679 continue;
21680 ACTIVATE_ATTRIBUTE(attr);
21681 switch (attr->state) {
21682 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21683 xmlChar *str = NULL;
21684 ACTIVATE_ELEM;
21685 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21686 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21687 "The attribute '%s' is required but missing",
21688 xmlSchemaFormatQName(&str,
21689 attr->decl->targetNamespace,
21690 attr->decl->name),
21691 NULL);
21692 FREE_AND_NULL(str)
21693 break;
21694 }
21695 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21696 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21697 "The type definition is absent");
21698 break;
21699 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21700 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21701 XML_SCHEMAV_CVC_AU, NULL, NULL,
21702 "The value '%s' does not match the fixed "
21703 "value constraint '%s'",
21704 attr->value, attr->vcValue);
21705 break;
21706 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21707 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21708 "No matching global attribute declaration available, but "
21709 "demanded by the strict wildcard");
21710 break;
21711 case XML_SCHEMAS_ATTR_UNKNOWN:
21712 if (attr->metaType)
21713 break;
21714 /*
21715 * MAYBE VAL TODO: One might report different error messages
21716 * for the following errors.
21717 */
21718 if (type->attributeWildcard == NULL) {
21719 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21720 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21721 } else {
21722 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21723 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21724 }
21725 break;
21726 default:
21727 break;
21728 }
21729 }
21730
21731 ACTIVATE_ELEM;
21732 return (0);
21733internal_error:
21734 ACTIVATE_ELEM;
21735 return (-1);
21736}
21737
21738static int
21739xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21740 int *skip)
21741{
21742 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21743 /*
21744 * The namespace of the element was already identified to be
21745 * matching the wildcard.
21746 */
21747 if ((skip == NULL) || (wild == NULL) ||
21748 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21749 VERROR_INT("xmlSchemaValidateElemWildcard",
21750 "bad arguments");
21751 return (-1);
21752 }
21753 *skip = 0;
21754 if (wild->negNsSet != NULL) {
21755 /*
21756 * URGENT VAL TODO: Fix the content model to reject
21757 * "##other" wildcards.
21758 */
21759 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21760 vctxt->inode->nsName) != 0) {
21761 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21762 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21763 /*
21764 * VAL TODO: Workaround possible *only* if minOccurs and
21765 * maxOccurs are 1.
21766 */
21767 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21768 /* VAL TODO: error code? */
21769 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21770 (xmlSchemaTypePtr) wild,
21771 "This element is not accepted by the wildcard",
21772 0, 0, NULL);
21773 vctxt->skipDepth = vctxt->depth;
21774 if ((pinode->flags &
21775 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21776 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21777 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21778 return (XML_SCHEMAV_ELEMENT_CONTENT);
21779 }
21780 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21781 *skip = 1;
21782 return (0);
21783 }
21784 vctxt->inode->typeDef =
21785 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21786 return (0);
21787 }
21788 }
21789 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21790 /*
21791 * URGENT VAL TODO: Either we need to position the stream to the
21792 * next sibling, or walk the whole subtree.
21793 */
21794 *skip = 1;
21795 return (0);
21796 }
21797 {
21798 xmlSchemaElementPtr decl = NULL;
21799
21800 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21801 vctxt->inode->localName, vctxt->inode->nsName,
21802 NULL);
21803 if (decl != NULL) {
21804 vctxt->inode->decl = decl;
21805 return (0);
21806 }
21807 }
21808 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21809 /* VAL TODO: Change to proper error code. */
21810 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21811 "No matching global element declaration available, but "
21812 "demanded by the strict wildcard");
21813 return (vctxt->err);
21814 }
21815 if (vctxt->nbAttrInfos != 0) {
21816 xmlSchemaAttrInfoPtr iattr;
21817 /*
21818 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21819 * (1.2.1.2.1) - (1.2.1.2.3 )
21820 *
21821 * Use the xsi:type attribute for the type definition.
21822 */
21823 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21824 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21825 if (iattr != NULL) {
21826 if (xmlSchemaProcessXSIType(vctxt, iattr,
21827 &(vctxt->inode->typeDef), NULL) == -1) {
21828 VERROR_INT("xmlSchemaValidateElemWildcard",
21829 "calling xmlSchemaProcessXSIType() to "
21830 "process the attribute 'xsi:nil'");
21831 return (-1);
21832 }
21833 /*
21834 * Don't return an error on purpose.
21835 */
21836 return (0);
21837 }
21838 }
21839 /*
21840 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21841 *
21842 * Fallback to "anyType".
21843 */
21844 vctxt->inode->typeDef =
21845 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21846 return (0);
21847}
21848
21849/*
21850* xmlSchemaCheckCOSValidDefault:
21851*
21852* This will be called if: not nilled, no content and a default/fixed
21853* value is provided.
21854*/
21855
21856static int
21857xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21858 const xmlChar *value,
21859 xmlSchemaValPtr *val)
21860{
21861 int ret = 0;
21862 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21863
21864 /*
21865 * cos-valid-default:
21866 * Schema Component Constraint: Element Default Valid (Immediate)
21867 * For a string to be a valid default with respect to a type
21868 * definition the appropriate case among the following must be true:
21869 */
21870 if IS_COMPLEX_TYPE(inode->typeDef) {
21871 /*
21872 * Complex type.
21873 *
21874 * SPEC (2.1) "its {content type} must be a simple type definition
21875 * or mixed."
21876 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21877 * type}'s particle must be ·emptiable· as defined by
21878 * Particle Emptiable (§3.9.6)."
21879 */
21880 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21881 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21882 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21883 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21884 /* NOTE that this covers (2.2.2) as well. */
21885 VERROR(ret, NULL,
21886 "For a string to be a valid default, the type definition "
21887 "must be a simple type or a complex type with simple content "
21888 "or mixed content and a particle emptiable");
21889 return(ret);
21890 }
21891 }
21892 /*
21893 * 1 If the type definition is a simple type definition, then the string
21894 * must be ·valid· with respect to that definition as defined by String
21895 * Valid (§3.14.4).
21896 *
21897 * AND
21898 *
21899 * 2.2.1 If the {content type} is a simple type definition, then the
21900 * string must be ·valid· with respect to that simple type definition
21901 * as defined by String Valid (§3.14.4).
21902 */
21903 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21904
21905 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21906 NULL, inode->typeDef, value, val, 1, 1, 0);
21907
21908 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21909
21910 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21911 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21912 }
21913 if (ret < 0) {
21914 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21915 "calling xmlSchemaVCheckCVCSimpleType()");
21916 }
21917 return (ret);
21918}
21919
21920static void
21921xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21922 const xmlChar * name ATTRIBUTE_UNUSED,
21923 xmlSchemaElementPtr item,
21924 xmlSchemaNodeInfoPtr inode)
21925{
21926 inode->decl = item;
21927#ifdef DEBUG_CONTENT
21928 {
21929 xmlChar *str = NULL;
21930
21931 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21932 xmlGenericError(xmlGenericErrorContext,
21933 "AUTOMATON callback for '%s' [declaration]\n",
21934 xmlSchemaFormatQName(&str,
21935 inode->localName, inode->nsName));
21936 } else {
21937 xmlGenericError(xmlGenericErrorContext,
21938 "AUTOMATON callback for '%s' [wildcard]\n",
21939 xmlSchemaFormatQName(&str,
21940 inode->localName, inode->nsName));
21941
21942 }
21943 FREE_AND_NULL(str)
21944 }
21945#endif
21946}
21947
21948static int
21949xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000021950{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021951 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
21952 if (vctxt->inode == NULL) {
21953 VERROR_INT("xmlSchemaValidatorPushElem",
21954 "calling xmlSchemaGetFreshElemInfo()");
21955 return (-1);
21956 }
21957 vctxt->nbAttrInfos = 0;
21958 return (0);
21959}
21960
21961static int
21962xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
21963 xmlSchemaNodeInfoPtr inode,
21964 xmlSchemaTypePtr type,
21965 const xmlChar *value)
21966{
21967 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
21968 return (xmlSchemaVCheckCVCSimpleType(
21969 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21970 type, value, &(inode->val), 1, 1, 0));
21971 else
21972 return (xmlSchemaVCheckCVCSimpleType(
21973 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21974 type, value, NULL, 1, 0, 0));
21975}
21976
21977
21978
21979/*
21980* Process END of element.
21981*/
21982static int
21983xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
21984{
21985 int ret = 0;
21986 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21987
21988 if (vctxt->nbAttrInfos != 0)
21989 xmlSchemaClearAttrInfos(vctxt);
21990 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
21991 /*
21992 * This element was not expected;
21993 * we will not validate child elements of broken parents.
21994 * Skip validation of all content of the parent.
21995 */
21996 vctxt->skipDepth = vctxt->depth -1;
21997 goto end_elem;
21998 }
21999 if ((inode->typeDef == NULL) ||
22000 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22001 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022002 * 1. the type definition might be missing if the element was
22003 * error prone
22004 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022005 */
22006 goto end_elem;
22007 }
22008 /*
22009 * Check the content model.
22010 */
22011 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22012 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22013
22014 /*
22015 * Workaround for "anyType".
22016 */
22017 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22018 goto character_content;
22019
22020 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22021 xmlChar *values[10];
22022 int terminal, nbval = 10, nbneg;
22023
22024 if (inode->regexCtxt == NULL) {
22025 /*
22026 * Create the regex context.
22027 */
22028 inode->regexCtxt =
22029 xmlRegNewExecCtxt(inode->typeDef->contModel,
22030 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22031 vctxt);
22032 if (inode->regexCtxt == NULL) {
22033 VERROR_INT("xmlSchemaValidatorPopElem",
22034 "failed to create a regex context");
22035 goto internal_error;
22036 }
22037#ifdef DEBUG_AUTOMATA
22038 xmlGenericError(xmlGenericErrorContext,
22039 "AUTOMATON create on '%s'\n", inode->localName);
22040#endif
22041 }
22042 /*
22043 * Get hold of the still expected content, since a further
22044 * call to xmlRegExecPushString() will loose this information.
22045 */
22046 xmlRegExecNextValues(inode->regexCtxt,
22047 &nbval, &nbneg, &values[0], &terminal);
22048 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22049 if (ret <= 0) {
22050 /*
22051 * Still missing something.
22052 */
22053 ret = 1;
22054 inode->flags |=
22055 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22056 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22057 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22058 "Missing child element(s)",
22059 nbval, nbneg, values);
22060#ifdef DEBUG_AUTOMATA
22061 xmlGenericError(xmlGenericErrorContext,
22062 "AUTOMATON missing ERROR on '%s'\n",
22063 inode->localName);
22064#endif
22065 } else {
22066 /*
22067 * Content model is satisfied.
22068 */
22069 ret = 0;
22070#ifdef DEBUG_AUTOMATA
22071 xmlGenericError(xmlGenericErrorContext,
22072 "AUTOMATON succeeded on '%s'\n",
22073 inode->localName);
22074#endif
22075 }
22076
22077 }
22078 }
22079 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22080 goto end_elem;
22081
22082character_content:
22083
22084 if (vctxt->value != NULL) {
22085 xmlSchemaFreeValue(vctxt->value);
22086 vctxt->value = NULL;
22087 }
22088 /*
22089 * Check character content.
22090 */
22091 if (inode->decl == NULL) {
22092 /*
22093 * Speedup if no declaration exists.
22094 */
22095 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22096 ret = xmlSchemaVCheckINodeDataType(vctxt,
22097 inode, inode->typeDef, inode->value);
22098 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22099 ret = xmlSchemaVCheckINodeDataType(vctxt,
22100 inode, inode->typeDef->contentTypeDef,
22101 inode->value);
22102 }
22103 if (ret < 0) {
22104 VERROR_INT("xmlSchemaValidatorPopElem",
22105 "calling xmlSchemaVCheckCVCSimpleType()");
22106 goto internal_error;
22107 }
22108 goto end_elem;
22109 }
22110 /*
22111 * cvc-elt (3.3.4) : 5
22112 * The appropriate case among the following must be true:
22113 */
22114 /*
22115 * cvc-elt (3.3.4) : 5.1
22116 * If the declaration has a {value constraint},
22117 * the item has neither element nor character [children] and
22118 * clause 3.2 has not applied, then all of the following must be true:
22119 */
22120 if ((inode->decl->value != NULL) &&
22121 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22122 (! INODE_NILLED(inode))) {
22123 /*
22124 * cvc-elt (3.3.4) : 5.1.1
22125 * If the ·actual type definition· is a ·local type definition·
22126 * then the canonical lexical representation of the {value constraint}
22127 * value must be a valid default for the ·actual type definition· as
22128 * defined in Element Default Valid (Immediate) (§3.3.6).
22129 */
22130 /*
22131 * NOTE: 'local' above means types aquired by xsi:type.
22132 * NOTE: Although the *canonical* value is stated, it is not
22133 * relevant if canonical or not. Additionally XML Schema 1.1
22134 * will removed this requirement as well.
22135 */
22136 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22137
22138 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22139 inode->decl->value, &(inode->val));
22140 if (ret != 0) {
22141 if (ret < 0) {
22142 VERROR_INT("xmlSchemaValidatorPopElem",
22143 "calling xmlSchemaCheckCOSValidDefault()");
22144 goto internal_error;
22145 }
22146 goto end_elem;
22147 }
22148 /*
22149 * Stop here, to avoid redundant validation of the value
22150 * (see following).
22151 */
22152 goto default_psvi;
22153 }
22154 /*
22155 * cvc-elt (3.3.4) : 5.1.2
22156 * The element information item with the canonical lexical
22157 * representation of the {value constraint} value used as its
22158 * ·normalized value· must be ·valid· with respect to the
22159 * ·actual type definition· as defined by Element Locally Valid (Type)
22160 * (§3.3.4).
22161 */
22162 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22163 ret = xmlSchemaVCheckINodeDataType(vctxt,
22164 inode, inode->typeDef, inode->decl->value);
22165 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22166 ret = xmlSchemaVCheckINodeDataType(vctxt,
22167 inode, inode->typeDef->contentTypeDef,
22168 inode->decl->value);
22169 }
22170 if (ret != 0) {
22171 if (ret < 0) {
22172 VERROR_INT("xmlSchemaValidatorPopElem",
22173 "calling xmlSchemaVCheckCVCSimpleType()");
22174 goto internal_error;
22175 }
22176 goto end_elem;
22177 }
22178
22179default_psvi:
22180 /*
22181 * PSVI: Create a text node on the instance element.
22182 */
22183 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22184 (inode->node != NULL)) {
22185 xmlNodePtr textChild;
22186 xmlChar *normValue;
22187 /*
22188 * VAL TODO: Normalize the value.
22189 */
22190 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22191 inode->decl->value);
22192 if (normValue != NULL) {
22193 textChild = xmlNewText(BAD_CAST normValue);
22194 xmlFree(normValue);
22195 } else
22196 textChild = xmlNewText(inode->decl->value);
22197 if (textChild == NULL) {
22198 VERROR_INT("xmlSchemaValidatorPopElem",
22199 "calling xmlNewText()");
22200 goto internal_error;
22201 } else
22202 xmlAddChild(inode->node, textChild);
22203 }
22204
22205 } else if (! INODE_NILLED(inode)) {
22206 /*
22207 * 5.2.1 The element information item must be ·valid· with respect
22208 * to the ·actual type definition· as defined by Element Locally
22209 * Valid (Type) (§3.3.4).
22210 */
22211 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22212 /*
22213 * SPEC (cvc-type) (3.1)
22214 * "If the type definition is a simple type definition, ..."
22215 * (3.1.3) "If clause 3.2 of Element Locally Valid
22216 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22217 * must be ·valid· with respect to the type definition as defined
22218 * by String Valid (§3.14.4).
22219 */
22220 ret = xmlSchemaVCheckINodeDataType(vctxt,
22221 inode, inode->typeDef, inode->value);
22222 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22223 /*
22224 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22225 * definition, then the element information item must be
22226 * ·valid· with respect to the type definition as per
22227 * Element Locally Valid (Complex Type) (§3.4.4);"
22228 *
22229 * SPEC (cvc-complex-type) (2.2)
22230 * "If the {content type} is a simple type definition, ...
22231 * the ·normalized value· of the element information item is
22232 * ·valid· with respect to that simple type definition as
22233 * defined by String Valid (§3.14.4)."
22234 */
22235 ret = xmlSchemaVCheckINodeDataType(vctxt,
22236 inode, inode->typeDef->contentTypeDef, inode->value);
22237 }
22238 if (ret != 0) {
22239 if (ret < 0) {
22240 VERROR_INT("xmlSchemaValidatorPopElem",
22241 "calling xmlSchemaVCheckCVCSimpleType()");
22242 goto internal_error;
22243 }
22244 goto end_elem;
22245 }
22246 /*
22247 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22248 * not applied, all of the following must be true:
22249 */
22250 if ((inode->decl->value != NULL) &&
22251 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22252
22253 /*
22254 * TODO: We will need a computed value, when comparison is
22255 * done on computed values.
22256 */
22257 /*
22258 * 5.2.2.1 The element information item must have no element
22259 * information item [children].
22260 */
22261 if (inode->flags &
22262 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22263 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22264 VERROR(ret, NULL,
22265 "The content must not containt element nodes since "
22266 "there is a fixed value constraint");
22267 goto end_elem;
22268 } else {
22269 /*
22270 * 5.2.2.2 The appropriate case among the following must
22271 * be true:
22272 */
22273 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22274 /*
22275 * 5.2.2.2.1 If the {content type} of the ·actual type
22276 * definition· is mixed, then the *initial value* of the
22277 * item must match the canonical lexical representation
22278 * of the {value constraint} value.
22279 *
22280 * ... the *initial value* of an element information
22281 * item is the string composed of, in order, the
22282 * [character code] of each character information item in
22283 * the [children] of that element information item.
22284 */
22285 if (! xmlStrEqual(inode->value, inode->decl->value)){
22286 /*
22287 * VAL TODO: Report invalid & expected values as well.
22288 * VAL TODO: Implement the canonical stuff.
22289 */
22290 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22291 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22292 ret, NULL, NULL,
22293 "The initial value '%s' does not match the fixed "
22294 "value constraint '%s'",
22295 inode->value, inode->decl->value);
22296 goto end_elem;
22297 }
22298 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22299 /*
22300 * 5.2.2.2.2 If the {content type} of the ·actual type
22301 * definition· is a simple type definition, then the
22302 * *actual value* of the item must match the canonical
22303 * lexical representation of the {value constraint} value.
22304 */
22305 /*
22306 * VAL TODO: *actual value* is the normalized value, impl.
22307 * this.
22308 * VAL TODO: Report invalid & expected values as well.
22309 * VAL TODO: Implement a comparison with the computed values.
22310 */
22311 if (! xmlStrEqual(inode->value,
22312 inode->decl->value)) {
22313 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22314 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22315 ret, NULL, NULL,
22316 "The actual value '%s' does not match the fixed "
22317 "value constraint '%s'",
22318 inode->value,
22319 inode->decl->value);
22320 goto end_elem;
22321 }
22322 }
22323 }
22324 }
22325 }
22326
22327end_elem:
22328 if (vctxt->depth < 0) {
22329 /* TODO: raise error? */
22330 return (0);
22331 }
22332 if (vctxt->depth == vctxt->skipDepth)
22333 vctxt->skipDepth = -1;
22334 /*
22335 * Evaluate the history of XPath state objects.
22336 */
22337 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22338 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022339 /*
22340 * TODO: 6 The element information item must be ·valid· with respect to each of
22341 * the {identity-constraint definitions} as per Identity-constraint
22342 * Satisfied (§3.11.4).
22343 */
22344 /*
22345 * Validate IDC keyrefs.
22346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022347 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22348 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022349 /*
22350 * Merge/free the IDC table.
22351 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022352 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022353#ifdef DEBUG_IDC
22354 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022355 inode->nsName,
22356 inode->localName,
22357 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022358#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022359 if (vctxt->depth > 0) {
22360 /*
22361 * Merge the IDC node table with the table of the parent node.
22362 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022363 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22364 goto internal_error;
22365 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022366 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022367 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022368 * Clear the current ielem.
22369 * VAL TODO: Don't free the PSVI IDC tables if they are
22370 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022371 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022372 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022373 /*
22374 * Skip further processing if we are on the validation root.
22375 */
22376 if (vctxt->depth == 0) {
22377 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022378 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022379 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022380 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022381 /*
22382 * Reset the bubbleDepth if needed.
22383 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022384 if (vctxt->aidcs != NULL) {
22385 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22386 do {
22387 if (aidc->bubbleDepth == vctxt->depth) {
22388 /*
22389 * A bubbleDepth of a key/unique IDC matches the current
22390 * depth, this means that we are leaving the scope of the
22391 * top-most keyref IDC.
22392 */
22393 aidc->bubbleDepth = -1;
22394 }
22395 aidc = aidc->next;
22396 } while (aidc != NULL);
22397 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022398 vctxt->depth--;
22399 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022400 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022401 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022402 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022404 return (ret);
22405
22406internal_error:
22407 vctxt->err = -1;
22408 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022409}
22410
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022411/*
22412* 3.4.4 Complex Type Definition Validation Rules
22413* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22414*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022415static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022416xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022417{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022418 xmlSchemaNodeInfoPtr pielem;
22419 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022420 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022421
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022422 if (vctxt->depth <= 0) {
22423 VERROR_INT("xmlSchemaValidateChildElem",
22424 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022425 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022426 }
22427 pielem = vctxt->elemInfos[vctxt->depth -1];
22428 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22429 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022430 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022431 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022432 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022433 if (INODE_NILLED(pielem)) {
22434 /*
22435 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22436 */
22437 ACTIVATE_PARENT_ELEM;
22438 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22439 VERROR(ret, NULL,
22440 "Neither character nor element content is allowed, "
22441 "because the element was 'nilled'");
22442 ACTIVATE_ELEM;
22443 goto unexpected_elem;
22444 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022445
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022446 ptype = pielem->typeDef;
22447
22448 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22449 /*
22450 * Workaround for "anyType": we have currently no content model
22451 * assigned for "anyType", so handle it explicitely.
22452 * "anyType" has an unbounded, lax "any" wildcard.
22453 */
22454 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22455 vctxt->inode->localName,
22456 vctxt->inode->nsName);
22457
22458 if (vctxt->inode->decl == NULL) {
22459 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022460 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022461 * Process "xsi:type".
22462 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022463 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022464 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22465 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22466 if (iattr != NULL) {
22467 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22468 &(vctxt->inode->typeDef), NULL);
22469 if (ret != 0) {
22470 if (ret == -1) {
22471 VERROR_INT("xmlSchemaValidateChildElem",
22472 "calling xmlSchemaProcessXSIType() to "
22473 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022474 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022475 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022476 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022477 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022478 } else {
22479 /*
22480 * Fallback to "anyType".
22481 *
22482 * SPEC (cvc-assess-elt)
22483 * "If the item cannot be ·strictly assessed·, [...]
22484 * an element information item's schema validity may be laxly
22485 * assessed if its ·context-determined declaration· is not
22486 * skip by ·validating· with respect to the ·ur-type
22487 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22488 */
22489 vctxt->inode->typeDef =
22490 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022491 }
22492 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022493 return (0);
22494 }
22495
22496 switch (ptype->contentType) {
22497 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022498 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022499 * SPEC (2.1) "If the {content type} is empty, then the
22500 * element information item has no character or element
22501 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022503 ACTIVATE_PARENT_ELEM
22504 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22505 VERROR(ret, NULL,
22506 "Element content is not allowed, "
22507 "because the content type is empty");
22508 ACTIVATE_ELEM
22509 goto unexpected_elem;
22510 break;
22511
22512 case XML_SCHEMA_CONTENT_MIXED:
22513 case XML_SCHEMA_CONTENT_ELEMENTS: {
22514 xmlRegExecCtxtPtr regexCtxt;
22515 xmlChar *values[10];
22516 int terminal, nbval = 10, nbneg;
22517
22518 /* VAL TODO: Optimized "anyType" validation.*/
22519
22520 if (ptype->contModel == NULL) {
22521 VERROR_INT("xmlSchemaValidateChildElem",
22522 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022523 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022524 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022525 /*
22526 * Safety belf for evaluation if the cont. model was already
22527 * examined to be invalid.
22528 */
22529 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22530 VERROR_INT("xmlSchemaValidateChildElem",
22531 "validating elem, but elem content is already invalid");
22532 return (-1);
22533 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022534
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022535 regexCtxt = pielem->regexCtxt;
22536 if (regexCtxt == NULL) {
22537 /*
22538 * Create the regex context.
22539 */
22540 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22541 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22542 vctxt);
22543 if (regexCtxt == NULL) {
22544 VERROR_INT("xmlSchemaValidateChildElem",
22545 "failed to create a regex context");
22546 return (-1);
22547 }
22548 pielem->regexCtxt = regexCtxt;
22549#ifdef DEBUG_AUTOMATA
22550 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22551 pielem->localName);
22552#endif
22553 }
22554
22555 /*
22556 * SPEC (2.4) "If the {content type} is element-only or mixed,
22557 * then the sequence of the element information item's
22558 * element information item [children], if any, taken in
22559 * order, is ·valid· with respect to the {content type}'s
22560 * particle, as defined in Element Sequence Locally Valid
22561 * (Particle) (§3.9.4)."
22562 */
22563 ret = xmlRegExecPushString2(regexCtxt,
22564 vctxt->inode->localName,
22565 vctxt->inode->nsName,
22566 vctxt->inode);
22567#ifdef DEBUG_AUTOMATA
22568 if (ret < 0)
22569 xmlGenericError(xmlGenericErrorContext,
22570 "AUTOMATON push ERROR for '%s' on '%s'\n",
22571 vctxt->inode->localName, pielem->localName);
22572 else
22573 xmlGenericError(xmlGenericErrorContext,
22574 "AUTOMATON push OK for '%s' on '%s'\n",
22575 vctxt->inode->localName, pielem->localName);
22576#endif
22577 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22578 VERROR_INT("xmlSchemaValidateChildElem",
22579 "calling xmlRegExecPushString2()");
22580 return (-1);
22581 }
22582 if (ret < 0) {
22583 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22584 &values[0], &terminal);
22585 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22586 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22587 "This element is not expected",
22588 nbval, nbneg, values);
22589 ret = vctxt->err;
22590 goto unexpected_elem;
22591 } else
22592 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022593 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022594 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022595 case XML_SCHEMA_CONTENT_SIMPLE:
22596 case XML_SCHEMA_CONTENT_BASIC:
22597 ACTIVATE_PARENT_ELEM
22598 if (IS_COMPLEX_TYPE(ptype)) {
22599 /*
22600 * SPEC (cvc-complex-type) (2.2)
22601 * "If the {content type} is a simple type definition, then
22602 * the element information item has no element information
22603 * item [children], ..."
22604 */
22605 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22606 VERROR(ret, NULL, "Element content is not allowed, "
22607 "because the content type is a simple type definition");
22608 } else {
22609 /*
22610 * SPEC (cvc-type) (3.1.2) "The element information item must
22611 * have no element information item [children]."
22612 */
22613 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22614 VERROR(ret, NULL, "Element content is not allowed, "
22615 "because the type definition is simple");
22616 }
22617 ACTIVATE_ELEM
22618 ret = vctxt->err;
22619 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022620 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022621
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022622 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022623 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022624 }
22625 return (ret);
22626unexpected_elem:
22627 /*
22628 * Pop this element and set the skipDepth to skip
22629 * all further content of the parent element.
22630 */
22631 vctxt->skipDepth = vctxt->depth;
22632 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22633 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22634 return (ret);
22635}
22636
22637#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22638#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22639#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22640
22641static int
22642xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22643 int nodeType, const xmlChar *value, int len,
22644 int mode, int *consumed)
22645{
22646 /*
22647 * Unfortunately we have to duplicate the text sometimes.
22648 * OPTIMIZE: Maybe we could skip it, if:
22649 * 1. content type is simple
22650 * 2. whitespace is "collapse"
22651 * 3. it consists of whitespace only
22652 *
22653 * Process character content.
22654 */
22655 if (consumed != NULL)
22656 *consumed = 0;
22657 if (INODE_NILLED(vctxt->inode)) {
22658 /*
22659 * SPEC cvc-elt (3.3.4 - 3.2.1)
22660 * "The element information item must have no character or
22661 * element information item [children]."
22662 */
22663 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22664 "Neither character nor element content is allowed "
22665 "because the element is 'nilled'");
22666 return (vctxt->err);
22667 }
22668 /*
22669 * SPEC (2.1) "If the {content type} is empty, then the
22670 * element information item has no character or element
22671 * information item [children]."
22672 */
22673 if (vctxt->inode->typeDef->contentType ==
22674 XML_SCHEMA_CONTENT_EMPTY) {
22675 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22676 "Character content is not allowed, "
22677 "because the content type is empty");
22678 return (vctxt->err);
22679 }
22680
22681 if (vctxt->inode->typeDef->contentType ==
22682 XML_SCHEMA_CONTENT_ELEMENTS) {
22683 if ((nodeType != XML_TEXT_NODE) ||
22684 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22685 /*
22686 * SPEC cvc-complex-type (2.3)
22687 * "If the {content type} is element-only, then the
22688 * element information item has no character information
22689 * item [children] other than those whose [character
22690 * code] is defined as a white space in [XML 1.0 (Second
22691 * Edition)]."
22692 */
22693 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22694 "Character content other than whitespace is not allowed "
22695 "because the content type is 'element-only'");
22696 return (vctxt->err);
22697 }
22698 return (0);
22699 }
22700
22701 if ((value == NULL) || (value[0] == 0))
22702 return (0);
22703 /*
22704 * Save the value.
22705 * NOTE that even if the content type is *mixed*, we need the
22706 * *initial value* for default/fixed value constraints.
22707 */
22708 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22709 ((vctxt->inode->decl == NULL) ||
22710 (vctxt->inode->decl->value == NULL)))
22711 return (0);
22712
22713 if (vctxt->inode->value == NULL) {
22714 /*
22715 * Set the value.
22716 */
22717 switch (mode) {
22718 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22719 /*
22720 * When working on a tree.
22721 */
22722 vctxt->inode->value = value;
22723 break;
22724 case XML_SCHEMA_PUSH_TEXT_CREATED:
22725 /*
22726 * When working with the reader.
22727 * The value will be freed by the element info.
22728 */
22729 vctxt->inode->value = value;
22730 if (consumed != NULL)
22731 *consumed = 1;
22732 vctxt->inode->flags |=
22733 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22734 break;
22735 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22736 /*
22737 * When working with SAX.
22738 * The value will be freed by the element info.
22739 */
22740 if (len != -1)
22741 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22742 else
22743 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22744 vctxt->inode->flags |=
22745 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22746 break;
22747 default:
22748 break;
22749 }
22750 } else {
22751 /*
22752 * Concat the value.
22753 */
22754 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022755 vctxt->inode->value = BAD_CAST xmlStrncat(
22756 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022757 } else {
22758 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022759 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022760 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22761 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022762 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022763
22764 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022765}
22766
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022767static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022768xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022769{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022770 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022771
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022772 if ((vctxt->skipDepth != -1) &&
22773 (vctxt->depth >= vctxt->skipDepth)) {
22774 VERROR_INT("xmlSchemaValidateElem",
22775 "in skip-state");
22776 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022777 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022778 if (vctxt->xsiAssemble) {
22779 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22780 goto internal_error;
22781 }
22782 if (vctxt->depth > 0) {
22783 /*
22784 * Validate this element against the content model
22785 * of the parent.
22786 */
22787 ret = xmlSchemaValidateChildElem(vctxt);
22788 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022789 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022790 VERROR_INT("xmlSchemaValidateElem",
22791 "calling xmlSchemaStreamValidateChildElement()");
22792 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022793 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022794 goto exit;
22795 }
22796 if (vctxt->depth == vctxt->skipDepth)
22797 goto exit;
22798 if ((vctxt->inode->decl == NULL) &&
22799 (vctxt->inode->typeDef == NULL)) {
22800 VERROR_INT("xmlSchemaValidateElem",
22801 "the child element was valid but neither the "
22802 "declaration nor the type was set");
22803 goto internal_error;
22804 }
22805 } else {
22806 /*
22807 * Get the declaration of the validation root.
22808 */
22809 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22810 vctxt->inode->localName,
22811 vctxt->inode->nsName);
22812 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022813 ret = XML_SCHEMAV_CVC_ELT_1;
22814 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022815 "No matching global declaration available "
22816 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022817 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022818 }
22819 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022820
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022821 if (vctxt->inode->decl == NULL)
22822 goto type_validation;
22823
22824 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22825 int skip;
22826 /*
22827 * Wildcards.
22828 */
22829 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22830 if (ret != 0) {
22831 if (ret < 0) {
22832 VERROR_INT("xmlSchemaValidateElem",
22833 "calling xmlSchemaValidateElemWildcard()");
22834 goto internal_error;
22835 }
22836 goto exit;
22837 }
22838 if (skip) {
22839 vctxt->skipDepth = vctxt->depth;
22840 goto exit;
22841 }
22842 /*
22843 * The declaration might be set by the wildcard validation,
22844 * when the processContents is "lax" or "strict".
22845 */
22846 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22847 /*
22848 * Clear the "decl" field to not confuse further processing.
22849 */
22850 vctxt->inode->decl = NULL;
22851 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022852 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022853 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022854 /*
22855 * Validate against the declaration.
22856 */
22857 ret = xmlSchemaValidateElemDecl(vctxt);
22858 if (ret != 0) {
22859 if (ret < 0) {
22860 VERROR_INT("xmlSchemaValidateElem",
22861 "calling xmlSchemaValidateElemDecl()");
22862 goto internal_error;
22863 }
22864 goto exit;
22865 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022866 /*
22867 * Validate against the type definition.
22868 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022869type_validation:
22870
22871 if (vctxt->inode->typeDef == NULL) {
22872 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22873 ret = XML_SCHEMAV_CVC_TYPE_1;
22874 VERROR(ret, NULL,
22875 "The type definition is absent");
22876 goto exit;
22877 }
22878 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22879 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22880 ret = XML_SCHEMAV_CVC_TYPE_2;
22881 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022882 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022883 goto exit;
22884 }
22885 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022886 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022887 * during validation against the declaration. This must be done
22888 * _before_ attribute validation.
22889 */
22890 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22891 if (ret == -1) {
22892 VERROR_INT("xmlSchemaValidateElem",
22893 "calling xmlSchemaXPathEvaluate()");
22894 goto internal_error;
22895 }
22896 /*
22897 * Validate attributes.
22898 */
22899 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22900 if ((vctxt->nbAttrInfos != 0) ||
22901 (vctxt->inode->typeDef->attributeUses != NULL)) {
22902
22903 ret = xmlSchemaVAttributesComplex(vctxt);
22904 }
22905 } else if (vctxt->nbAttrInfos != 0) {
22906
22907 ret = xmlSchemaVAttributesSimple(vctxt);
22908 }
22909 /*
22910 * Clear registered attributes.
22911 */
22912 if (vctxt->nbAttrInfos != 0)
22913 xmlSchemaClearAttrInfos(vctxt);
22914 if (ret == -1) {
22915 VERROR_INT("xmlSchemaValidateElem",
22916 "calling attributes validation");
22917 goto internal_error;
22918 }
22919 /*
22920 * Don't return an error if attributes are invalid on purpose.
22921 */
22922 ret = 0;
22923
22924exit:
22925 if (ret != 0)
22926 vctxt->skipDepth = vctxt->depth;
22927 return (ret);
22928internal_error:
22929 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022930}
22931
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022932#ifdef XML_SCHEMA_READER_ENABLED
22933static int
22934xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022935{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022936 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22937 int depth, nodeType, ret = 0, consumed;
22938 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022939
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022940 vctxt->depth = -1;
22941 ret = xmlTextReaderRead(vctxt->reader);
22942 /*
22943 * Move to the document element.
22944 */
22945 while (ret == 1) {
22946 nodeType = xmlTextReaderNodeType(vctxt->reader);
22947 if (nodeType == XML_ELEMENT_NODE)
22948 goto root_found;
22949 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022950 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022951 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022952
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022953root_found:
22954
22955 do {
22956 depth = xmlTextReaderDepth(vctxt->reader);
22957 nodeType = xmlTextReaderNodeType(vctxt->reader);
22958
22959 if (nodeType == XML_ELEMENT_NODE) {
22960
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022961 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022962 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
22963 VERROR_INT("xmlSchemaVReaderWalk",
22964 "calling xmlSchemaValidatorPushElem()");
22965 goto internal_error;
22966 }
22967 ielem = vctxt->inode;
22968 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
22969 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
22970 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
22971 /*
22972 * Is the element empty?
22973 */
22974 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
22975 if (ret == -1) {
22976 VERROR_INT("xmlSchemaVReaderWalk",
22977 "calling xmlTextReaderIsEmptyElement()");
22978 goto internal_error;
22979 }
22980 if (ret) {
22981 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
22982 }
22983 /*
22984 * Register attributes.
22985 */
22986 vctxt->nbAttrInfos = 0;
22987 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
22988 if (ret == -1) {
22989 VERROR_INT("xmlSchemaVReaderWalk",
22990 "calling xmlTextReaderMoveToFirstAttribute()");
22991 goto internal_error;
22992 }
22993 if (ret == 1) {
22994 do {
22995 /*
22996 * VAL TODO: How do we know that the reader works on a
22997 * node tree, to be able to pass a node here?
22998 */
22999 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23000 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23001 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23002 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23003
23004 VERROR_INT("xmlSchemaVReaderWalk",
23005 "calling xmlSchemaValidatorPushAttribute()");
23006 goto internal_error;
23007 }
23008 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23009 if (ret == -1) {
23010 VERROR_INT("xmlSchemaVReaderWalk",
23011 "calling xmlTextReaderMoveToFirstAttribute()");
23012 goto internal_error;
23013 }
23014 } while (ret == 1);
23015 /*
23016 * Back to element position.
23017 */
23018 ret = xmlTextReaderMoveToElement(vctxt->reader);
23019 if (ret == -1) {
23020 VERROR_INT("xmlSchemaVReaderWalk",
23021 "calling xmlTextReaderMoveToElement()");
23022 goto internal_error;
23023 }
23024 }
23025 /*
23026 * Validate the element.
23027 */
23028 ret= xmlSchemaValidateElem(vctxt);
23029 if (ret != 0) {
23030 if (ret == -1) {
23031 VERROR_INT("xmlSchemaVReaderWalk",
23032 "calling xmlSchemaValidateElem()");
23033 goto internal_error;
23034 }
23035 goto exit;
23036 }
23037 if (vctxt->depth == vctxt->skipDepth) {
23038 int curDepth;
23039 /*
23040 * Skip all content.
23041 */
23042 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23043 ret = xmlTextReaderRead(vctxt->reader);
23044 curDepth = xmlTextReaderDepth(vctxt->reader);
23045 while ((ret == 1) && (curDepth != depth)) {
23046 ret = xmlTextReaderRead(vctxt->reader);
23047 curDepth = xmlTextReaderDepth(vctxt->reader);
23048 }
23049 if (ret < 0) {
23050 /*
23051 * VAL TODO: A reader error occured; what to do here?
23052 */
23053 ret = 1;
23054 goto exit;
23055 }
23056 }
23057 goto leave_elem;
23058 }
23059 /*
23060 * READER VAL TODO: Is an END_ELEM really never called
23061 * if the elem is empty?
23062 */
23063 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23064 goto leave_elem;
23065 } else if (nodeType == END_ELEM) {
23066 /*
23067 * Process END of element.
23068 */
23069leave_elem:
23070 ret = xmlSchemaValidatorPopElem(vctxt);
23071 if (ret != 0) {
23072 if (ret < 0) {
23073 VERROR_INT("xmlSchemaVReaderWalk",
23074 "calling xmlSchemaValidatorPopElem()");
23075 goto internal_error;
23076 }
23077 goto exit;
23078 }
23079 if (vctxt->depth >= 0)
23080 ielem = vctxt->inode;
23081 else
23082 ielem = NULL;
23083 } else if ((nodeType == XML_TEXT_NODE) ||
23084 (nodeType == XML_CDATA_SECTION_NODE) ||
23085 (nodeType == WHTSP) ||
23086 (nodeType == SIGN_WHTSP)) {
23087 /*
23088 * Process character content.
23089 */
23090 xmlChar *value;
23091
23092 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23093 nodeType = XML_TEXT_NODE;
23094
23095 value = xmlTextReaderValue(vctxt->reader);
23096 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23097 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23098 if (! consumed)
23099 xmlFree(value);
23100 if (ret == -1) {
23101 VERROR_INT("xmlSchemaVReaderWalk",
23102 "calling xmlSchemaVPushText()");
23103 goto internal_error;
23104 }
23105 } else if ((nodeType == XML_ENTITY_NODE) ||
23106 (nodeType == XML_ENTITY_REF_NODE)) {
23107 /*
23108 * VAL TODO: What to do with entities?
23109 */
23110 TODO
23111 }
23112 /*
23113 * Read next node.
23114 */
23115 ret = xmlTextReaderRead(vctxt->reader);
23116 } while (ret == 1);
23117
23118exit:
23119 return (ret);
23120internal_error:
23121 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023122}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023123#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023124
23125/************************************************************************
23126 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023127 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023128 * *
23129 ************************************************************************/
23130
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023131#ifdef XML_SCHEMA_SAX_ENABLED
23132/*
23133* Process text content.
23134*/
23135static void
23136xmlSchemaSAXHandleText(void *ctx,
23137 const xmlChar * ch,
23138 int len)
23139{
23140 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23141
23142 if (vctxt->depth < 0)
23143 return;
23144 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23145 return;
23146 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23147 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23148 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23149 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23150 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23151 "calling xmlSchemaVPushText()");
23152 vctxt->err = -1;
23153 xmlStopParser(vctxt->parserCtxt);
23154 }
23155}
23156
23157/*
23158* Process CDATA content.
23159*/
23160static void
23161xmlSchemaSAXHandleCDataSection(void *ctx,
23162 const xmlChar * ch,
23163 int len)
23164{
23165 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23166
23167 if (vctxt->depth < 0)
23168 return;
23169 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23170 return;
23171 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23172 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23173 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23174 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23175 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23176 "calling xmlSchemaVPushText()");
23177 vctxt->err = -1;
23178 xmlStopParser(vctxt->parserCtxt);
23179 }
23180}
23181
23182static void
23183xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23184 const xmlChar * name ATTRIBUTE_UNUSED)
23185{
23186 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23187
23188 if (vctxt->depth < 0)
23189 return;
23190 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23191 return;
23192 /* SAX VAL TODO: What to do here? */
23193 TODO
23194}
23195
23196static void
23197xmlSchemaSAXHandleStartElementNs(void *ctx,
23198 const xmlChar * localname,
23199 const xmlChar * prefix ATTRIBUTE_UNUSED,
23200 const xmlChar * URI,
23201 int nb_namespaces,
23202 const xmlChar ** namespaces,
23203 int nb_attributes,
23204 int nb_defaulted ATTRIBUTE_UNUSED,
23205 const xmlChar ** attributes)
23206{
23207 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23208 int ret;
23209 xmlSchemaNodeInfoPtr ielem;
23210 int i, j;
23211
23212 /*
23213 * SAX VAL TODO: What to do with nb_defaulted?
23214 */
23215 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023216 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023217 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023218 vctxt->depth++;
23219 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023220 return;
23221 /*
23222 * Push the element.
23223 */
23224 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23225 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23226 "calling xmlSchemaValidatorPushElem()");
23227 goto internal_error;
23228 }
23229 ielem = vctxt->inode;
23230 ielem->localName = localname;
23231 ielem->nsName = URI;
23232 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23233 /*
23234 * Register namespaces on the elem info.
23235 */
23236 if (nb_namespaces != 0) {
23237 /*
23238 * Although the parser builds its own namespace list,
23239 * we have no access to it, so we'll use an own one.
23240 */
23241 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23242 /*
23243 * Store prefix and namespace name.
23244 */
23245 if (ielem->nsBindings == NULL) {
23246 ielem->nsBindings =
23247 (const xmlChar **) xmlMalloc(10 *
23248 sizeof(const xmlChar *));
23249 if (ielem->nsBindings == NULL) {
23250 xmlSchemaVErrMemory(vctxt,
23251 "allocating namespace bindings for SAX validation",
23252 NULL);
23253 goto internal_error;
23254 }
23255 ielem->nbNsBindings = 0;
23256 ielem->sizeNsBindings = 5;
23257 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23258 ielem->sizeNsBindings *= 2;
23259 ielem->nsBindings =
23260 (const xmlChar **) xmlRealloc(
23261 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023262 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023263 if (ielem->nsBindings == NULL) {
23264 xmlSchemaVErrMemory(vctxt,
23265 "re-allocating namespace bindings for SAX validation",
23266 NULL);
23267 goto internal_error;
23268 }
23269 }
23270
23271 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23272 if (namespaces[j+1][0] == 0) {
23273 /*
23274 * Handle xmlns="".
23275 */
23276 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23277 } else
23278 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23279 namespaces[j+1];
23280 ielem->nbNsBindings++;
23281 }
23282 }
23283 /*
23284 * Register attributes.
23285 * SAX VAL TODO: We are not adding namespace declaration
23286 * attributes yet.
23287 */
23288 if (nb_attributes != 0) {
23289 xmlChar *value;
23290
23291 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23292 /*
23293 * Duplicate the value.
23294 */
23295 value = xmlStrndup(attributes[j+3],
23296 attributes[j+4] - attributes[j+3]);
23297 ret = xmlSchemaValidatorPushAttribute(vctxt,
23298 NULL, attributes[j], attributes[j+2], 0,
23299 value, 1);
23300 if (ret == -1) {
23301 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23302 "calling xmlSchemaValidatorPushAttribute()");
23303 goto internal_error;
23304 }
23305 }
23306 }
23307 /*
23308 * Validate the element.
23309 */
23310 ret = xmlSchemaValidateElem(vctxt);
23311 if (ret != 0) {
23312 if (ret == -1) {
23313 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23314 "calling xmlSchemaValidateElem()");
23315 goto internal_error;
23316 }
23317 goto exit;
23318 }
23319
23320exit:
23321 return;
23322internal_error:
23323 vctxt->err = -1;
23324 xmlStopParser(vctxt->parserCtxt);
23325 return;
23326}
23327
23328static void
23329xmlSchemaSAXHandleEndElementNs(void *ctx,
23330 const xmlChar * localname ATTRIBUTE_UNUSED,
23331 const xmlChar * prefix ATTRIBUTE_UNUSED,
23332 const xmlChar * URI ATTRIBUTE_UNUSED)
23333{
23334 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23335 int res;
23336
23337 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023338 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023339 */
23340 if (vctxt->skipDepth != -1) {
23341 if (vctxt->depth > vctxt->skipDepth) {
23342 vctxt->depth--;
23343 return;
23344 } else
23345 vctxt->skipDepth = -1;
23346 }
23347 /*
23348 * SAX VAL TODO: Just a temporary check.
23349 */
23350 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23351 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23352 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23353 "elem pop mismatch");
23354 }
23355 res = xmlSchemaValidatorPopElem(vctxt);
23356 if (res != 0) {
23357 if (res < 0) {
23358 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23359 "calling xmlSchemaValidatorPopElem()");
23360 goto internal_error;
23361 }
23362 goto exit;
23363 }
23364exit:
23365 return;
23366internal_error:
23367 vctxt->err = -1;
23368 xmlStopParser(vctxt->parserCtxt);
23369 return;
23370}
23371#endif
23372
Daniel Veillard4255d502002-04-16 15:50:10 +000023373/************************************************************************
23374 * *
23375 * Validation interfaces *
23376 * *
23377 ************************************************************************/
23378
23379/**
23380 * xmlSchemaNewValidCtxt:
23381 * @schema: a precompiled XML Schemas
23382 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023383 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023384 *
23385 * Returns the validation context or NULL in case of error
23386 */
23387xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023388xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23389{
Daniel Veillard4255d502002-04-16 15:50:10 +000023390 xmlSchemaValidCtxtPtr ret;
23391
23392 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23393 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023394 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023395 return (NULL);
23396 }
23397 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023398 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23399 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023400 return (ret);
23401}
23402
23403/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023404 * xmlSchemaClearValidCtxt:
23405 * @ctxt: the schema validation context
23406 *
23407 * Free the resources associated to the schema validation context;
23408 * leaves some fields alive intended for reuse of the context.
23409 */
23410static void
23411xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23412{
23413 if (vctxt == NULL)
23414 return;
23415
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023416 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023417 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023418 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023419#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023420 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023421#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023422 if (vctxt->value != NULL) {
23423 xmlSchemaFreeValue(vctxt->value);
23424 vctxt->value = NULL;
23425 }
23426 /*
23427 * Augmented IDC information.
23428 */
23429 if (vctxt->aidcs != NULL) {
23430 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23431 do {
23432 next = cur->next;
23433 xmlFree(cur);
23434 cur = next;
23435 } while (cur != NULL);
23436 vctxt->aidcs = NULL;
23437 }
23438 if (vctxt->idcNodes != NULL) {
23439 int i;
23440 xmlSchemaPSVIIDCNodePtr item;
23441
23442 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023443 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023444 xmlFree(item->keys);
23445 xmlFree(item);
23446 }
23447 xmlFree(vctxt->idcNodes);
23448 vctxt->idcNodes = NULL;
23449 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023450 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023451 * Note that we won't delete the XPath state pool here.
23452 */
23453 if (vctxt->xpathStates != NULL) {
23454 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23455 vctxt->xpathStates = NULL;
23456 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023457 /*
23458 * Attribute info.
23459 */
23460 if (vctxt->nbAttrInfos != 0) {
23461 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023463 /*
23464 * Element info.
23465 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023466 if (vctxt->elemInfos != NULL) {
23467 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023468 xmlSchemaNodeInfoPtr ei;
23469
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023470 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023471 ei = vctxt->elemInfos[i];
23472 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023473 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023474 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023475 }
23476 }
23477}
23478
23479/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023480 * xmlSchemaFreeValidCtxt:
23481 * @ctxt: the schema validation context
23482 *
23483 * Free the resources associated to the schema validation context
23484 */
23485void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023486xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23487{
Daniel Veillard4255d502002-04-16 15:50:10 +000023488 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023489 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023490 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023491 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023492 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023493 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023494 if (ctxt->idcNodes != NULL) {
23495 int i;
23496 xmlSchemaPSVIIDCNodePtr item;
23497
23498 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023499 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023500 xmlFree(item->keys);
23501 xmlFree(item);
23502 }
23503 xmlFree(ctxt->idcNodes);
23504 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023505 if (ctxt->idcKeys != NULL) {
23506 int i;
23507 for (i = 0; i < ctxt->nbIdcKeys; i++)
23508 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23509 xmlFree(ctxt->idcKeys);
23510 }
23511
23512 if (ctxt->xpathStates != NULL)
23513 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23514 if (ctxt->xpathStatePool != NULL)
23515 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23516
23517 /*
23518 * Augmented IDC information.
23519 */
23520 if (ctxt->aidcs != NULL) {
23521 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23522 do {
23523 next = cur->next;
23524 xmlFree(cur);
23525 cur = next;
23526 } while (cur != NULL);
23527 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023528 if (ctxt->attrInfos != NULL) {
23529 int i;
23530 xmlSchemaAttrInfoPtr attr;
23531
23532 /* Just a paranoid call to the cleanup. */
23533 if (ctxt->nbAttrInfos != 0)
23534 xmlSchemaClearAttrInfos(ctxt);
23535 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23536 attr = ctxt->attrInfos[i];
23537 xmlFree(attr);
23538 }
23539 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023540 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023541 if (ctxt->elemInfos != NULL) {
23542 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023543 xmlSchemaNodeInfoPtr ei;
23544
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023545 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023546 ei = ctxt->elemInfos[i];
23547 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023548 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023549 xmlSchemaClearElemInfo(ei);
23550 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023551 }
23552 xmlFree(ctxt->elemInfos);
23553 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023554 if (ctxt->dict != NULL)
23555 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023556 xmlFree(ctxt);
23557}
23558
23559/**
23560 * xmlSchemaSetValidErrors:
23561 * @ctxt: a schema validation context
23562 * @err: the error function
23563 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023564 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023565 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023566 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023567 */
23568void
23569xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023570 xmlSchemaValidityErrorFunc err,
23571 xmlSchemaValidityWarningFunc warn, void *ctx)
23572{
Daniel Veillard4255d502002-04-16 15:50:10 +000023573 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023574 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023575 ctxt->error = err;
23576 ctxt->warning = warn;
23577 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023578 if (ctxt->pctxt != NULL)
23579 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023580}
23581
23582/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023583 * xmlSchemaGetValidErrors:
23584 * @ctxt: a XML-Schema validation context
23585 * @err: the error function result
23586 * @warn: the warning function result
23587 * @ctx: the functions context result
23588 *
23589 * Get the error and warning callback informations
23590 *
23591 * Returns -1 in case of error and 0 otherwise
23592 */
23593int
23594xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23595 xmlSchemaValidityErrorFunc * err,
23596 xmlSchemaValidityWarningFunc * warn, void **ctx)
23597{
23598 if (ctxt == NULL)
23599 return (-1);
23600 if (err != NULL)
23601 *err = ctxt->error;
23602 if (warn != NULL)
23603 *warn = ctxt->warning;
23604 if (ctx != NULL)
23605 *ctx = ctxt->userData;
23606 return (0);
23607}
23608
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023609
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023610/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023611 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023612 * @ctxt: a schema validation context
23613 * @options: a combination of xmlSchemaValidOption
23614 *
23615 * Sets the options to be used during the validation.
23616 *
23617 * Returns 0 in case of success, -1 in case of an
23618 * API error.
23619 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023620int
23621xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23622 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023623
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023624{
23625 int i;
23626
23627 if (ctxt == NULL)
23628 return (-1);
23629 /*
23630 * WARNING: Change the start value if adding to the
23631 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023632 * TODO: Is there an other, more easy to maintain,
23633 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023634 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023635 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023636 if (options & 1<<i)
23637 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023638 }
23639 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023640 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023641}
23642
23643/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023644 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023645 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023646 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023647 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023648 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023649 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023650 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023651int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023652xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023653
23654{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023655 if (ctxt == NULL)
23656 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023657 else
23658 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023659}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023660
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023661static int
23662xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23663{
23664 xmlAttrPtr attr;
23665 int ret = 0;
23666 xmlSchemaNodeInfoPtr ielem = NULL;
23667 xmlNodePtr node, valRoot;
23668 const xmlChar *nsName;
23669
23670 /* DOC VAL TODO: Move this to the start function. */
23671 valRoot = xmlDocGetRootElement(vctxt->doc);
23672 if (valRoot == NULL) {
23673 /* VAL TODO: Error code? */
23674 VERROR(1, NULL, "The document has no document element");
23675 return (1);
23676 }
23677 vctxt->depth = -1;
23678 vctxt->validationRoot = valRoot;
23679 node = valRoot;
23680 while (node != NULL) {
23681 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23682 goto next_sibling;
23683 if (node->type == XML_ELEMENT_NODE) {
23684
23685 /*
23686 * Init the node-info.
23687 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023688 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023689 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23690 goto internal_error;
23691 ielem = vctxt->inode;
23692 ielem->node = node;
23693 ielem->localName = node->name;
23694 if (node->ns != NULL)
23695 ielem->nsName = node->ns->href;
23696 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23697 /*
23698 * Register attributes.
23699 * DOC VAL TODO: We do not register namespace declaration
23700 * attributes yet.
23701 */
23702 vctxt->nbAttrInfos = 0;
23703 if (node->properties != NULL) {
23704 attr = node->properties;
23705 do {
23706 if (attr->ns != NULL)
23707 nsName = attr->ns->href;
23708 else
23709 nsName = NULL;
23710 ret = xmlSchemaValidatorPushAttribute(vctxt,
23711 (xmlNodePtr) attr,
23712 attr->name, nsName, 0,
23713 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23714 if (ret == -1) {
23715 VERROR_INT("xmlSchemaDocWalk",
23716 "calling xmlSchemaValidatorPushAttribute()");
23717 goto internal_error;
23718 }
23719 attr = attr->next;
23720 } while (attr);
23721 }
23722 /*
23723 * Validate the element.
23724 */
23725 ret = xmlSchemaValidateElem(vctxt);
23726 if (ret != 0) {
23727 if (ret == -1) {
23728 VERROR_INT("xmlSchemaDocWalk",
23729 "calling xmlSchemaValidateElem()");
23730 goto internal_error;
23731 }
23732 /*
23733 * Don't stop validation; just skip the content
23734 * of this element.
23735 */
23736 goto leave_node;
23737 }
23738 if ((vctxt->skipDepth != -1) &&
23739 (vctxt->depth >= vctxt->skipDepth))
23740 goto leave_node;
23741 } else if ((node->type == XML_TEXT_NODE) ||
23742 (node->type == XML_CDATA_SECTION_NODE)) {
23743 /*
23744 * Process character content.
23745 */
23746 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23747 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23748 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23749 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23750 if (ret < 0) {
23751 VERROR_INT("xmlSchemaVDocWalk",
23752 "calling xmlSchemaVPushText()");
23753 goto internal_error;
23754 }
23755 /*
23756 * DOC VAL TODO: Should we skip further validation of the
23757 * element content here?
23758 */
23759 } else if ((node->type == XML_ENTITY_NODE) ||
23760 (node->type == XML_ENTITY_REF_NODE)) {
23761 /*
23762 * DOC VAL TODO: What to do with entities?
23763 */
23764 TODO
23765 } else {
23766 goto leave_node;
23767 /*
23768 * DOC VAL TODO: XInclude nodes, etc.
23769 */
23770 }
23771 /*
23772 * Walk the doc.
23773 */
23774 if (node->children != NULL) {
23775 node = node->children;
23776 continue;
23777 }
23778leave_node:
23779 if (node->type == XML_ELEMENT_NODE) {
23780 /*
23781 * Leaving the scope of an element.
23782 */
23783 if (node != vctxt->inode->node) {
23784 VERROR_INT("xmlSchemaVDocWalk",
23785 "element position mismatch");
23786 goto internal_error;
23787 }
23788 ret = xmlSchemaValidatorPopElem(vctxt);
23789 if (ret != 0) {
23790 if (ret < 0) {
23791 VERROR_INT("xmlSchemaVDocWalk",
23792 "calling xmlSchemaValidatorPopElem()");
23793 goto internal_error;
23794 }
23795 }
23796 if (node == valRoot)
23797 goto exit;
23798 }
23799next_sibling:
23800 if (node->next != NULL)
23801 node = node->next;
23802 else {
23803 node = node->parent;
23804 goto leave_node;
23805 }
23806 }
23807
23808exit:
23809 return (ret);
23810internal_error:
23811 return (-1);
23812}
23813
23814static int
23815xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23816{
23817 int ret = 0;
23818
23819 /*
23820 * Some initialization.
23821 */
23822 vctxt->err = 0;
23823 vctxt->nberrors = 0;
23824 vctxt->depth = -1;
23825 vctxt->skipDepth = -1;
23826 /*
23827 * Create a schema + parser if necessary.
23828 */
23829 if (vctxt->schema == NULL) {
23830
23831 if ((vctxt->pctxt == NULL) &&
23832 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23833 return (-1);
23834
23835 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23836 if (vctxt->schema == NULL) {
23837 VERROR_INT("xmlSchemaVStartValidation",
23838 "creating a schema");
23839 return (-1);
23840 }
23841 vctxt->xsiAssemble = 1;
23842 } else
23843 vctxt->xsiAssemble = 0;
23844 /*
23845 * Augment the IDC definitions.
23846 */
23847 if (vctxt->schema->idcDef != NULL) {
23848 xmlHashScan(vctxt->schema->idcDef,
23849 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23850 }
23851 if (vctxt->doc != NULL) {
23852 /*
23853 * Tree validation.
23854 */
23855 ret = xmlSchemaVDocWalk(vctxt);
Daniel Veillard39e5c892005-07-03 22:48:50 +000023856#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023857 } else if (vctxt->reader != NULL) {
23858 /*
23859 * XML Reader validation.
23860 */
23861#ifdef XML_SCHEMA_READER_ENABLED
23862 ret = xmlSchemaVReaderWalk(vctxt);
23863#endif
Daniel Veillard39e5c892005-07-03 22:48:50 +000023864#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023865 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23866 /*
23867 * SAX validation.
23868 */
23869 /* ret = xmlSAXUserParseFile(ctxt->sax, ctxt, uri); */
23870 ret = xmlParseDocument(vctxt->parserCtxt);
23871 } else {
23872 VERROR_INT("xmlSchemaVStartValidation",
23873 "no instance to validate");
23874 ret = -1;
23875 }
23876
23877 if (vctxt->xsiAssemble) {
23878 if (vctxt->schema != NULL) {
23879 xmlSchemaFree(vctxt->schema);
23880 vctxt->schema = NULL;
23881 }
23882 }
23883 xmlSchemaClearValidCtxt(vctxt);
23884 if (ret == 0)
23885 ret = vctxt->err;
23886 return (ret);
23887}
23888
23889/**
23890 * xmlSchemaValidateOneElement:
23891 * @ctxt: a schema validation context
23892 * @elem: an element node
23893 *
23894 * Validate a branch of a tree, starting with the given @elem.
23895 *
23896 * Returns 0 if the element and its subtree is valid, a positive error
23897 * code number otherwise and -1 in case of an internal or API error.
23898 */
23899int
23900xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23901{
23902 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
23903 return (-1);
23904
23905 if (ctxt->schema == NULL)
23906 return (-1);
23907
23908 ctxt->doc = elem->doc;
23909 ctxt->node = elem;
23910 ctxt->validationRoot = elem;
23911 return(xmlSchemaVStart(ctxt));
23912}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023913
Daniel Veillard259f0df2004-08-18 09:13:18 +000023914/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023915 * xmlSchemaValidateDoc:
23916 * @ctxt: a schema validation context
23917 * @doc: a parsed document tree
23918 *
23919 * Validate a document tree in memory.
23920 *
23921 * Returns 0 if the document is schemas valid, a positive error code
23922 * number otherwise and -1 in case of internal or API error.
23923 */
23924int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023925xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23926{
Daniel Veillard4255d502002-04-16 15:50:10 +000023927 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023928 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023929
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023930 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023931 ctxt->node = xmlDocGetRootElement(doc);
23932 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023933 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023934 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23935 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023936 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023937 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023938 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023939 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023940 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023941}
23942
Daniel Veillardcdc82732005-07-08 15:04:06 +000023943
23944/************************************************************************
23945 * *
23946 * Function and data for SAX streaming API *
23947 * *
23948 ************************************************************************/
23949typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
23950typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
23951
23952struct _xmlSchemaSplitSAXData {
23953 xmlSAXHandlerPtr user_sax;
23954 void *user_data;
23955 xmlSchemaValidCtxtPtr ctxt;
23956 xmlSAXHandlerPtr schemas_sax;
23957};
23958
23959/* All those functions just bounces to the user provided SAX handlers */
23960static void
23961internalSubsetSplit(void *ctx, const xmlChar *name,
23962 const xmlChar *ExternalID, const xmlChar *SystemID)
23963{
23964 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
23965 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
23966 (ctxt->user_sax->internalSubset != NULL))
23967 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
23968 SystemID);
23969}
23970
23971static int
23972isStandaloneSplit(void *ctx)
23973{
23974 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
23975 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
23976 (ctxt->user_sax->isStandalone != NULL))
23977 return(ctxt->user_sax->isStandalone(ctxt->user_data));
23978 return(0);
23979}
23980
23981static int
23982hasInternalSubsetSplit(void *ctx)
23983{
23984 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
23985 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
23986 (ctxt->user_sax->hasInternalSubset != NULL))
23987 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
23988 return(0);
23989}
23990
23991static int
23992hasExternalSubsetSplit(void *ctx)
23993{
23994 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
23995 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
23996 (ctxt->user_sax->hasExternalSubset != NULL))
23997 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
23998 return(0);
23999}
24000
24001static void
24002externalSubsetSplit(void *ctx, const xmlChar *name,
24003 const xmlChar *ExternalID, const xmlChar *SystemID)
24004{
24005 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24006 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24007 (ctxt->user_sax->internalSubset != NULL))
24008 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24009 SystemID);
24010}
24011
24012static xmlParserInputPtr
24013resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24014{
24015 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24016 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24017 (ctxt->user_sax->resolveEntity != NULL))
24018 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24019 systemId));
24020 return(NULL);
24021}
24022
24023static xmlEntityPtr
24024getEntitySplit(void *ctx, const xmlChar *name)
24025{
24026 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24027 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24028 (ctxt->user_sax->getEntity != NULL))
24029 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24030 return(NULL);
24031}
24032
24033static xmlEntityPtr
24034getParameterEntitySplit(void *ctx, const xmlChar *name)
24035{
24036 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24037 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24038 (ctxt->user_sax->getParameterEntity != NULL))
24039 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24040 return(NULL);
24041}
24042
24043
24044static void
24045entityDeclSplit(void *ctx, const xmlChar *name, int type,
24046 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24047{
24048 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24049 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24050 (ctxt->user_sax->entityDecl != NULL))
24051 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24052 systemId, content);
24053}
24054
24055static void
24056attributeDeclSplit(void *ctx, const xmlChar * elem,
24057 const xmlChar * name, int type, int def,
24058 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24059{
24060 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24061 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24062 (ctxt->user_sax->attributeDecl != NULL)) {
24063 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24064 def, defaultValue, tree);
24065 } else {
24066 xmlFreeEnumeration(tree);
24067 }
24068}
24069
24070static void
24071elementDeclSplit(void *ctx, const xmlChar *name, int type,
24072 xmlElementContentPtr content)
24073{
24074 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24075 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24076 (ctxt->user_sax->elementDecl != NULL))
24077 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24078}
24079
24080static void
24081notationDeclSplit(void *ctx, const xmlChar *name,
24082 const xmlChar *publicId, const xmlChar *systemId)
24083{
24084 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24085 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24086 (ctxt->user_sax->notationDecl != NULL))
24087 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24088 systemId);
24089}
24090
24091static void
24092unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24093 const xmlChar *publicId, const xmlChar *systemId,
24094 const xmlChar *notationName)
24095{
24096 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24097 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24098 (ctxt->user_sax->unparsedEntityDecl != NULL))
24099 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24100 systemId, notationName);
24101}
24102
24103static void
24104setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24105{
24106 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24107 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24108 (ctxt->user_sax->setDocumentLocator != NULL))
24109 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24110}
24111
24112static void
24113startDocumentSplit(void *ctx)
24114{
24115 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24116 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24117 (ctxt->user_sax->startDocument != NULL))
24118 ctxt->user_sax->startDocument(ctxt->user_data);
24119}
24120
24121static void
24122endDocumentSplit(void *ctx)
24123{
24124 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24125 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24126 (ctxt->user_sax->endDocument != NULL))
24127 ctxt->user_sax->endDocument(ctxt->user_data);
24128}
24129
24130static void
24131processingInstructionSplit(void *ctx, const xmlChar *target,
24132 const xmlChar *data)
24133{
24134 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24135 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24136 (ctxt->user_sax->processingInstruction != NULL))
24137 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24138}
24139
24140static void
24141commentSplit(void *ctx, const xmlChar *value)
24142{
24143 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24144 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24145 (ctxt->user_sax->comment != NULL))
24146 ctxt->user_sax->comment(ctxt->user_data, value);
24147}
24148
24149/*
24150 * Varargs error callbacks to the user application, harder ...
24151 */
24152
24153static void
24154warningSplit(void *ctx, const char *msg, ...) {
24155 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24156 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24157 (ctxt->user_sax->warning != NULL)) {
24158 TODO
24159 }
24160}
24161static void
24162errorSplit(void *ctx, const char *msg, ...) {
24163 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24164 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24165 (ctxt->user_sax->error != NULL)) {
24166 TODO
24167 }
24168}
24169static void
24170fatalErrorSplit(void *ctx, const char *msg, ...) {
24171 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24172 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24173 (ctxt->user_sax->fatalError != NULL)) {
24174 TODO
24175 }
24176}
24177
24178/*
24179 * Those are function where both the user handler and the schemas handler
24180 * need to be called.
24181 */
24182static void
24183charactersSplit(void *ctx, const xmlChar *ch, int len)
24184{
24185 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24186 if (ctxt == NULL)
24187 return;
24188 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24189 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24190 if (ctxt->ctxt != NULL)
24191 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24192}
24193
24194static void
24195ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24196{
24197 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24198 if (ctxt == NULL)
24199 return;
24200 if ((ctxt->user_sax != NULL) &&
24201 (ctxt->user_sax->ignorableWhitespace != NULL))
24202 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24203 if (ctxt->ctxt != NULL)
24204 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24205}
24206
24207static void
24208cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24209{
24210 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24211 if (ctxt == NULL)
24212 return;
24213 if ((ctxt->user_sax != NULL) &&
24214 (ctxt->user_sax->ignorableWhitespace != NULL))
24215 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24216 if (ctxt->ctxt != NULL)
24217 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24218}
24219
24220static void
24221referenceSplit(void *ctx, const xmlChar *name)
24222{
24223 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24224 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24225 (ctxt->user_sax->reference != NULL))
24226 ctxt->user_sax->reference(ctxt->user_data, name);
24227 if (ctxt->ctxt != NULL)
24228 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24229}
24230
24231static void
24232startElementNsSplit(void *ctx, const xmlChar * localname,
24233 const xmlChar * prefix, const xmlChar * URI,
24234 int nb_namespaces, const xmlChar ** namespaces,
24235 int nb_attributes, int nb_defaulted,
24236 const xmlChar ** attributes) {
24237 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24238 if (ctxt == NULL)
24239 return;
24240 if ((ctxt->user_sax != NULL) &&
24241 (ctxt->user_sax->startElementNs != NULL))
24242 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24243 URI, nb_namespaces, namespaces,
24244 nb_attributes, nb_defaulted,
24245 attributes);
24246 if (ctxt->ctxt != NULL)
24247 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24248 URI, nb_namespaces, namespaces,
24249 nb_attributes, nb_defaulted,
24250 attributes);
24251}
24252
24253static void
24254endElementNsSplit(void *ctx, const xmlChar * localname,
24255 const xmlChar * prefix, const xmlChar * URI) {
24256 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24257 if (ctxt == NULL)
24258 return;
24259 if ((ctxt->user_sax != NULL) &&
24260 (ctxt->user_sax->endElementNs != NULL))
24261 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24262 if (ctxt->ctxt != NULL)
24263 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24264}
24265
Daniel Veillard4255d502002-04-16 15:50:10 +000024266/**
24267 * xmlSchemaValidateStream:
24268 * @ctxt: a schema validation context
24269 * @input: the input to use for reading the data
24270 * @enc: an optional encoding information
24271 * @sax: a SAX handler for the resulting events
24272 * @user_data: the context to provide to the SAX handler.
24273 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024274 * Validate an input based on a flow of SAX event from the parser
24275 * and forward the events to the @sax handler with the provided @user_data
24276 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024277 *
24278 * Returns 0 if the document is schemas valid, a positive error code
24279 * number otherwise and -1 in case of internal or API error.
24280 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024281int
Daniel Veillard4255d502002-04-16 15:50:10 +000024282xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024283 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24284 xmlSAXHandlerPtr sax, void *user_data)
24285{
Daniel Veillardcdc82732005-07-08 15:04:06 +000024286 xmlSchemaSplitSAXData split_block;
24287 xmlSAXHandler schemas_sax;
24288 xmlSAXHandlerPtr old_sax;
24289 xmlParserCtxtPtr pctxt;
24290 xmlParserInputPtr inputStream;
24291 int ret;
24292
Daniel Veillard4255d502002-04-16 15:50:10 +000024293 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024294 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024295
24296 memset(&schemas_sax, 0, sizeof(xmlSAXHandler));
24297 schemas_sax.initialized = XML_SAX2_MAGIC;
24298 if (sax == NULL) {
24299 /*
24300 * go direct, no need for the split block and functions.
24301 */
24302 schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24303 schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24304 /*
24305 * Note that we use the same text-function for both, to prevent
24306 * the parser from testing for ignorable whitespace.
24307 */
24308 schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24309 schemas_sax.characters = xmlSchemaSAXHandleText;
24310
24311 schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24312 schemas_sax.reference = xmlSchemaSAXHandleReference;
24313 ctxt->user_data = &split_block;
24314 } else {
24315 /*
24316 * Return -1 without parsing if passed a SAXv1 block
24317 */
24318 if (sax->initialized != XML_SAX2_MAGIC)
24319 return(-1);
24320 if ((sax->startElementNs == NULL) && (sax->endElementNs == NULL) &&
24321 ((sax->startElement != NULL) || (sax->endElement != NULL)))
24322 return(-1);
24323
24324 /*
24325 * for each callback unused by Schemas initialize it to the Split
24326 * routine only if non NULL in the user block, this can speed up
24327 * things at the SAX level.
24328 */
24329 if (sax->internalSubset != NULL)
24330 schemas_sax.internalSubset = internalSubsetSplit;
24331 if (sax->isStandalone != NULL)
24332 schemas_sax.isStandalone = isStandaloneSplit;
24333 if (sax->hasInternalSubset != NULL)
24334 schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24335 if (sax->hasExternalSubset != NULL)
24336 schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24337 if (sax->resolveEntity != NULL)
24338 schemas_sax.resolveEntity = resolveEntitySplit;
24339 if (sax->getEntity != NULL)
24340 schemas_sax.getEntity = getEntitySplit;
24341 if (sax->entityDecl != NULL)
24342 schemas_sax.entityDecl = entityDeclSplit;
24343 if (sax->notationDecl != NULL)
24344 schemas_sax.notationDecl = notationDeclSplit;
24345 if (sax->attributeDecl != NULL)
24346 schemas_sax.attributeDecl = attributeDeclSplit;
24347 if (sax->elementDecl != NULL)
24348 schemas_sax.elementDecl = elementDeclSplit;
24349 if (sax->unparsedEntityDecl != NULL)
24350 schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24351 if (sax->setDocumentLocator != NULL)
24352 schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24353 if (sax->startDocument != NULL)
24354 schemas_sax.startDocument = startDocumentSplit;
24355 if (sax->endDocument != NULL)
24356 schemas_sax.endDocument = endDocumentSplit;
24357 if (sax->processingInstruction != NULL)
24358 schemas_sax.processingInstruction = processingInstructionSplit;
24359 if (sax->comment != NULL)
24360 schemas_sax.comment = commentSplit;
24361 if (sax->warning != NULL)
24362 schemas_sax.warning = warningSplit;
24363 if (sax->error != NULL)
24364 schemas_sax.error = errorSplit;
24365 if (sax->fatalError != NULL)
24366 schemas_sax.fatalError = fatalErrorSplit;
24367 if (sax->getParameterEntity != NULL)
24368 schemas_sax.getParameterEntity = getParameterEntitySplit;
24369 if (sax->externalSubset != NULL)
24370 schemas_sax.externalSubset = externalSubsetSplit;
24371
24372 /*
24373 * the 6 schemas callback have to go to the splitter functions
24374 * Note that we use the same text-function for ignorableWhitespace
24375 * if possible, to prevent the parser from testing for ignorable
24376 * whitespace.
24377 */
24378 schemas_sax.characters = charactersSplit;
24379 if ((sax->ignorableWhitespace != NULL) &&
24380 (sax->ignorableWhitespace != sax->characters))
24381 schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24382 else
24383 schemas_sax.ignorableWhitespace = charactersSplit;
24384 schemas_sax.cdataBlock = cdataBlockSplit;
24385 schemas_sax.reference = referenceSplit;
24386 schemas_sax.startElementNs = startElementNsSplit;
24387 schemas_sax.endElementNs = endElementNsSplit;
24388 ctxt->user_data = &split_block;
24389 }
24390
24391 split_block.user_sax = sax;
24392 split_block.user_data = user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +000024393 ctxt->input = input;
24394 ctxt->enc = enc;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024395 ctxt->sax = &schemas_sax;
24396
24397 /*
24398 * prepare the parser
24399 */
24400 pctxt = xmlNewParserCtxt();
24401 if (pctxt == NULL)
24402 return (-1);
24403 old_sax = pctxt->sax;
24404 pctxt->sax = &schemas_sax;
24405#if 0
24406 if (options)
24407 xmlCtxtUseOptions(pctxt, options);
24408#endif
24409 pctxt->linenumbers = 1;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024410 pctxt->userData = (void *) ctxt;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024411
24412 inputStream = xmlNewIOInputStream(pctxt, input, XML_CHAR_ENCODING_NONE);;
24413 if (inputStream == NULL) {
24414 ret = -1;
24415 goto done;
24416 }
24417 inputPush(pctxt, inputStream);
24418 ctxt->parserCtxt = pctxt;
24419 ctxt->input = input;
24420
24421 /*
24422 * Launch the validation
24423 */
24424 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24425 ret = xmlSchemaVStart(ctxt);
24426
24427 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24428 ret = ctxt->parserCtxt->errNo;
24429 if (ret == 0)
24430 ret = 1;
24431 }
24432 ctxt->parserCtxt = NULL;
24433 ctxt->sax = NULL;
24434 ctxt->user_data = NULL;
24435 ctxt->input = NULL;
24436
24437done:
24438 /* cleanup */
24439 pctxt->sax = old_sax;
24440 xmlFreeParserCtxt(pctxt);
24441 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024442}
24443
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024444/**
24445 * xmlSchemaValidateFile:
24446 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024447 * @filename: the URI of the instance
24448 * @options: a future set of options, currently unused
24449 *
24450 * Do a schemas validation of the given resource, it will use the
24451 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024452 *
24453 * Returns 0 if the document is valid, a positive error code
24454 * number otherwise and -1 in case of an internal or API error.
24455 */
24456int
24457xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024458 const char * filename,
24459 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024460{
Daniel Veillard81562d22005-06-15 13:27:56 +000024461#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024462 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024463 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024464
24465 if ((ctxt == NULL) || (filename == NULL))
24466 return (-1);
24467
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024468 input = xmlParserInputBufferCreateFilename(filename,
24469 XML_CHAR_ENCODING_NONE);
24470 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024471 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024472 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24473 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024474 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024475#else
24476 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024477#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024478}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024479
24480#ifdef XML_SCHEMA_READER_ENABLED
Daniel Veillard81562d22005-06-15 13:27:56 +000024481/**
24482 * xmlSchemaValidateReader:
24483 * @ctxt: a schema validation context
24484 * @reader: an XML reader.
24485 *
24486 * Do a schemas validation of the given resource, using the reader.
24487 *
24488 * Returns 0 if the document is valid, a positive error code
24489 * number otherwise and -1 in case of an internal or API error.
24490 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024491int
24492xmlSchemaValidateReader(xmlSchemaValidCtxtPtr ctxt,
24493 xmlTextReaderPtr reader)
24494{
24495 if ((ctxt == NULL) || (reader == NULL))
24496 return (-1);
24497 ctxt->reader = reader;
24498 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24499 return(xmlSchemaVStart(ctxt, NULL));
24500}
24501#endif /* XML_SCHEMA_READER_ENABLED */
24502
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024503#define bottom_xmlschemas
24504#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024505#endif /* LIBXML_SCHEMAS_ENABLED */